/* Copyright Statement:
 *
 * This software/firmware and related documentation ("AutoChips Software") are
 * protected under relevant copyright laws. The information contained herein is
 * confidential and proprietary to AutoChips Inc. and/or its licensors. Without
 * the prior written permission of AutoChips inc. and/or its licensors, any
 * reproduction, modification, use or disclosure of AutoChips Software, and
 * information contained herein, in whole or in part, shall be strictly
 * prohibited.
 *
 * AutoChips Inc. (C) 2022. All rights reserved.
 *
 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("AUTOCHIPS SOFTWARE")
 * RECEIVED FROM AUTOCHIPS AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
 * ON AN "AS-IS" BASIS ONLY. AUTOCHIPS EXPRESSLY DISCLAIMS ANY AND ALL
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NONINFRINGEMENT. NEITHER DOES AUTOCHIPS PROVIDE ANY WARRANTY WHATSOEVER WITH
 * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
 * INCORPORATED IN, OR SUPPLIED WITH THE AUTOCHIPS SOFTWARE, AND RECEIVER AGREES
 * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
 * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
 * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN AUTOCHIPS
 * SOFTWARE. AUTOCHIPS SHALL ALSO NOT BE RESPONSIBLE FOR ANY AUTOCHIPS SOFTWARE
 * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND AUTOCHIPS'S
 * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE AUTOCHIPS SOFTWARE
 * RELEASED HEREUNDER WILL BE, AT AUTOCHIPS'S OPTION, TO REVISE OR REPLACE THE
 * AUTOCHIPS SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
 * CHARGE PAID BY RECEIVER TO AUTOCHIPS FOR SUCH AUTOCHIPS SOFTWARE AT ISSUE.
 */
 
 /******************************************************************************
 * @version: V1.0.0  demo
 ******************************************************************************/
 
/*!
 * @file timer_capture_pwm.c
 *
 * @brief 定时器捕捉PWM配置源文件
 *
 */

/* ===========================================  Includes  =========================================== */
#include "string.h"
#include "ac780x_timer.h"
#include "ac780x_timer_reg.h"
#include "ac780x_gpio.h" 
#include "ac780x_pwm.h"  
#include "timer_capture_pwm.h"

/* ============================================  Define  ============================================ */
#define APB_CLK         (APB_BUS_FREQ)                     /*! APB时钟定义 */
#define FREQ            (1000)                             /*! 频率为1k */
#define PWM_PRES        (0)                                /*! PWM预分频 */
#define MOD_PWM         (APB_CLK / FREQ / (PWM_PRES + 1))  /*! PWM模值 */

/* ===========================================  Typedef  ============================================ */


/* ==========================================  Variables  =========================================== */
uint32_t g_pwm_DownMomentOne = 0;           /* PWM波第一次出现下降沿 */
uint32_t g_pwm_DownMomentTwo = 0;           /* PWM波第二次出现下降沿 */
uint32_t g_pwm_UpMoment = 0;                /* PWM波上升沿降沿 */
uint32_t g_pwm_Period = 0;                  /* PWM频率 */
uint32_t g_pwm_Duty = 0;                    /* PWM占空比 */

/* ====================================  Functions declaration  ===================================== */


/* ======================================  Functions define  ======================================== */

/*!
*
* @brief 初始化TIMER0,产生100s计时
*
* @param[in] none
* @return none
*/
void Timer0_Init(void)
{
    TIMER_ConfigType  timerConfig0;
    
    memset(&timerConfig0, 0, sizeof(timerConfig0));
    
    /* TIMER0配置函数 */
    timerConfig0.periodValue = DelayS(100);                  /*! 100s计时 */
    timerConfig0.interruptEn = DISABLE;                      /*! 禁能定时器中断 */
    timerConfig0.linkModeEn = DISABLE;                       /*! 禁能链接模式 */
    timerConfig0.timerEn = DISABLE;                          /*! 先关掉定时器，在PWM第一个下降沿开，第二个下降沿关闭，以使得计时时间更精确，具体位置在GPIO中断处理函数中 */
    timerConfig0.callBack = NULL;                            /*! 回调函数为空 */

    TIMER_Init(TIMER_CHANNEL0, &timerConfig0);               /*! TIMER初始化函数生效 */
    mdelay(10);                                              /*! 防止在定时器溢出后产生误差 */ 
}

/**
*
* @brief GPIO中断处理函数
* 
* @param  device：
* GPIOx: GPIO type structure pointer:
*   -GPIOA
*   -GPIOB
* wpara：
* GPIO_Pin: GPIO_Pin type num:
*   -GPIO_PIN0
*   -GPIO_PIN1
*   -GPIO_PIN2
*   - ...
*   -GPIO_PIN15
* lpara：0
* 	@return none
*
*/
void PWM_Capture_ByTimer(void *device, uint32_t wpara, uint32_t lpara)
{
    static uint8_t pwm_EdgCount = 0;
    
    if(pwm_EdgCount  == 0)
    {
        TIMER_SetChannel(TIMER_CHANNEL0, ENABLE);                                     /*! 此处打开定时器 */
        if (GPIO_GetPinLevel(GPIOA,GPIO_PIN1) == 0)                                   /*! PWM下降沿 */
        {
            g_pwm_DownMomentOne = TIMER_GetCurrentValue(TIMER_CHANNEL0);
            pwm_EdgCount = 1;
        }
    }
    else if(pwm_EdgCount  == 1)
    {
        if (GPIO_GetPinLevel(GPIOA,GPIO_PIN1) == 1)                                  /*! PWM上升沿 */
        {
            g_pwm_UpMoment = TIMER_GetCurrentValue(TIMER_CHANNEL0);
            pwm_EdgCount = 2;
        }
    }
    else if(pwm_EdgCount  == 2)
    {
        if(GPIO_GetPinLevel(GPIOA,GPIO_PIN1) == 0)                                   /*! PWM下降沿 */
        {
           TIMER_SetChannel(TIMER_CHANNEL0, DISABLE);                                /*!此处关闭定时器 */
           g_pwm_DownMomentTwo = TIMER_GetCurrentValue(TIMER_CHANNEL0);	
            pwm_EdgCount = 0;
        }
    }
    
    if((g_pwm_UpMoment < g_pwm_DownMomentOne)&&(g_pwm_DownMomentTwo < g_pwm_UpMoment))                                 /*! Timer为向下计数 */
    {
        g_pwm_Period = (g_pwm_DownMomentOne - g_pwm_DownMomentTwo)/16;                                                 /*! 16个计数为1us */
        g_pwm_Duty = (100 * (g_pwm_UpMoment - g_pwm_DownMomentTwo))/(g_pwm_DownMomentOne - g_pwm_DownMomentTwo);
    }
}

/*!
* @brief  初始化PWM捕获GPIO
*
* @param[in] none
* @return none
*/
void Capture_Gpio_Init(void)
{   
    GPIO_SetFunc(GPIOA,GPIO_PIN1,GPIO_FUN0);                                /*! PA1引脚配置为GPIO模式，用于采集端口 */
    
    GPIO_SetDir(GPIOA,GPIO_PIN1,GPIO_IN);                                   /*! PA1引脚配置为输入模式，用于采集端口 */
    
    GPIO_EnableExtInterrupt(GPIOA,GPIO_PIN1, EXTI_TRIGGER_RISING_FALLING);  /*! 使能外部中断,上升沿下降沿都中断 */
    
    GPIO_SetCallback(GPIO_PIN1, PWM_Capture_ByTimer);                       /*! 设置中断回调函数 */
}

/**
*
* @brief PA2，PWM2_CH1,PMW输出频率为1K，占空比为25%
*
* @param[in] none
* @return    none
*/
void PWM_Generate(void)
{
    GPIO_SetFunc(GPIOA, GPIO_PIN2, GPIO_FUN1);                             /*! PWM2_CH0 */

    PWM_IndependentChConfig independentChConfig[1];                        /*! 独立模式相关结构体 */
    PWM_ModulationConfigType pwmConfig;                                    /*! PWM模式相关结构体 */
    PWM_ConfigType config;                                                 /*! PWM模块结构体 */
    
    memset(&independentChConfig, 0, sizeof(independentChConfig));
    memset(&pwmConfig, 0, sizeof(pwmConfig));
    memset(&config, 0, sizeof(config));
 
    independentChConfig[0].channel = PWM_CH_1;                             /*! 通道1 */
    independentChConfig[0].chValue = MOD_PWM >> 2;                         /*! 通道1 channel值，输出占空比 = chValue / maxValue = 25%  */
    independentChConfig[0].levelMode = PWM_HIGH_TRUE;                      /*! 输出PWM高有效 */
    independentChConfig[0].polarity = PWM_OUTPUT_POLARITY_ACTIVE_HIGH;     /*! 输出极性高有效，PWM mask后PWM输出低电平 */
    independentChConfig[0].interruptEn = DISABLE;                          /*! PWM通道匹配中断使能位 */
    independentChConfig[0].initLevel = PWM_LOW_LEVEL;                      /*! PWM初始电平输出为低，该配置受initChOutputEn控制，决定PWM计数器未工作前PWM口的输出电平值 */
    independentChConfig[0].triggerEn = DISABLE;                            /*! 通道外部触发使能 */
    
    /*! modulation mode config */
    pwmConfig.countMode = PWM_UP_COUNT;                                    /*! PWM计数器模式 (不同的计数模式频率及占空比计算方式不同) */
    pwmConfig.independentChannelNum = 1;                                   /*! 独立通道数 */
    pwmConfig.combineChannelNum = 0;                                       /*! 组合对数 */
    pwmConfig.independentChConfig = independentChConfig;                   /*! 独立通道配置变量地址赋值 */
    pwmConfig.initChOutputEn = ENABLE;                                     /*! 使能初始化通道输出 */
    pwmConfig.initTriggerEn = DISABLE;                                     /*! 通道外部触发使能 */
    
    /*! pwm config */
    config.mode = PWM_MODE_MODULATION;                                     /*! PWM模块配置为PWM模式 */
    config.initModeStruct = &pwmConfig;                                    /*! PWM配置结构体地址赋值 */
    config.clkSource = PWM_CLK_SOURCE_APB;                                 /*! PWM时钟源配置 */
    config.clkPsc = PWM_PRES;                                              /*! PWM时钟源分频 */
    config.initValue = 0;                                                  /*! 计数器初始寄存器值 */
    config.maxValue = MOD_PWM - 1;                                         /*! PWM计数器最大值 */
    config.overflowInterrupEn = DISABLE;                                   /*! 计数器溢出中断禁能 */
    config.cntOverflowFreq = 0;                                            /*! CNTOF中断产生的频率与计数器频率的关系(0-127), 0表示每次计数器溢出都产生溢出中断，1表示间隔1次，2表示间隔2次，以此类推 */
    config.interruptEn = DISABLE;                                          /*! PWM中断使能 */
    
    PWM_Init(PWM2, &config);                                               /*! 配置初始化生效 */
}

/*!
* @brief      PWM捕捉函数
*
* @param[in]  none
* @return     none
*/

void TIMER_PWM_Capture(void)
{
    Capture_Gpio_Init();                                                   /*! 初始化PWM捕获GPIO */
    Timer0_Init();                                                         /*! 定时器配置函数 */
    PWM_Generate();                                                        /*! PWM输出函数 */
}
