/**
  ******************************************************************************
  * @file    uart.h
  * @author  Разваляев Алексей
  * @brief   Драйвер UART на основе PLIB035.
  *          Данный файл содержит определения типов, структур и прототипы функций
  *          для работы с UART, включая:
  *           + Структуры и typedef для UART
  *           + Макросы для конфигурации направления передачи
  *           + Прототипы функций для инициализации и API драйвера
  *
  ******************************************************************************
  */

#ifndef __UART_H
#define __UART_H
//-- Includes ------------------------------------------------------------------
#include "plib035.h"
#include "retarget_conf.h"

//-- Defines -------------------------------------------------------------------
// Дефайны для режима направления UART
// Дефайны для режима пина              RxEnable,   TxEnable
/** @brief Направление: никакого */
#define UART_Direction_None             DISABLE,    DISABLE
/** @brief Направление: Rx и Tx */
#define UART_Direction_RxTx             ENABLE,     ENABLE
/** @brief Направление: только Tx */
#define UART_Direction_Tx               DISABLE,    ENABLE
/** @brief Направление: только Rx */
#define UART_Direction_Rx               ENABLE,     DISABLE

// Дефайны для пинов UART
#define UART0_Tx_Pin      GPIO_Pin_10   /**< PB10 — UART0 Tx */
#define UART0_Rx_Pin      GPIO_Pin_11   /**< PB11 — UART0 Rx */
#define UART0_GPIO_Port   GPIOB         /**< GPIO порт UART0 */

#define UART1_Tx_Pin      GPIO_Pin_8    /**< PB8 — UART1 Tx */
#define UART1_Rx_Pin      GPIO_Pin_9    /**< PB9 — UART1 Rx */
#define UART1_GPIO_Port   GPIOB         /**< GPIO порт UART1 */

#define USE_TX_QUEUE  1   /*!< Использовать очередь для отправки, чтобы не терять данные */
#define TX_QUEUE_SIZE 32  /*!< Размер очереди в кол-ве буферов для отправки */

//-- Types ---------------------------------------------------------------------

/**
  * @brief Типы callback-функций UART
  */
typedef enum
{
  UART_Callback_Rx,     /*!< Приём данных завершён */
  UART_Callback_Tx,     /*!< Передача данных завершена */
  UART_Callback_Idle,   /*!< Обнаружено состояние IDLE */
  UART_Callback_Error,  /*!< Ошибка UART */
  
} UART_CallbackTypeDef;


/**
  * @brief Расширенная конфигурация UART
  */
typedef struct
{
  UART_Init_TypeDef UART_Init;  /*!< Стандартная конфигурация UART из PLIB */

  /* Callback функции */
  void (*RxCallback)(void);     /*!< Вызывается при приёме полного сообщения */
  void (*TxCallback)(void);     /*!< Вызывается при окончании передачи */
  void (*IdleCallback)(void);   /*!< Вызывается при IDLE линии RX */
  void (*ErrCallback)(void);    /*!< Вызывается при ошибке UART */

} UART_ExtInit_TypeDef;


/**
  * @brief Структура элемента очереди
  */
typedef struct {
  const uint8_t *Buf;     /*!< Указатель на буфер данных */
  uint16_t Size;          /*!< Размер данных в буфере */
  uint8_t InUse;         /*!< Флаг занятости элемента */
} UART_QueueItemTypeDef;

/**
  * @brief Структура очереди UART
  */
typedef struct {
  UART_QueueItemTypeDef Queue[TX_QUEUE_SIZE]; /*!< Циклический буфер очереди */
  uint8_t QueueHead;                /*!< Индекс головы очереди (куда добавляем) */
  uint8_t QueueTail;                /*!< Индекс хвоста очереди (откуда берем) */
  uint8_t QueueCount;               /*!< Количество элементов в очереди */
  uint8_t QueueEmpty;               /*!< Флаг пустой очереди */
  uint8_t QueueFull;                /*!< Флаг полной очереди */
} UART_TxQueueTypeDef;

/**
  * @brief Хендл UART
  */
typedef struct
{
  UART_TypeDef         *Instance;  /*!< Регистры UART */
  UART_ExtInit_TypeDef *Config;    /*!< Конфигурация UART */

  /* ===== TX ===== */
  const uint8_t     *TxBufPtr;  /*!< Указатель на буфер передачи */
  uint16_t          TxCount;    /*!< Счётчик переданных байт */
  uint16_t          TxSize;     /*!< Размер передаваемых данных */
  volatile uint8_t  TxBusy;     /*!< Флаг занятости TX */

  /* ===== RX ===== */
  uint8_t           *RxBufPtr;  /*!< Указатель на буфер приёма */
  uint16_t          RxCount;    /*!< Счётчик принятых байт */
  uint16_t          RxSize;     /*!< Размер принимаемых данных */
  volatile uint8_t  RxBusy;     /*!< Флаг занятости RX */
  
#if (USE_TX_QUEUE==1)
  /* == TX QUEUE == */
  UART_TxQueueTypeDef TxQueue;
#endif
  
} UART_HandleTypeDef;

//-- External handles ----------------------------------------------------------

extern UART_HandleTypeDef huart0;
extern UART_HandleTypeDef huart1;

//-- Exported functions prototypes ---------------------------------------------

/* Init functions */

/* Первичная инициализация UART (UART0 / UART1) */
void uart_init_first(void);
/* Инициализация UARTx */
OperationStatus uart_init(UART_HandleTypeDef *huart, UART_ExtInit_TypeDef *NewConfig);
/* Общий обработчик прерываний UART */
void uart_irq_handler(UART_HandleTypeDef *huart);
/* Инициализация GPIO для UART0 */
void uart0_gpio_init(void);
/* Деинициализация GPIO для UART0 */
void uart0_gpio_deinit(void);
/* Инициализация GPIO для UART1 */
void uart1_gpio_init(void);
/* Деинициализация GPIO для UART1 */
void uart1_gpio_deinit(void);

/* API functions*/

/* Установка callback-функции UART */
OperationStatus UART_Set_Callback(UART_HandleTypeDef *huart, UART_CallbackTypeDef CallbackType, void (*Callback)(void));
/* Запуск UART и настройка FIFO */
OperationStatus UART_Start(UART_HandleTypeDef *huart, UART_FIFOLevel_TypeDef TxFifoLevel, UART_FIFOLevel_TypeDef RxFifoLevel);

/* Передача данных по UART (блокирующий режим) */
OperationStatus UART_Transmit(UART_HandleTypeDef *huart, uint8_t *buf, uint16_t size, uint32_t timeout);
/* Приём данных по UART (блокирующий режим) */
OperationStatus UART_Receive(UART_HandleTypeDef *huart, uint8_t *buf, uint16_t size, uint32_t timeout);
/* Передача данных по UART (режим прерываний) */
OperationStatus UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *buf, uint16_t size);
/* Приём данных по UART (режим прерываний) */
OperationStatus UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *buf, uint16_t size);



#endif /*__UART_H*/
