#ifndef SW_LIB_SPI_H
#define SW_LIB_SPI_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>

#define HIGH    1
#define LOW     0
#define NOP()   0
#define DELAY1US() NOP()


/**
 * @brief   SPI通信模式枚举
 **/
typedef enum {
    Mode0,  // 时钟空闲状态为低电平，数据在时钟的下降沿采样
    Mode1,  // 时钟空闲状态为低电平，数据在时钟的上升沿采样
    Mode2,  // 时钟空闲状态为高电平，数据在时钟的下降沿采样
    Mode3   // 时钟空闲状态为高电平，数据在时钟的上升沿采样
} mode;

/**
 * @brief   数据端序枚举
 **/
typedef enum {
    LTL,  // 小端模式，低字节在低地址
    LTB,  // 小端模式，低字节在高地址
    BTB,  // 大端模式，低字节在低地址
    BTL   // 大端模式，低字节在高地址
} endian;
/**
 * @brief   SPI设备结构体
 **/
typedef struct {
    uint8_t (*MOSI_SET)(uint8_t);   // 设置MOSI引脚状态的函数指针
    uint8_t (*SCK_SET)(uint8_t);    // 设置SCK引脚状态的函数指针
    uint8_t (*CS_SET)(uint8_t);     // 设置CS引脚状态的函数指针
    uint8_t (*MISO)();              // 读取MISO引脚状态的函数指针
    mode MODE;                      // SPI模式
    uint8_t CS;                      // CS引脚编号
    endian ENDIAN;                  // 数据端序
} SW_Dev_Spi;

/**
 * @brief   向 SPI 设备写入一个字节并读取返回的数据
 * @param   Dev: [输入]       SPI 设备
 * @param   Write_Date: [输入]要写入的数据
 * @return  读取到的数据
 **/
uint8_t SW_SPI_RW(SW_Dev_Spi Dev, uint8_t Write_Date);

/**
 * @brief   向 SPI 设备写入数据流
 * @param   Dev: [输入]       SPI 设备
 * @param   Write_Date: [输入]要写入的数据流指针
 * @param   Len: [输入]       数据流长度
 * @return  void
 **/
void SW_SPI_WL(SW_Dev_Spi Dev, uint8_t *Write_Date, uint32_t Len);

/**
 * @brief   从 SPI 设备读取数据流
 * @param   Dev: [输入]       SPI 设备
 * @param   Read_Date: [输出]存储读取数据的缓冲区指针
 * @param   Len: [输入]       读取数据流长度
 * @return  void
 **/
void SW_SPI_RL(SW_Dev_Spi Dev, uint8_t *Read_Date, uint32_t Len);

/**
 * @brief   向 SPI 设备写入数据并读取返回数据流
 * @param   Dev: [输入]       SPI 设备
 * @param   Read_Date: [输出]存储读取数据的缓冲区指针
 * @param   Write_Date: [输入]要写入的数据流指针
 * @param   Len: [输入]       数据流长度
 * @return  void
 **/
void SW_SPI_RWL(SW_Dev_Spi Dev, uint8_t *Read_Date, uint8_t *Write_Date, uint32_t Len);

/**
 * @brief   向 SPI 设备写入一个字（16位）并读取返回的数据
 * @param   Dev: [输入]       SPI 设备
 * @param   Write_Date: [输入]要写入的数据
 * @return  读取到的数据
 **/
uint16_t SW_SPI_RW16(SW_Dev_Spi Dev, uint16_t Write_Date);

/**
 * @brief   从 SPI 设备读取数据流（16位）
 * @param   Dev: [输入]       SPI 设备
 * @param   Read_Date: [输出]存储读取数据的缓冲区指针
 * @param   Len: [输入]       读取数据流长度
 * @return  void
 **/
void SW_SPI_RL16(SW_Dev_Spi Dev, uint16_t *Read_Date, uint32_t Len);

/**
 * @brief   向 SPI 设备写入数据流（16位）
 * @param   Dev: [输入]       SPI 设备
 * @param   Write_Date: [输入]要写入的数据流指针
 * @param   Len: [输入]       数据流长度
 * @return  void
 **/
void SW_SPI_WL16(SW_Dev_Spi Dev, uint16_t *Write_Date, uint32_t Len);

/**
 * @brief   向 SPI 设备写入数据并读取返回数据流（16位）
 * @param   Dev: [输入]       SPI 设备
 * @param   Read_Date: [输出]存储读取数据的缓冲区指针
 * @param   Write_Date: [输入]要写入的数据流指针
 * @param   Len: [输入]       数据流长度
 * @return  void
 **/
void SW_SPI_RWL16(SW_Dev_Spi Dev, uint16_t *Read_Date, uint16_t *Write_Date, uint32_t Len);
#ifdef __cplusplus
}
#endif
#endif //SW_LIB_SPI_H
