#include "stm32f0xx_hal.h"
#include "pwm_in.h"
#include <stdio.h>

#define LED_ON      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
#define LED_OFF     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);

#define PWM_IN_TIM_FREQ     1000000
#define PWM_FILTER_THR      16

static TIM_HandleTypeDef       TimHandle;
static TIM_IC_InitTypeDef      sConfig;
static TIM_SlaveConfigTypeDef  sSlaveConfig;

static uint16_t prescaler;

__IO uint32_t cap_value_1 = 0;  // Captured Value
__IO uint32_t duty = 0;         // Duty Cycle Value
__IO uint32_t freq = 0;         // Frequency Value

uint8_t btn_pressed = 0;

//
void tim_pwm_in_init(void)
{
    GPIO_InitTypeDef   GPIO_InitStruct;
    
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_TIM3_CLK_ENABLE();
  
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF1_TIM3;//GPIO_AF0_TIM3;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    HAL_NVIC_SetPriority(TIM3_IRQn, 0, 1);
    //HAL_NVIC_SetPriority(TIM3_IRQn, 2, 0); // From lasertag project
    HAL_NVIC_EnableIRQ(TIM3_IRQn);
    
    prescaler = HAL_RCC_GetHCLKFreq()/PWM_IN_TIM_FREQ - 1;
    
    TimHandle.Instance = TIM3;
    TimHandle.Init.Period            = 0xFFFF;
    TimHandle.Init.Prescaler         = prescaler;
    TimHandle.Init.ClockDivision     = 0;
    TimHandle.Init.CounterMode       = TIM_COUNTERMODE_UP;
    TimHandle.Init.RepetitionCounter = 0;
    TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    HAL_TIM_IC_Init(&TimHandle);

    sConfig.ICPrescaler = TIM_ICPSC_DIV1;
    sConfig.ICFilter = 0;
  
    sConfig.ICPolarity = TIM_ICPOLARITY_RISING; ;
    sConfig.ICSelection = TIM_ICSELECTION_DIRECTTI;
    HAL_TIM_IC_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_1);
    
    sConfig.ICPolarity = TIM_ICPOLARITY_FALLING;
    sConfig.ICSelection = TIM_ICSELECTION_INDIRECTTI;
    HAL_TIM_IC_ConfigChannel(&TimHandle, &sConfig, TIM_CHANNEL_2);
    
    sSlaveConfig.SlaveMode        = TIM_SLAVEMODE_RESET;
    sSlaveConfig.InputTrigger     = TIM_TS_TI1FP1;
    sSlaveConfig.TriggerPolarity  = TIM_TRIGGERPOLARITY_NONINVERTED;
    sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;
    sSlaveConfig.TriggerFilter    = 0;
    
    HAL_TIM_SlaveConfigSynchro(&TimHandle, &sSlaveConfig);
    
    HAL_TIM_IC_Start_IT(&TimHandle, TIM_CHANNEL_1);
    HAL_TIM_IC_Start_IT(&TimHandle, TIM_CHANNEL_2);
}

//
void tim_print_out_pwm(void)
{
    printf("Captured Value %u\r\n", cap_value_1);
    printf("Duty Cycle Value %u\r\n", duty);
    printf("Frequency Value %u\r\n\n", freq);
}

//
void TIM3_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&TimHandle);
}

//
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    static uint8_t bt_pressed_flag = 0;
    static uint8_t filter_cnt = 0;
    
    if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
    {
        cap_value_1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);

        if (cap_value_1 != 0)
        {
            // частота ШИМ в герцах (для контроля)
            freq = PWM_IN_TIM_FREQ/cap_value_1;
            
            duty = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
            
            if (duty > 1600) {
                filter_cnt++;
                LED_ON;
            }
            else {
                bt_pressed_flag = 0;
                filter_cnt = 0;
                LED_OFF;
            }
            
            // Выполняется условие фильтра и было ожатие кнопки
            if ((filter_cnt == PWM_FILTER_THR) && (bt_pressed_flag == 0)){
                bt_pressed_flag = 1;
                btn_pressed = true;
            }
        }
        else
        {
            duty = 0;
            freq = 0;
        }
    }
}


bool get_button(void)
{
    return btn_pressed;
}


//
void set_button(bool state)
{
    btn_pressed = state;
}