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


TIM_HandleTypeDef TIM16_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;  



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(htim, TIM_IT_CC1);   
            HAL_TIM_Capture_Stop(htim->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(htim, TIM_IT_CC2);   
            HAL_TIM_Capture_Stop(htim->Instance, TIM_CHANNEL_2);    
        }
    }
       
  
    NVIC_ClearPendingIRQ(TIM16_IRQn);     
}  



void TIM16_MSP_Post_Init(void)     
{
	
}  


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

    TIM16_MSP_Post_Init();    
    TIM16_Handler.Instance->TISEL = 4;  //Select RC32K as input capture signal 
} 

 
/**********************************************************************************************
* Function    : TIM1_IC1_Capture      
* Description : start timer capture by channel 1, read data in interrupt servic 
* Input       : none    
* Output      : none 
* Author      : xwl                       
******************************************************************************************************/  
void TIM16_IC1_Capture_IT(void)     
{   
    uint16_t delta[CAPTURE_TIMES-1];         
    uint32_t i, j;   
    
    capture_times = 0;        
    for(i = 0; i < (CAPTURE_TIMES-1); i++)  
    {
        delta[i] = 0;    
    }      
    
    printfS("TISEL:0x%08x\n", TIM16_Handler.Instance->TISEL);  
        
    HAL_TIMER_Clear_Capture_Flag(&TIM16_Handler, TIM_CHANNEL_1);  
    NVIC_ClearPendingIRQ(TIM16_IRQn);     
    NVIC_EnableIRQ(TIM16_IRQn);       
    HAL_TIM_ENABLE_IT(&TIM16_Handler, TIM_IT_CC1);    
    HAL_TIM_Capture_Start(TIM16_Handler.Instance, TIM_CHANNEL_1);     
    
    j = 0; 
    
    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, Delta[%d]:%u\n", i, delta[i]);      
                 if( (delta[i] > 4000) || (delta[i] < 3000) )      
                 {
                    printfS("Capture ERR, %u\n", delta[i]);       
                    for(i = 0; i < (CAPTURE_TIMES); i++)  
                    {
                        printfS("IC1 capture test, Capture[%d]:%u\n", i, Capture_data[TIM_CHANNEL_1][i] );  
                    }
                    while(1);  
                 }                 
            }
            
            for(i = 0; i < (CAPTURE_TIMES); i++)  
            {
                 printfS("IC1 capture test, Capture[%d]:%u\n", i, Capture_data[TIM_CHANNEL_1][i] );     
            }
            
            HAL_Delay(500+j);  // delay different period   
            j++;
            if (j > 1500) 
            {
                j = 0; 
            }
            capture_times = 0;   
            HAL_TIMER_Clear_Capture_Flag(&TIM16_Handler, TIM_CHANNEL_1);   
            HAL_TIM_ENABLE_IT(&TIM16_Handler, TIM_IT_CC1);    
            HAL_TIM_Capture_Start(TIM16_Handler.Instance, TIM_CHANNEL_1);   
        }            		
	}
}  


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



void Timer_Capture_Test(uint32_t capture_channel)    
{
    uint32_t timer_clock;    
    
    timer_clock = HAL_RCC_GetPCLK2Freq(); // TIM16 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:  
        TIM16_IC1_Init();  
        
#ifdef  READ_CAPTURE_DATA_BY_INTERRUPT        
        TIM16_IC1_Capture_IT();        
#else
        TIM16_IC1_Capture();  
#endif         
        break;   
        
        default: 
        printfS("Application not supported \n");   
        break;  
    }

}

