/***********************************************************************
 * Filename    : app.c
 * Description : app source file
 * Author(s)   : xwl  
 * version     : V1.0
 * Modify date : 2020-04-07  
 ***********************************************************************/
#include  "app.h"



TIM_HandleTypeDef TIM1_Handler;  
       
volatile uint16_t Capture_1, Capture_2;     

#define READ_CAPTURE_DATA_BY_INTERRUPT      
#define CHANNEL_NUMBER  2  
#define CAPTURE_TIMES   4         
volatile uint16_t Capture_data[CHANNEL_NUMBER][CAPTURE_TIMES];      
volatile uint32_t capture_times;  

extern void TIM1_MSP_Pre_Init(TIM_HandleTypeDef * htim); 
extern void TIM1_MSP_Post_Init(void);  

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{   
    if (HAL_TIM_ACTIVE_CHANNEL_1 == htim->activeChannel)
    {
        Capture_data[0][capture_times] = HAL_TIMER_ReadCapturedValue(htim, TIM_CHANNEL_1); 
        capture_times++;  
        if (capture_times >= CAPTURE_TIMES)
        {
            HAL_TIM_DISABLE_IT(&TIM1_Handler, TIM_IT_CC1);   
            HAL_TIM_Capture_Stop(TIM1_Handler.Instance, TIM_CHANNEL_1);    
        }
    }
    
    if (HAL_TIM_ACTIVE_CHANNEL_2 == htim->activeChannel)
    {
        Capture_data[1][capture_times] = HAL_TIMER_ReadCapturedValue(htim, TIM_CHANNEL_2);     
        capture_times++;    
        if (capture_times >= CAPTURE_TIMES)
        {
            HAL_TIM_DISABLE_IT(&TIM1_Handler, TIM_IT_CC2);   
            HAL_TIM_Capture_Stop(TIM1_Handler.Instance, TIM_CHANNEL_2);    
        }
    }
       
  
    NVIC_ClearPendingIRQ(TIM1_CC_IRQn);    
}  

/**********************************************************************************************
* Function    : TIM1_IC1_Init      
* Description : timer capture by channel 1 initiation, includes clock, gpio, capture channel.  
* Input       : none    
* Output      : none 
* Author      : xwl                       
******************************************************************************************************/  
void TIM1_IC1_Init(void)  
{
	TIM_IC_InitTypeDef Tim_IC_Init_Para;     
	
	TIM1_Handler.Instance = TIM1;
	TIM1_Handler.Init.ARRPreLoadEn = TIM_ARR_PRELOAD_ENABLE;       
	TIM1_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; 
	TIM1_Handler.Init.CounterMode = TIM_COUNTERMODE_UP; 
	TIM1_Handler.Init.RepetitionCounter = 0;  
	TIM1_Handler.Init.Prescaler = 0;  
	TIM1_Handler.Init.Period = 0xFFFF;     // max period 
	
	TIM1_MSP_Pre_Init(&TIM1_Handler);         
	HAL_TIMER_Base_Init(&TIM1_Handler);       
	    
	Tim_IC_Init_Para.TIFilter = TIM_TI1_FILTER_LVL(0);    // no filter    
	Tim_IC_Init_Para.ICPolarity = TIM_SLAVE_CAPTURE_ACTIVE_FALLING;         
	Tim_IC_Init_Para.ICPrescaler = TIM_IC1_PRESCALER_1; 
	Tim_IC_Init_Para.ICSelection = TIM_ICSELECTION_DIRECTTI;     // TI1FP1 	 
	HAL_TIMER_Capture_Config(TIM1_Handler.Instance, &Tim_IC_Init_Para,  TIM_CHANNEL_1);     
	    
	TIM1_MSP_Post_Init();   
		 
} 

/**********************************************************************************************
* Function    : TIM1_IC1_Capture      
* Description : start timer capture by channel 1
* Input       : none    
* Output      : none 
* Author      : xwl                       
******************************************************************************************************/  
void TIM1_IC1_Capture(void)     
{
    uint16_t i, delta;    
    
    i = 0;        
    HAL_TIMER_Clear_Capture_Flag(&TIM1_Handler, TIM_CHANNEL_1);   
    HAL_TIM_Capture_Start(TIM1_Handler.Instance, TIM_CHANNEL_1);   
    while(1)  
	{
	
        while (0 == (TIM1->SR & TIMER_SR_CC1IF)  );     		
		Capture_1 = TIM1->CCR1; 
        HAL_TIMER_Clear_Capture_Flag(&TIM1_Handler, TIM_CHANNEL_1);   
            
        while (0 == (TIM1->SR & TIMER_SR_CC1IF)  );       		
        Capture_2 = TIM1->CCR1; 
        delta = Capture_2-Capture_1;  
        printfS("IC1 capture test, Capture_1:%d, Capture_2:%d, Delta:%u\n", Capture_1, Capture_2, delta);                 
        HAL_Delay(500+i);  // delay different period   
        i++;
        if (i > 1500) 
        {
            i = 0; 
        }
        HAL_TIMER_Clear_Capture_Flag(&TIM1_Handler, TIM_CHANNEL_1);         		
	}
}

/**********************************************************************************************
* Function    : TIM1_IC1_Capture      
* Description : start timer capture by channel 1, read data in interrupt servic 
* Input       : none    
* Output      : none 
* Author      : xwl                       
******************************************************************************************************/  
void TIM1_IC1_Capture_IT(void)     
{
    uint16_t delta[CAPTURE_TIMES-1];         
    uint32_t i;     
    
    capture_times = 0;        
    for(i = 0; i < (CAPTURE_TIMES-1); i++)  
    {
        delta[i] = 0;    
    }      
    
    HAL_TIMER_Clear_Capture_Flag(&TIM1_Handler, TIM_CHANNEL_1);  
    NVIC_ClearPendingIRQ(TIM1_CC_IRQn);     
    NVIC_EnableIRQ(TIM1_CC_IRQn);       
    HAL_TIM_ENABLE_IT(&TIM1_Handler, TIM_IT_CC1);    
    HAL_TIM_Capture_Start(TIM1_Handler.Instance, TIM_CHANNEL_1);     
    
    while(1)
	{
	
        if (capture_times >= CAPTURE_TIMES)  
        {
            
            
            for(i = 0; i < (CAPTURE_TIMES-1); i++)  
            {
               delta[i] = Capture_data[TIM_CHANNEL_1][i+1] - Capture_data[TIM_CHANNEL_1][i];    
            }
            for(i = 0; i < (CAPTURE_TIMES-1); i++)  
            {
                 printfS("IC1 capture test, i=%d, Delta[i]:%u\n", i, delta[i]);            
            }
            
            HAL_TIMER_Clear_Capture_Flag(&TIM1_Handler, TIM_CHANNEL_1);   
            break;   
        }            		
	}
}  

/****************************************************************************************************
* Function    : TIM1_IC2_Init      
* Description : timer capture by channel 2 initiation, includes clock, gpio, capture channel.    
* Input       : none    
* Output      : none 
* Author      : xwl                       
******************************************************************************************************/ 
void TIM1_IC2_Init(void)  
{ 
	TIM_IC_InitTypeDef Tim_IC_Init_Para;     
	
	TIM1_Handler.Instance = TIM1;
	TIM1_Handler.Init.ARRPreLoadEn = TIM_ARR_PRELOAD_ENABLE;       
	TIM1_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; 
	TIM1_Handler.Init.CounterMode = TIM_COUNTERMODE_UP; 
	TIM1_Handler.Init.RepetitionCounter = 0;  
	TIM1_Handler.Init.Prescaler = 0;  
	TIM1_Handler.Init.Period = 0xFFFF;     // max period 
	
	TIM1_MSP_Pre_Init(&TIM1_Handler);         
	HAL_TIMER_Base_Init(&TIM1_Handler);       
	    
	Tim_IC_Init_Para.TIFilter = TIM_TI1_FILTER_LVL(0);    // filter configuration     
	Tim_IC_Init_Para.ICPolarity = TIM_SLAVE_CAPTURE_ACTIVE_FALLING;         
	Tim_IC_Init_Para.ICPrescaler = TIM_IC2_PRESCALER_1; 
	Tim_IC_Init_Para.ICSelection = TIM_ICSELECTION_INDIRECTTI;     // TI1FP2->IC2, it is indirect way  	 
	HAL_TIMER_Capture_Config(TIM1_Handler.Instance, &Tim_IC_Init_Para,  TIM_CHANNEL_2);     
	   	 
	TIM1_MSP_Post_Init();   
	      
} 

/**********************************************************************************************
* Function    : TIM1_IC2_Capture      
* Description : start timer capture by channel 2  
* Input       : none    
* Output      : none 
* Author      : xwl                       
******************************************************************************************************/ 
void TIM1_IC2_Capture(void)     
{
    uint16_t i, delta;   
    
    i = 0;  
    
    HAL_TIMER_Clear_Capture_Flag(&TIM1_Handler, TIM_CHANNEL_2);    
    HAL_TIM_Capture_Start(TIM1_Handler.Instance, TIM_CHANNEL_2);   
    while(1)  
	{
	
        while (0 == (TIM1->SR & TIMER_SR_CC2IF)  );     		
		Capture_1 = TIM1->CCR2; 
        HAL_TIMER_Clear_Capture_Flag(&TIM1_Handler, TIM_CHANNEL_2);      
            
        while (0 == (TIM1->SR & TIMER_SR_CC2IF)  );     		
        Capture_2 = TIM1->CCR2; 
        
        delta = Capture_2-Capture_1;  
        printfS("IC2 Capture test, Capture_1:%d, Capture_2:%d, Delta:%u\n", Capture_1, Capture_2, delta);                 
        HAL_Delay(500+i);  // delay different period   
        i++;
        if (i > 1500) 
        {
            i = 0; 
        }
        HAL_TIMER_Clear_Capture_Flag(&TIM1_Handler, TIM_CHANNEL_2);       		
	}
}  

/**********************************************************************************************
* Function    : TIM1_IC2_Capture      
* Description : start timer capture by channel 2, read data in interrupt servic 
* Input       : none    
* Output      : none 
* Author      : xwl                       
******************************************************************************************************/  
void TIM1_IC2_Capture_IT(void)     
{
    uint16_t delta[CAPTURE_TIMES-1];         
    uint32_t i;     
    
    capture_times = 0;        
    for(i = 0; i < (CAPTURE_TIMES-1); i++)  
    {
        delta[i] = 0;    
    }      
    
    HAL_TIMER_Clear_Capture_Flag(&TIM1_Handler, TIM_CHANNEL_2);  
    NVIC_ClearPendingIRQ(TIM1_CC_IRQn);     
    NVIC_EnableIRQ(TIM1_CC_IRQn);       
    HAL_TIM_ENABLE_IT(&TIM1_Handler, TIM_IT_CC2);    
    HAL_TIM_Capture_Start(TIM1_Handler.Instance, TIM_CHANNEL_2);     
    
    while(1)
	{
	
        if (capture_times >= CAPTURE_TIMES)  
        {
            HAL_TIM_DISABLE_IT(&TIM1_Handler, TIM_IT_CC2);   
            HAL_TIM_Capture_Stop(TIM1_Handler.Instance, TIM_CHANNEL_2);    
            
            for(i = 0; i < (CAPTURE_TIMES-1); i++)  
            {
               delta[i] = Capture_data[TIM_CHANNEL_2][i+1] - Capture_data[TIM_CHANNEL_2][i];    
            }
            for(i = 0; i < (CAPTURE_TIMES-1); i++)  
            {
                 printfS("IC2 capture test, i=%d, Delta[i]:%u\n", i, delta[i]);            
            }
            
            HAL_TIMER_Clear_Capture_Flag(&TIM1_Handler, TIM_CHANNEL_2);   
            break;   
        }            		
	}
}  

#define BUZZER_OUTPUT_FREQ  100000  // 100K   
 /*********************************************************************************
* Function    : System_Set_Buzzer_Divider
* Description : set buzzer divide factor 
* Input       : 
              div: div factor, if div = 80 then output buzzer freq=HCLK/80   
              enable: FUNC_DISABLE and FUNC_ENABLE      
* Output      : none
* Author      : xwl                         Date : 2021?¡§o
**********************************************************************************/
void Set_Buzzer_Divider(uint32_t div, uint8_t enable)  
{      
    if (1 == enable)
    {
        RCC->CLKOCR = (RCC->CLKOCR & (~(0x1FFFFU << 5) ) ) | (div << 5);      
        RCC->CLKOCR |= BIT23;  
    }
    else
    {
        RCC->CLKOCR &= (~BIT23);   
    }
}

/**********************************************************************************************
* Function    : Timer_Capture_Test      
* Description : capture test entry
* Input       : capture_channel: CAPTURE_CHANNEL_1, CAPTURE_CHANNEL_2        
* Output      : none 
* Author      : xwl                       
******************************************************************************************************/  
void Timer_Capture_Test(uint32_t capture_channel)    
{
    uint32_t timer_clock;    
    
    Set_Buzzer_Divider( (HAL_RCC_GetHCLKFreq()/BUZZER_OUTPUT_FREQ) - 1, 1);    
    
    timer_clock = HAL_RCC_GetPCLK2Freq(); // TIM1 is on APB2    
    
    if (HAL_RCC_GetHCLKFreq() != timer_clock)  // if hclk/pclk != 1, then timer clk = pclk * 2  
    {
       timer_clock =  timer_clock << 1;    
    }  
    
	switch(capture_channel)
    {
        case CAPTURE_CHANNEL_1:  
        TIM1_IC1_Init();   
#ifndef READ_CAPTURE_DATA_BY_INTERRUPT           
        TIM1_IC1_Capture();      
#else  
        TIM1_IC1_Capture_IT();         
#endif            
        break;  
        
        case CAPTURE_CHANNEL_2:  
        TIM1_IC2_Init();   
#ifndef READ_CAPTURE_DATA_BY_INTERRUPT          
        TIM1_IC2_Capture();  
#else  
        TIM1_IC2_Capture_IT();     
#endif     
        break;  
        
        default: 
        printfS("Application not supported \n");   
        break;  
    }

}

