/*
 * hal_spi.h
 *
 *  Created on: 2023年5月29日
 *      Author: jinyaoh
 */

#ifndef _HAL_SPI_H_
#define _HAL_SPI_H_

#include "hal_dma.h"
#include "hal_def.h"
#include "hal_cmu.h"

typedef void (*spi_callback)(void *param, uint32_t flag);

typedef struct
{
    DMA_HandleTypeDef dma_handle_tx;
    DMA_HandleTypeDef dma_handle_rx;
    uint32_t dma_rx_num;
} spi_dma_handle;


typedef struct
{
    spi_callback callback;
    void  *param;
    uint32_t flag;
    spi_dma_handle *dma_handle;
} spi_callback_t;

typedef enum
{
    SPI_0 = 0,
    SPI_1,
    SPI_NUM,
} spi_port_t;


typedef enum
{
    CPOL_0_CPHA_0 = DEV_SPIn_CTL_SPI_MODE_MODE0,
    CPOL_0_CPHA_1 = DEV_SPIn_CTL_SPI_MODE_MODE1,
    CPOL_1_CPHA_0 = DEV_SPIn_CTL_SPI_MODE_MODE2,
    CPOL_1_CPHA_1 = DEV_SPIn_CTL_SPI_MODE_MODE3
} spi_clk_mode_t;




#define hal_spi_tx_dma_config_default                   \
{                                                       \
    8,                          /* channel */           \
    DMA_Address_Type_Inc,       /* src_inc */           \
    DMA_Address_Type_Fix,       /* dst_inc */           \
    DMA_Data_Width_8Bit,        /* src_data_width  */   \
    DMA_Data_Width_8Bit,        /* dst_data_width */    \
    DMA_Data_Location_Select_Low,  /* src_data_loc */       \
    DMA_Data_Location_Select_Low,   /* dst_data_loc */      \
    DMA_Burst_Length_Burst1,    /* memory_burst */      \
    DMA_Mode_Single,            /* mode */              \
    1                           /* priority */          \
}

#define hal_spi_rx_dma_config_default                   \
{                                                       \
    8,                          /* channel */           \
    DMA_Address_Type_Fix,       /* src_inc */           \
    DMA_Address_Type_Inc,       /* dst_inc */           \
    DMA_Data_Width_8Bit,        /* src_data_width  */   \
    DMA_Data_Width_8Bit,        /* dst_data_width */    \
    DMA_Data_Location_Select_Low,  /* src_data_loc */       \
    DMA_Data_Location_Select_Low,   /* dst_data_loc */      \
    DMA_Burst_Length_Burst1,    /* memory_burst */      \
    DMA_Mode_Single,            /* mode */              \
    1                           /* priority */          \
}


typedef struct
{
	cmu_clock_source_t clockSource;  // 时钟源，选择内部时钟源或者外部时钟源等
	cmu_clk_div_t prescaler;            // 分频系数，例如可以取值0 - 7等，不同值对应不同的分频比例，具体由硬件规定
    uint8_t receiveThreshold;    // 接收阈值，比如接收FIFO缓冲区达到多少个字节就触发相应中断或者处理逻辑，单位字节
    uint8_t transmitThreshold;   // 发射阈值，类似接收阈值，不过是针对发送缓冲区的情况，单位字节
    uint8_t useTxDMA;              // 发射是否使用DMA，1表示使用，0表示不使用
    uint8_t useRxDMA;              // 接收是否使用DMA，1表示使用，0表示不使用
} SpiInitTypeDef;


// SPI0 IO引脚复用功能
#define HAL_SPI0_CSS_MUXSEL_FUNCTION    1
#define HAL_SPI0_CLK_MUXSEL_FUNCTION    1
#define HAL_SPI0_DAT0_MUXSEL_FUNCTION   1
#define HAL_SPI0_DAT1_MUXSEL_FUNCTION   1
// SPI1 IO引脚复用功能
#define HAL_SPI1_CSS_MUXSEL_FUNCTION    1
#define HAL_SPI1_CLK_MUXSEL_FUNCTION    1
#define HAL_SPI1_DAT0_MUXSEL_FUNCTION   1
#define HAL_SPI1_DAT1_MUXSEL_FUNCTION   1
// SPI0 SPI1  DMA使能
#define SPV_SPI0_TX_USING_DMA   1
#define SPV_SPI0_RX_USING_DMA   2
#define SPV_SPI1_TX_USING_DMA   1
#define SPV_SPI1_RX_USING_DMA   2



void hal_spi_init(uint32_t spi_port, SpiInitTypeDef* config_param);
HAL_StatusTypeDef hal_spi_transmit(uint32_t spi_port, uint8_t *send_buf, uint32_t send_length);
HAL_StatusTypeDef hal_spi_receive(uint32_t spi_port, uint8_t *recv_buf, uint32_t length);
HAL_StatusTypeDef hal_spi_transmit_receive(uint32_t spi_port, uint8_t *send_buf, uint8_t *recv_buf, uint32_t length);

int32_t hal_spi_tx_dma_init(int32_t spi_port, DMA_HandleTypeDef *dma_handle);
int32_t hal_spi_rx_dma_init(int32_t spi_port, DMA_HandleTypeDef *dma_handle);

HAL_StatusTypeDef hal_spi_transmit_dma(DMA_HandleTypeDef *hdma, uint32_t spi_port, uint8_t *send_buf, uint32_t length, void *param);
HAL_StatusTypeDef hal_spi_receive_dma(DMA_HandleTypeDef *hdma, uint32_t spi_port, uint8_t *recv_buf, uint32_t length);
HAL_StatusTypeDef hal_spi_transmit_receive_dma(spi_dma_handle *hdma, uint32_t spi_port, uint8_t *send_buf, uint8_t *recv_buf, uint32_t length);
void hal_spi_set_cpol_cpha(uint32_t spi_port, spi_clk_mode_t spi_clk_mode);
//void hal_spi_rx_interrupt_enable(uint32_t spi_port);
//int32_t hal_spi_set_rx_callback(int32_t spi_port, void *callback, void *param, uint32_t flag, spi_dma_handle *dma_handle);

#endif /* DRIVER_INCLUDE_HAL_HAL_SPI_H_ */
