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

#ifndef __I2C_H
#define __I2C_H

//-- Includes ------------------------------------------------------------------
#include "plib035.h"
#include "plib035_i2c.h"
#include "retarget_conf.h"

//-- Defines -------------------------------------------------------------------
// Дефайны для пинов I2C
#define I2C_SCL_Pin      GPIO_Pin_0   /**< PA0 — I2C SCL */
#define I2C_SDA_Pin      GPIO_Pin_1   /**< PA1 — I2C SDA */
#define I2C_GPIO_Port    GPIOA        /**< GPIO порт I2C */

// Стандартные частоты I2C
#define I2C_STANDARD_MODE              100000    /**< 100 kHz */
#define I2C_FAST_MODE                  400000    /**< 400 kHz */
#define I2C_FAST_MODE_PLUS             1000000   /**< 1 MHz */
#define I2C_HIGH_SPEED_MODE            3400000   /**< 3.4 MHz */

// Максимальное время ожидания по умолчанию (мс)
#define I2C_DEFAULT_TIMEOUT            1000

// Коды ошибок I2C
#define I2C_ERROR_NONE                 0x00
#define I2C_ERROR_BUS_BUSY             0x01
#define I2C_ERROR_TIMEOUT              0x02
#define I2C_ERROR_NACK                 0x03
#define I2C_ERROR_ARBITRATION_LOST     0x04
#define I2C_ERROR_BUS_ERROR            0x05
#define I2C_ERROR_PEC_FAIL             0x06

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

/**
  * @brief Типы callback-функций I2C
  */
typedef enum
{
  I2C_Callback_Tx,     /*!< Передача данных завершена */
  I2C_Callback_Rx,     /*!< Приём данных завершён */
  I2C_Callback_Addr,   /*!< Ведомый получил свой адрес */
  I2C_Callback_Error,  /*!< Ошибка I2C */
  
} I2C_CallbackTypeDef;

/**
  * @brief Режимы работы I2C
  */
typedef enum
{
  I2C_Mode_Master,     /*!< Режим мастера */
  I2C_Mode_Slave,      /*!< Режим ведомого */
} I2C_ModeTypeDef;

/**
  * @brief Направление передачи I2C
  */
typedef enum
{
  I2C_Direction_Transmitter,  /*!< Направление: передатчик */
  I2C_Direction_Receiver,     /*!< Направление: приемник */
} I2C_DirectionTypeDef;

/**
  * @brief Размер регистра устройства
  */
typedef enum
{
  I2C_RegSize_8bit,    /*!< Размер регистра: 8 бит */
  I2C_RegSize_16bit,   /*!< Размер регистра: 16 бит */
} I2C_RegSizeTypeDef;

/**
  * @brief Структура инициализации I2C
  */
typedef struct
{
  I2C_ModeTypeDef       Mode;           /*!< Режим работы: I2C_Mode_Master или I2C_Mode_Slave */
  FunctionalState       HSMode;         /*!< Высокоскоростной режим */
  FunctionalState       Addr10Bit;      /*!< 10-битная адресация */
  I2C_RegSizeTypeDef    RegSize;        /*!< Размер регистра: I2C_RegSize_8bit или I2C_RegSize_16bit */
  uint16_t              SlaveAddr;      /*!< Адрес ведомого (для режима Slave) */
  
  FunctionalState           Timeout;        /*!< Таймаут: */
  I2C_TimeoutClkDiv_TypeDef TimeoutClkDiv;  /*!< Делитель тактирования таймаута */
  uint8_t                   TimeoutLoad;    /*!< Значение загрузки счетчика таймаута */
  
  FunctionalState       AlertResponse;  /*!< Ответ на тревогу */
  FunctionalState       GlobalCall;     /*!< Общий вызов */
  
} I2C_Init_TypeDef;

/**
  * @brief Расширенная конфигурация I2C
  */
typedef struct
{
  I2C_Init_TypeDef I2C_Init;          /*!< Базовая конфигурация I2C */
  
  uint32_t I2CFreq;                   /*!< Частота тактирования I2C в Гц */
  uint32_t FSFreq;                    /*!< Частота SCL в стандартном режиме в Гц */
  uint32_t HSFreq;                    /*!< Частота SCL в высокоскоростном режиме в Гц */
  
  /* Callback функции */
  void (*TxCallback)(void);           /*!< Вызывается при завершении передачи */
  void (*RxCallback)(void);           /*!< Вызывается при завершении приема */
  void (*AddrCallback)(void);         /*!< Вызывается когда ведомый получает свой адрес */
  void (*ErrCallback)(uint8_t error); /*!< Вызывается при ошибке I2C с кодом ошибки */
  
} I2C_ExtInit_TypeDef;

/**
  * @brief Хендл I2C
  */
typedef struct
{
  I2C_TypeDef           *Instance;    /*!< Регистры I2C */
  I2C_ExtInit_TypeDef   *Config;      /*!< Конфигурация I2C */
  
  uint8_t               LastError;    /*!< Код последней ошибки */
  
} I2C_HandleTypeDef;

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

extern I2C_HandleTypeDef hi2c;

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

/* Init functions */

/* Первичная инициализация I2C */
void i2c_init_first(void);
/* Инициализация I2C */
OperationStatus i2c_init(I2C_HandleTypeDef *hi2c, I2C_ExtInit_TypeDef *NewConfig);
/* Инициализация GPIO для I2C */
void i2c_gpio_init(void);
/* Деинициализация GPIO для I2C */
void i2c_gpio_deinit(void);

/* API functions*/

/* Установка callback-функции I2C */
OperationStatus I2C_Set_Callback(I2C_HandleTypeDef *hi2c, I2C_CallbackTypeDef CallbackType, void (*Callback)());
/* Запуск I2C */
OperationStatus I2C_Start(I2C_HandleTypeDef *hi2c);
/* Остановка I2C */
OperationStatus I2C_Stop(I2C_HandleTypeDef *hi2c);

/* Получение кода последней ошибки */
uint8_t I2C_GetLastError(I2C_HandleTypeDef *hi2c);

/* Передача данных в режиме мастера (блокирующий режим) */
OperationStatus I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t addr, uint8_t *buf, uint16_t size, uint32_t timeout);
/* Прием данных в режиме мастера (блокирующий режим) */
OperationStatus I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t addr, uint8_t *buf, uint16_t size, uint32_t timeout);
/* Запись регистра устройства (блокирующий режим) */
OperationStatus I2C_Master_WriteReg(I2C_HandleTypeDef *hi2c, uint16_t addr, uint16_t reg, uint8_t value, uint32_t timeout);
/* Чтение регистра устройства (блокирующий режим) */
OperationStatus I2C_Master_ReadReg(I2C_HandleTypeDef *hi2c, uint16_t addr, uint16_t reg, uint8_t *buf, uint16_t size, uint32_t timeout);
/* Запись нескольких регистров (блокирующий режим) */
OperationStatus I2C_Master_WriteRegs(I2C_HandleTypeDef *hi2c, uint16_t addr, uint16_t reg, uint8_t *buf, uint16_t size, uint32_t timeout);
/* Чтение нескольких регистров (блокирующий режим) */
OperationStatus I2C_Master_ReadRegs(I2C_HandleTypeDef *hi2c, uint16_t addr, uint16_t reg, uint8_t *buf, uint16_t size, uint32_t timeout);

/* Проверка наличия устройства на шине */
OperationStatus I2C_Master_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t addr, uint32_t timeout);

#endif /*__I2C_H*/
