// SPI接口驱动(GPIO模拟)
// 杭州秒寻科技有限公司
// 周涛
// 2023-09-30
// 4线制，模式0
// 注意：在使用读写接口前，请先根据项目具体使用GPIO管脚替换头文件中的12个宏

#include "includes.h"

// 写片选信号
// byBitValue:片选信号，只能是0或者1
// 注意：每一个SPI都需要单独一个函数
void driver_synctx_spi_wr_cs(uint8 byBitValue)
{
    GPIO_WriteBit(DRIVER_SYNCTX_SPIGPIO_CS_PORT, DRIVER_SYNCTX_SPIGPIO_CS_PIN, (BitAction)byBitValue);
    return;
}

// 写时钟
// byBitValue:只能是0或者1
void driver_synctx_spi_wr_sck(uint8 byBitValue)
{
    GPIO_WriteBit(DRIVER_SYNCTX_SPIGPIO_SCK_PORT, DRIVER_SYNCTX_SPIGPIO_SCK_PIN, (BitAction)byBitValue);
    return;
}

// 写MOSI
// byBitValue:只能是0或者1
void driver_synctx_spi_wr_mosi(uint8 byBitValue)
{
    GPIO_WriteBit(DRIVER_SYNCTX_SPIGPIO_MOSI_PORT, DRIVER_SYNCTX_SPIGPIO_MOSI_PIN, (BitAction)byBitValue);
    return;
}

// 读MISO
uint8 driver_synctx_spi_rd_miso()
{
    return GPIO_ReadInputDataBit(DRIVER_SYNCTX_SPIGPIO_MISO_PORT, DRIVER_SYNCTX_SPIGPIO_MISO_PIN);
}

// 同步芯片硬复位
void driver_synctx_spi_reset()
{
    GPIO_WriteBit(DRIVER_SYNCTX_SPIGPIO_RESET_PORT, DRIVER_SYNCTX_SPIGPIO_RESET_PIN, (BitAction)0x01);
    driver_delay_nxus(200);
    GPIO_WriteBit(DRIVER_SYNCTX_SPIGPIO_RESET_PORT, DRIVER_SYNCTX_SPIGPIO_RESET_PIN, (BitAction)0x00);
    driver_delay_nxus(200);
}

// 初始化SPI接口所用到的GPIO管脚
// 注意：具体管脚需要根据项目确定
void driver_synctx_spi_init()
{
    GPIO_InitTypeDef stGpio = {0};

    // 组织GPIO公共数据
    stGpio.GPIO_Speed = GPIO_Speed_25MHz;
    stGpio.GPIO_PuPd = GPIO_PuPd_NOPULL;

    // 初始化CS
    RCC_AHB1PeriphClockCmd(DRIVER_SYNCTX_SPIGPIO_CS_CLK, ENABLE);
    stGpio.GPIO_Mode = GPIO_Mode_OUT;
    stGpio.GPIO_OType = GPIO_OType_PP;
    stGpio.GPIO_Pin = DRIVER_SYNCTX_SPIGPIO_CS_PIN;
    GPIO_Init(DRIVER_SYNCTX_SPIGPIO_CS_PORT, &stGpio);

    // 初始化SCK
    RCC_AHB1PeriphClockCmd(DRIVER_SYNCTX_SPIGPIO_SCK_CLK, ENABLE);
    stGpio.GPIO_Mode = GPIO_Mode_OUT;
    stGpio.GPIO_OType = GPIO_OType_PP;
    stGpio.GPIO_Pin = DRIVER_SYNCTX_SPIGPIO_SCK_PIN;
    GPIO_Init(DRIVER_SYNCTX_SPIGPIO_SCK_PORT, &stGpio);

    // 初始化MOSI
    RCC_AHB1PeriphClockCmd(DRIVER_SYNCTX_SPIGPIO_MOSI_CLK, ENABLE);
    stGpio.GPIO_Mode = GPIO_Mode_OUT;
    stGpio.GPIO_OType = GPIO_OType_PP;
    stGpio.GPIO_Pin = DRIVER_SYNCTX_SPIGPIO_MOSI_PIN;
    GPIO_Init(DRIVER_SYNCTX_SPIGPIO_MOSI_PORT, &stGpio);

    // 初始化MISO
    RCC_AHB1PeriphClockCmd(DRIVER_SYNCTX_SPIGPIO_MISO_CLK, ENABLE);
    stGpio.GPIO_Mode = GPIO_Mode_IN;
    stGpio.GPIO_Pin = DRIVER_SYNCTX_SPIGPIO_MISO_PIN;
    GPIO_Init(DRIVER_SYNCTX_SPIGPIO_MISO_PORT, &stGpio);

    // 初始化硬复位管脚
    RCC_AHB1PeriphClockCmd(DRIVER_SYNCTX_SPIGPIO_RESET_CLK, ENABLE);
    stGpio.GPIO_Mode = GPIO_Mode_IN;
    stGpio.GPIO_Pin = DRIVER_SYNCTX_SPIGPIO_RESET_PIN;
    GPIO_Init(DRIVER_SYNCTX_SPIGPIO_RESET_PORT, &stGpio);
    GPIO_WriteBit(DRIVER_SYNCTX_SPIGPIO_RESET_PORT, DRIVER_SYNCTX_SPIGPIO_RESET_PIN, (BitAction)0x00);

    // 设置默认值（模式0）
    driver_synctx_spi_wr_cs(1);  // 片选拉高
    driver_synctx_spi_wr_sck(0); // 时钟拉低
    driver_delay_nxms(10);

    return;
}

// 启动SPI信号
void driver_synctx_spi_start()
{
    driver_synctx_spi_wr_cs(0); // 选择SPI
    driver_delay_nxus(10);

    return;
}

// 停止SPI信号
void driver_synctx_spi_stop()
{
    driver_delay_nxus(10);
    driver_synctx_spi_wr_cs(1); // 不选择SPI

    return;
}

// 交换一个字节(读写都行)
// spi模式0，若要修改成其他模式，需要做该相位或者极性
uint8 driver_synctx_spi_exchange_byte(uint8 byData)
{
    uint8 byReceiveData = 0;
    uint8 bySendTmp = 0;
    uint8 byReceiveTmp = 0;

    // 交换数据
    for (uint8 i = 0; i < 8; i++)
    {
        // 移入数据
        bySendTmp = byData & (0x80 >> i);
        driver_synctx_spi_wr_mosi(bySendTmp);

        // 时钟产生上升沿
        driver_synctx_spi_wr_sck(1);

        // 接收从机数据
        byReceiveTmp = driver_synctx_spi_rd_miso();
        if (byReceiveTmp == 1)
        {
            byReceiveTmp = 0x80 >> i;
            byReceiveData |= byReceiveTmp;
        }

        // 时钟产生下降沿
        driver_synctx_spi_wr_sck(0);
    }

    return byReceiveData;
}