/** 
**************************************************************************
* @file general_gpio.h
* @brief Заголовочный файл для модуля инициализации портов и работы с ними.
**************************************************************************
* @defgroup GENERAL_GPIO      GPIO Tools
* @ingroup  STM32_GENERAL
* @brief    Функции и макросы для удобной работы с GPIO.
* @details
Модуль предоставляет универсальные инструменты для работы с GPIO):
  - @ref  MYLIBS_GPIO_GENERAL — инициализация и общие функции работы с портами.
  - @ref  MYLIBS_GPIO_SWITCH — работа с GPIO как с кнопкой: чтение состояния, 
          фильтрация дребезга, настройка активного уровня.
  - @ref  MYLIBS_GPIO_LEDS — работа с GPIO как со светодиодом: включение, 
          выключение, моргание и плавное затухание.

*************************************************************************/
#ifndef __GPIO_GENERAL_H_
#define __GPIO_GENERAL_H_

#include "mylibs_defs.h"

/** 
  * @addtogroup GPIO_INIT GPIO Init defines
  * @ingroup    MYLIBS_GPIO_GENERAL
  * @ingroup    GENERAL_CONFIGS Конфигурации STM32 General
  * @brief      Настройка состояний кнопок и количества тиков в периоде ШИМ
  * @{
  */

#ifndef local_time
#define local_time()  HAL_GetTick() ///< Локальное время
#endif

#ifndef LED_PWM_TICKS
#define LED_PWM_TICKS 15 ///< Количество тиков в периоде ШИМ
#endif
  
#ifndef LED_ON
#define LED_ON 1  ///< Состояние пина для включения светодиода
#endif
#ifndef LED_OFF
#define LED_OFF 0 ///< Состояние пина для выключения светодиода
#endif

#ifndef SW_ON
#define SW_ON 1   ///< Состояние пина при нажатой кнопке
#endif
#ifndef SW_OFF
#define SW_OFF 0  ///< Состояние пина при отжатой кнопке
#endif

/** GPIO_INIT
  * @}
  */


/**
  * @brief Режимы работы светодиода
  * @ingroup  MYLIBS_GPIO_LEDS
  */
typedef enum
{
  LED_IS_OFF = 0,       ///< Светодиод выключен
  LED_IS_ON = 1,        ///< Светодиод включен
  LED_IS_BLINKING = 2,  ///< Моргание светодиодом
  LED_IS_FADING = 3,    ///< Плавное моргание светодиодом
}GPIO_LEDStateTypeDef;

/**
  * @brief Структура светодиода
  * @ingroup  MYLIBS_GPIO_LEDS
  */
typedef struct
{
  GPIO_LEDStateTypeDef state;     ///< Текущий режим работы светодиода
  
  GPIO_TypeDef  *LED_Port;        ///< GPIO порт ножки светодиода
  uint32_t      LED_Pin;          ///< GPIO пин ножки светодиода
  
  uint8_t       LED_ActiveLvl;    ///< Активный уровень ножки (при котором светодиод горит)
  uint32_t      LED_Period;       ///< Период моргания светодиода

  uint32_t      tickprev;
}GPIO_LEDTypeDef;

/**
  * @brief Структура кнопки
  * @ingroup  MYLIBS_GPIO_SWITCH
  */
typedef struct
{
  GPIO_TypeDef  *Sw_Port;         ///< GPIO порт ножки кнопки
  uint32_t      Sw_Pin;           ///< GPIO пин ножки кнопки
  
  uint8_t       Sw_ActiveLvl;     ///< Активный уровень ножки (при котором кнопка нажата)
  uint32_t      Sw_PrevState;     ///< Предыдущее состояние кнопки
  uint32_t      Sw_FilterDelay;   ///< Фильтр от дребезга (в мс)

  uint32_t      tickprev; 
}GPIO_SwitchTypeDef;


/////////////////////////////////////////////////////////////////////
///////////////////////////---FUNCTIONS---///////////////////////////
/** 
  * @addtogroup MYLIBS_GPIO_GENERAL  General tools
  * @ingroup    GENERAL_GPIO
  * @brief      Общие функции/макросы для работы с GPIO
  * @par Пример использования:
    @code
    // Включаем тактирование порта GPIOA
    GPIO_Clock_Enable(GPIOA);
    @endcode
  * @{
  */

HAL_StatusTypeDef GPIO_Clock_Enable(GPIO_TypeDef *GPIOx);

/** MYLIBS_GPIO_GENERAL
  * @}
  */

/** 
  * @addtogroup MYLIBS_GPIO_SWITCH  Switch tools
  * @ingroup    GENERAL_GPIO
  * @brief      Функции для работы с GPIO, как с кнопкой
  * @par Пример использования:
    @code
    MX_GPIO_Init(); // инициализация пина аппаратная
    
    // Инициализация кнопки на порте GPIOB, пин 0, активный уровень 1
    GPIO_SwitchTypeDef sw1;
    GPIO_Switch_Init(&sw1, GPIOB, GPIO_PIN_0, 1); // или дефайн SW_ON/SW_OFF

    // Считываем состояние кнопки
    if(GPIO_Read_Switch(&sw1))
    {
        // Кнопка нажата
        LED_ON();
    }
    else
    {
        // Кнопка отжата
        LED_OFF();
    }
    @endcode
  * @{
  */

/* Инициализировать кнопку (структуру кнопки) */
HAL_StatusTypeDef GPIO_Switch_Init(GPIO_SwitchTypeDef *sw, GPIO_TypeDef *GPIOx, uint32_t GPIO_PIN_X, uint8_t SW_On_State);
/* Считать состоянии кнопки запуска */
int GPIO_Read_Switch(GPIO_SwitchTypeDef *swstart);

/** MYLIBS_GPIO_SWITCH
  * @}
  */


/** 
  * @addtogroup MYLIBS_GPIO_LEDS  LED tools
  * @ingroup    GENERAL_GPIO
  * @brief      Функции для работы с GPIO, для управления светодиодом
  * @par Пример использования:
    @code
    MX_GPIO_Init(); // инициализация пина аппаратная

    // Инициализация светодиода на порте GPIOA, пин 5, активный уровень 0
    GPIO_LEDTypeDef led;
    GPIO_LED_Init(&led, GPIOA, GPIO_PIN_5, 0); // или дефайн LED_ON/LED_OFF

    // Включение светодиода
    GPIO_LED_On(&led);

    // Запуск моргания
    GPIO_LED_Blink_Start(&led, 500); // Период 500 мс

    // В основном цикле
    while (1) {
      GPIO_LED_Dynamic_Handle(&led);
    }
    @endcode
  * @{
  */

/* Инициализировать светодиод (структуру светодиода) */
HAL_StatusTypeDef GPIO_LED_Init(GPIO_LEDTypeDef *led, GPIO_TypeDef *GPIOx, uint32_t GPIO_PIN_X, uint8_t LED_On_State);
/* Включить светодиод */
HAL_StatusTypeDef GPIO_LED_On (GPIO_LEDTypeDef *led);
/* Выключить светодиод */
HAL_StatusTypeDef GPIO_LED_Off (GPIO_LEDTypeDef *led);
/* Выставить светодиод по переменной */
HAL_StatusTypeDef GPIO_LED_Set (GPIO_LEDTypeDef *led, uint8_t led_state);
/* Активировать моргание светодиодом */
HAL_StatusTypeDef GPIO_LED_Blink_Start (GPIO_LEDTypeDef *led, uint32_t period);
/* Активировать моргание светодиодом */
HAL_StatusTypeDef GPIO_LED_Fading_Start(GPIO_LEDTypeDef *led, uint32_t period);
/* Управление динамическими режимами свечения светодиода */
void GPIO_LED_Dynamic_Handle(GPIO_LEDTypeDef *led);

/** MYLIBS_GPIO_LEDS
  * @}
  */
///////////////////////////---FUNCTIONS---///////////////////////////


/** 
 * @cond GPIO_INTERNAL
 */

// /**
//   * @brief Маппинг альтернативной функции SPI между GPIO
//   * @ingroup  MYLIBS_GPIO_GENERAL
//   */
// #define SPI_Alternate_Mapping(INSTANCE) \
// ((((INSTANCE) == TIM1)  || ((INSTANCE) == TIM2))?     GPIO_AF1_TIM1:                                                   \
// (((INSTANCE) == TIM3)   || ((INSTANCE) == TIM4)   || ((INSTANCE) == TIM5))? GPIO_AF2_TIM3:                            \
// (((INSTANCE) == TIM8)   || ((INSTANCE) == TIM9)   || ((INSTANCE) == TIM10) || ((INSTANCE) == TIM11))? GPIO_AF3_TIM8:  \
// (((INSTANCE) == TIM12)  || ((INSTANCE) == TIM13)  || ((INSTANCE) == TIM14))? GPIO_AF9_TIM12:                        \
// (0))


/**
  * @brief Маппинг альтернативной функции TIM между GPIO
  * @ingroup  MYLIBS_GPIO_GENERAL
  */
#define GPIO_TIM_Alternate_Mapping(INSTANCE) \
((((INSTANCE) == TIM1)  || ((INSTANCE) == TIM2))? GPIO_AF1_TIM1:                                                      \
(((INSTANCE) == TIM3)   || ((INSTANCE) == TIM4)   || ((INSTANCE) == TIM5))? GPIO_AF2_TIM3:                            \
(((INSTANCE) == TIM8)   || ((INSTANCE) == TIM9)   || ((INSTANCE) == TIM10) || ((INSTANCE) == TIM11))? GPIO_AF3_TIM8:  \
(((INSTANCE) == TIM12)  || ((INSTANCE) == TIM13)  || ((INSTANCE) == TIM14))? GPIO_AF9_TIM12:                          \
(0))


/** @endcond */

#endif // __GPIO_GENERAL_H_