/********************************* (C) РОТЕК ***********************************
 * @module  buttons
 * @file    buttons.c
 * @version 1.0.0
 * @date    XX.XX.XXXX
 * $brief   buttons
 *******************************************************************************
 * @history     Version  Author         Comment
 * XX.XX.XXXX   1.0.0    Telenkov D.A.  First release.
 *******************************************************************************
 */
#include "common_config.h"
#include "stm32f4xx.h"  
#include "buttons.h"
#include "led.h"
#include "settings_api.h"
#include "commands_api.h"

#include "FreeRTOS.h"
#include "task.h"

BUTTON_NO_FIX_t defButton;
BUTTON_NO_FIX_t setButton;

uint8_t DefCounter = 0;
uint8_t SetCounter = 0;

/**
  * @brief  
  * @retval 
  */
void BUTTON_Init(void) 
{
  defButton.id_pin			  = KEY_DEF;
  defButton.timeDelay         = 5;
  defButton.pressHandler      = BUTTON_DEF_UpHandler;
  defButton.unpressHandler    = BUTTON_DEF_DownHandler;
  defButton.counterActivation = 0;
  defButton.timeActivation    = 40;
  defButton.fActivation       = false;
    
  defButton.stateOld     = BUTTON_GetState(&defButton);

  setButton.id_pin			  = MODE_JUMPER;
  setButton.timeDelay         = 5;
  setButton.pressHandler      = BUTTON_SET_UpHandler;
  setButton.unpressHandler    = BUTTON_SET_DownHandler;
  setButton.counterActivation = 0;
  setButton.timeActivation    = 40;
  setButton.fActivation       = false;

  setButton.stateOld     = BUTTON_GetState(&setButton);
	
}

/**
  * @brief   Возвращает сотояние ключа
  */
BUTTON_STATE_t BUTTON_GetState(BUTTON_NO_FIX_t *button)
{
  return (BUTTON_STATE_t)gpio_get(button->id_pin);
}

/**
  * @brief  Обработчик кнопки без фиксации. В обработчике реализована защита
  *         от дребезга с помощью задержки. Защита срабатывает при нажатии 
  *         и при отпускании.
  * @param *button: указатель на структуру типа BUTTON_NO_FIX
  * @retval нет
  */
void BUTTON_NoFixHandler(BUTTON_NO_FIX_t *button)
{
  uint8_t temp;
  
  if (button->stateNew != BUT_NO_DEFINE)
  {  
    temp = gpio_get(button->id_pin);
    
    if (temp == 0)  // определяем текущее (новое) состояние кнопки        
      button->stateNew = BUT_ON;
    else
      button->stateNew = BUT_OFF;
  
    if (button->stateNew != button->stateOld)  // зафиксирован факт нажатия/отжатия
      button->stateNew = BUT_NO_DEFINE;  // переводим кнопку в неопределенное состояние
  }
  else
  {
    button->counterDelay++;             // запускаем счетчик на задержку
    
    if (button->counterDelay > button->timeDelay)  // задержка закончилась
    {
      button->counterDelay = 0;

      temp = gpio_get(button->id_pin);
   	  
      button->counterActivation = 0;
		
      if (temp == 0)  // определяем текущее (новое) состояние кнопки        
      {  
        button->stateNew = BUT_ON;
        button->unpressHandler();
      }  
      else
      {  
        button->stateNew = BUT_OFF;
        button->pressHandler();
      }
	  	
    }
  }
  
  button->stateOld = button->stateNew;

}


/**
  * @brief  Обработчик кнопки без фиксации. Кнопка срабатывает через определеное
            время нажатия.
  * @param *button: указатель на структуру типа BUTTON_NO_FIX
  * @retval нет
  */
void BUTTON_DellayHandler(BUTTON_NO_FIX_t *button)
{
  /* Кнопка нажата. Ведем отсчет времени удержания */
  if (gpio_get(button->id_pin) == 0)  // определяем текущее (новое) состояние кнопки
  {  
	button->counterActivation++;
	button->fActivation = false;
	
	/* Кнопка нажата более необходимого времени - начинаем чаще мигать диодом */
	if (button->counterActivation > button->timeActivation)
	  LED_SetStatusLedFreq(100);
  }
  /* Кнопку отжата. Если до этого она была нажата нужное время - вызываем хендлер */
  else
  {
	if ((button->counterActivation > button->timeActivation) 
	     && button->fActivation == false)
	{  
	  button->fActivation = true;
	  LED_SetStatusLedFreq(1000);
	  button->unpressHandler();
	}  
	else
	  button->counterActivation = 0;
  }		

}

/**
  * @brief  Опрос кнопок
  */
void vTaskButtons(void *pvParameters) 
{
  for (;;) 
  {
	BUTTON_DellayHandler(&defButton);
	
    vTaskDelay(100);  //20
  }
}

/**
  * @brief  Хендлер кнопки DEFAULT.
  */
void BUTTON_DEF_UpHandler(void)
{
    DefCounter++;
#ifdef LED_INIT_ERR
    LED_Off(LED_INIT_ERR);
#endif
#ifdef LED_ALARM
	LED_Off(LED_ALARM);
#endif
#ifdef LED_RED_MINOR
	LED_Off(LED_RED_MINOR);
#endif
}


/**
  * @brief  Хендлер кнопки DEFAULT. Сброс всех настроек, сохранение и перезагрузка
  */
void BUTTON_DEF_DownHandler(void)
{
#ifdef LED_INIT_ERR
	LED_On(LED_INIT_ERR);
#endif
#ifdef LED_ALARM
	LED_On(LED_ALARM);
#endif
#ifdef LED_RED_MINOR
	LED_On(LED_RED_MINOR);
#endif
    fDefPressed = true;
}

/**
  * @brief  Хендлер кнопки SET.
  */
void BUTTON_SET_UpHandler(void)
{
#ifdef LED_INIT_OK
   LED_On(LED_INIT_OK);
#endif
#ifdef LED_GREEN_MINOR
	LED_On(LED_GREEN_MINOR);
#endif
}


/**
  * @brief  Хендлер кнопки SET
  */
void BUTTON_SET_DownHandler(void)
{
	SetCounter++;
#ifdef LED_INIT_OK
    LED_Off(LED_INIT_OK);
#endif
#ifdef LED_GREEN_MINOR
	LED_Off(LED_GREEN_MINOR);
#endif
}


/********************************* (C) РОТЕК **********************************/