/** 
**************************************************************************
* @file general_spi.h
* @brief Заголовочный файл для модуля инициализации SPI.
**************************************************************************
* @defgroup GENERAL_SPI      SPI Tools
* @ingroup  STM32_GENERAL
* @brief    Функции и макросы для удобной работы с SPI.
* @details
Модуль предоставляет функции для базовой инициализации SPI


@par Пример использования:
@code
// Структура настроек SPI
SPI_SettingsTypeDef spi1Settings;

void SPI1_Init(void)
{
    // Настройка SPI1 как Master, 8 бит, полный дуплекс
    spi1Settings.hspi.Instance = SPI1;
    spi1Settings.hspi.Init.Mode = SPI_MODE_MASTER;
    spi1Settings.hspi.Init.Direction = SPI_DIRECTION_2LINES;
    spi1Settings.hspi.Init.DataSize = SPI_DATASIZE_8BIT;
    spi1Settings.hspi.Init.CLKPolarity = SPI_POLARITY_LOW;
    spi1Settings.hspi.Init.CLKPhase = SPI_PHASE_1EDGE;
    spi1Settings.hspi.Init.NSS = SPI_NSS_SOFT;
    spi1Settings.hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
    spi1Settings.hspi.Init.FirstBit = SPI_FIRSTBIT_MSB;
    spi1Settings.hspi.Init.TIMode = SPI_TIMODE_DISABLE;
    spi1Settings.hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

    // Настройка GPIO
    spi1Settings.CLK_GPIOx = GPIOA;
    spi1Settings.CLK_PIN = GPIO_PIN_5;
    spi1Settings.CLK_GPIO_AlternageFunc = GPIO_AF5_SPI1;

    spi1Settings.MISO_GPIOx = GPIOA;
    spi1Settings.MISO_PIN = GPIO_PIN_6;
    spi1Settings.MISO_GPIO_AlternageFunc = GPIO_AF5_SPI1;

    spi1Settings.MOSI_GPIOx = GPIOA;
    spi1Settings.MOSI_PIN = GPIO_PIN_7;
    spi1Settings.MOSI_GPIO_AlternageFunc = GPIO_AF5_SPI1;

    // Инициализация SPI
    if(SPI_Base_Init(&spi1Settings) != HAL_OK)
    {
        // Обработка ошибки
        Error_Handler();
    }
}
@endcode



*  @note Требуется подключение модуля SPI в библиотеке HAL 
@code 
#define HAL_SPI_MODULE_ENABLED
@endcode
* @{
*************************************************************************/
#ifndef __SPI_GENERAL_H_
#define __SPI_GENERAL_H_


/////////////////////////////////////////////////////////////////////
/////////////////////////---USER SETTINGS---/////////////////////////
/** 
  * @addtogroup SPI_INIT SPI Init defines
  * @ingroup    GENERAL_SPI
  * @ingroup    GENERAL_CONFIGS Конфигурации STM32 General
  * @brief      Настройка SPI
  * @{
  */
#define HAL_SPI_MODULE_ENABLED   ///< Включение HAL SPI

#define USE_SPI1    ///< Включить SPI1 в @ref SPI_MspInit
#define USE_SPI2    ///< Включить SPI2 в @ref SPI_MspInit
#define USE_SPI3    ///< Включить SPI3 в @ref SPI_MspInit
/** SPI_INIT
  * @}
  */
/////////////////////////---USER SETTINGS---/////////////////////////
#include "mylibs_defs.h"



/////////////////////////////////////////////////////////////////////
////////////////////////////---DEFINES---////////////////////////////


                              
////////////////////////////---DEFINES---////////////////////////////


/////////////////////////////////////////////////////////////////////
///////////////////////---STRUCTURES & ENUMS---//////////////////////
/**
  * @brief Структура настроек SPI
  * @details Содержит все необходимые параметры для инициализации SPI,
  * включая GPIO и DMA.
  */
typedef struct
{
  SPI_HandleTypeDef hspi;                 ///< HAL handle SPI
  
  GPIO_TypeDef  *CLK_GPIOx;               ///< Порт CLK
  uint32_t      CLK_PIN;                  ///< Пин CLK
  uint32_t      CLK_GPIO_AlternageFunc;   ///< Альтернативная функция для CLK
  
  GPIO_TypeDef  *MISO_GPIOx;              ///< Порт MISO
  uint32_t      MISO_PIN;                 ///< Пин MISO
  uint32_t      MISO_GPIO_AlternageFunc;  ///< Альтернативная функция для MISO
  
  GPIO_TypeDef  *MOSI_GPIOx;              ///< Порт MOSI
  uint32_t      MOSI_PIN;                 ///< Пин MOSI
  uint32_t      MOSI_GPIO_AlternageFunc;  ///< Альтернативная функция для MOSI

  DMA_Stream_TypeDef *DMAChannel;         ///< Канал DMA (NULL если не нужен)
  uint32_t DMA_CHANNEL_X;                 ///< Номер канала DMA (0 если не нужен)
  
} SPI_SettingsTypeDef;
///////////////////////---STRUCTURES & ENUMS---//////////////////////


/////////////////////////////////////////////////////////////////////
///////////////////////////---FUNCTIONS---///////////////////////////

/* Инициализация SPI с использованием структуры настроек */
HAL_StatusTypeDef SPI_Base_Init(SPI_SettingsTypeDef *sspi);

/* Проверка корректности структуры настроек SPI */
HAL_StatusTypeDef SPI_Check_Init_Struct(SPI_SettingsTypeDef *sspi);

/* Инициализация тактирования и прерываний для выбранного SPI */
void SPI_MspInit(SPI_HandleTypeDef *hspi);

/* Деинициализация тактирования и прерываний для выбранного SPI */
void SPI_MspDeInit(SPI_HandleTypeDef *hspi);

  
/** 
 * @cond SPI_INTERNAL
 */

/* Настройка GPIO для SPI */
void SPI_GPIO_Init(SPI_SettingsTypeDef *sspi);

/* Настройка DMA для SPI */
void SPI_DMA_Init(SPI_HandleTypeDef *hspi, DMA_HandleTypeDef *hdma_rx, DMA_Stream_TypeDef *DMAChannel, uint32_t DMA_CHANNEL_X);

#ifndef __USER_LINKDMA
/**  
  * @brief  Аналог HAL макроса для привязки DMA к UART.
  * @note   @ref __HAL_LINKDMA.
  */
#define __USER_LINKDMA(__HANDLE__, __PPP_DMA_FIELD__, __DMA_HANDLE__)   \
do{                                                                     \
(__HANDLE__)->__PPP_DMA_FIELD__ = (__DMA_HANDLE__);                     \
(__DMA_HANDLE__)->Parent = (__HANDLE__);} while(0U)
#endif

/** @endcond */
///////////////////////////---FUNCTIONS---///////////////////////////

#endif // __SPI_GENERAL_H_

/** GENERAL_SPI
  * @}
  */