#include "sr_spi.h"

#ifdef SR_USE_SPI

#include "sr_gpio.h"
#include "sr_log.h"

#ifdef SR_USE_SPI1
SPI_InitType spi1Handle;

#endif

#ifdef SR_USE_SPI2
SPI_InitType spi2Handle;

#endif

static BSP_SPI_INFO_T _SpiInfo[] =
{

#ifdef SR_USE_SPI1
		{		
			.trdHandle = &spi1Handle,
			.instance = SPI1,
			.srId = SR_SPI1,
		},
#endif

#ifdef SR_USE_SPI2
		{
			.trdHandle = &spi2Handle,
			.instance = SPI2,
			.srId = SR_SPI2,
		},
#endif

};

static SR_SPI_DEV_T gs_spiDevice[sizeof(_SpiInfo) / sizeof(_SpiInfo[0])] = {0};


void HAL_SPI_MspDeInit(SPI_Module *instance);
void HAL_SPI_MspInit(SPI_Module *instance);

SR_DEVICE_T *BspSpiOpen(SR_SPI_ID_E spiId)
{
    uint8_t i;
	uint8_t devNum = sizeof(_SpiInfo) / sizeof(BSP_SPI_INFO_T);
	SR_SPI_DEV_T *spiDev = SR_NULL;

	for (i = 0; i < devNum; i++)
	{
		if (spiId == _SpiInfo[i].srId)
		{
			spiDev = &gs_spiDevice[i];
			spiDev->parent.deviceData = &_SpiInfo[i]; // 绑定设备信息数据
			break;
		}
	}

	return (spiDev) ? (&(spiDev->parent)) : SR_NULL;

}

int BspSpiClose(SR_DEVICE_T *dev)
{
    BSP_SPI_INFO_T *info = (BSP_SPI_INFO_T *)dev->deviceData;
	SR_SPI_DEV_T *spiDev = (SR_SPI_DEV_T *)dev;

    // 检查有效性检查
    if(!dev || !info || !info->trdHandle) return SR_INVALID;

    //CS 引脚去初始化
    SR_HalGpioDeinit(spiDev->csId); 

    // 调用原厂接口
	SPI_Module *instance = (SPI_Module *)info->instance;

    //MISO/MOSI/CLK 引脚去初始化
    HAL_SPI_MspDeInit(instance);

    SPI_Enable(instance, DISABLE);
    SPI_I2S_DeInit(instance);

    return SR_OK;

}
int BspSpiConfig(SR_DEVICE_T *dev, SR_SPI_CFG_T *cfg)
{
    BSP_SPI_INFO_T *info = (BSP_SPI_INFO_T *)dev->deviceData;
	SR_SPI_DEV_T *spiDev = (SR_SPI_DEV_T *)dev;
	int ret = -1;
	
	// 检查有效性检查
    if(!dev || !cfg || !info || !info->trdHandle) return SR_INVALID;

    //保存cs id和极性
    spiDev->csId = cfg->csId;
    spiDev->csPol = cfg->csPol;

   
    //CS 引脚初始化,片选无效
    SR_GPIO_CFG_T gpioCfg = {0};
	
	gpioCfg.gpioMode = SR_GPIO_OUTPUT;		   // 输出
	gpioCfg.pull = SR_GPIO_NP;				   // 无上下拉
	gpioCfg.initLvl = (cfg->csPol)? SR_GPIO_LOW:SR_GPIO_HIGH; // 初始低电平
	ret = SR_HalGpioInit(cfg->csId, &gpioCfg);  // 初始化
    if(ret != SR_OK)  return SR_FAIL;

    // 调用原厂接口
    SPI_InitType SPI_InitStructure;
	SPI_Module *instance = (SPI_Module *)info->instance;

    //MISO/MOSI/CLK 引脚初始化
    HAL_SPI_MspInit(instance);

    /*!< SPI configuration */
    SPI_InitStructure.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;  //默认全双工
    SPI_InitStructure.SpiMode       = cfg->mode;
    SPI_InitStructure.DataLen       = cfg->dw;
    SPI_InitStructure.CLKPOL        = cfg->cpol;
    SPI_InitStructure.CLKPHA        = cfg->cpha;
    SPI_InitStructure.NSS           = SPI_NSS_SOFT;  //软件片选

    SPI_InitStructure.BaudRatePres = cfg->bdPrescaler;

    SPI_InitStructure.FirstBit = cfg->order;
    SPI_InitStructure.CRCPoly  = 7;
    SPI_Init(instance, &SPI_InitStructure);

    /*!< Enable the sFLASH_SPI  */
    SPI_Enable(instance, ENABLE);
    
    return SR_OK;
}

static uint8_t _SpiSendByte(SPI_Module *instance,uint8_t byte)
{
    /*!< Loop while DAT register in not emplty */
    while (SPI_I2S_GetStatus(instance, SPI_I2S_TE_FLAG) == RESET);

    /*!< Send byte through the SPI1 peripheral */
    SPI_I2S_TransmitData(instance, byte);

    /*!< Wait to receive a byte */
    while (SPI_I2S_GetStatus(instance, SPI_I2S_RNE_FLAG) == RESET);

    /*!< Return the byte read from the SPI bus */
    return SPI_I2S_ReceiveData(instance);
}


int BspSpiReadReg(SR_DEVICE_T *dev, uint32_t reg,uint16_t regLen, uint8_t *buff, uint16_t buffLen)
{
    BSP_SPI_INFO_T *info = (BSP_SPI_INFO_T *)dev->deviceData;
	SR_SPI_DEV_T *spiDev = (SR_SPI_DEV_T *)dev;
    uint8_t i,regAddr[4] = {0};


    // 检查有效性检查
    if(!dev || !info || !info->trdHandle || (regLen<=0 || regLen>4)) return SR_INVALID;

    // 复制寄存器地址
    for (i = 0; i < regLen; i++)
        regAddr[i] = (reg >> (8 * (regLen - 1 - i)) & 0xFF);

    // CS 使能处理
    SR_HalGpioWrite(spiDev->csId, (spiDev->csPol) ? SR_GPIO_HIGH:SR_GPIO_LOW);

    // 调用原厂接口.WARN：目前只考虑了8bit数据宽度，待优化
	SPI_Module *instance = (SPI_Module *)info->instance;

    //发送寄存器地址
    for(i = 0;i<regLen; i++) _SpiSendByte(instance,regAddr[i]);
    
    //接收数据
    if(buff && buffLen>0)
    {
         for(i = 0;i<buffLen; i++)  buff[i] = _SpiSendByte(instance,SPI_DUMMY_BYTE);
    }

    
    // CS 失能处理
    SR_HalGpioWrite(spiDev->csId, (spiDev->csPol) ? SR_GPIO_LOW : SR_GPIO_HIGH);

    return SR_OK;

}


int BspSpiWriteReg(SR_DEVICE_T *dev, uint32_t reg,uint16_t regLen,uint8_t *buff, uint16_t buffLen)
{
    BSP_SPI_INFO_T *info = (BSP_SPI_INFO_T *)dev->deviceData;
	SR_SPI_DEV_T *spiDev = (SR_SPI_DEV_T *)dev;

    uint8_t i,regAddr[4] = {0};


    // 检查有效性检查
    if(!dev || !info || !info->trdHandle || (regLen<=0 || regLen>4)) return SR_INVALID;

    // 复制寄存器地址
    for (i = 0; i < regLen; i++)
        regAddr[i] = (reg >> (8 * (regLen - 1 - i)) & 0xFF);

    // CS 使能处理
    SR_HalGpioWrite(spiDev->csId, (spiDev->csPol) ? SR_GPIO_HIGH:SR_GPIO_LOW);

    // 调用原厂接口.WARN：目前只考虑了8bit数据宽度，待优化
	SPI_Module *instance = (SPI_Module *)info->instance;
    //发送寄存器地址
    for(i = 0;i<regLen; i++) _SpiSendByte(instance,regAddr[i]);

    //发送数据
    if(buff && buffLen>0)
    {
         for(i = 0;i<buffLen; i++) _SpiSendByte(instance,buff[i]);
    }

    // CS 失能处理
    SR_HalGpioWrite(spiDev->csId, (spiDev->csPol) ? SR_GPIO_LOW : SR_GPIO_HIGH);

    return SR_OK;
}

int BspSpiWriteRead(SR_DEVICE_T *dev,uint8_t *txBuf,uint8_t *rxBuf,uint16_t len,uint8_t csCtrl)
{
    BSP_SPI_INFO_T *info = (BSP_SPI_INFO_T *)dev->deviceData;
	SR_SPI_DEV_T *spiDev = (SR_SPI_DEV_T *)dev;
    uint16_t i;

    // 检查有效性检查
    if(!dev || !info || !info->trdHandle) return SR_INVALID;

    // CS 使能处理
    if(csCtrl&SR_SPI_CS_SEL )
        SR_HalGpioWrite(spiDev->csId, (spiDev->csPol) ? SR_GPIO_HIGH:SR_GPIO_LOW);

    // 调用原厂接口
	SPI_Module *instance = (SPI_Module *)info->instance;
	
    if(txBuf && !rxBuf)
        for(i = 0;i<len; i++) _SpiSendByte(instance,txBuf[i]);
    else if(!txBuf && rxBuf)
        for(i = 0;i<len; i++) rxBuf[i]=_SpiSendByte(instance,SPI_DUMMY_BYTE);
    else
        for(i = 0;i<len; i++) rxBuf[i]=_SpiSendByte(instance,txBuf[i]);


    // CS 失能处理
    if(csCtrl&SR_SPI_CS_RLS )
        SR_HalGpioWrite(spiDev->csId, (spiDev->csPol) ? SR_GPIO_LOW : SR_GPIO_HIGH);

     return  SR_OK;
}   

void HAL_SPI_MspInit(SPI_Module *instance)
{

    //GPIO配置
    SR_GPIO_CFG_T gpioCfg = {0};
    if(instance==SPI1)
    {
        /* SPI1 clock enable */
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_SPI1, ENABLE);
     	
        //SCK
        gpioCfg.gpioMode = SR_GPIO_AF_OUTPUT;   // 复用推挽输出
        gpioCfg.altFun =  BSP_SPI1_SCK_AF;      // 复用功能
        gpioCfg.pull = SR_GPIO_NP;				// 无上下拉
        SR_HalGpioInit(BSP_SPI1_SCK_PIN, &gpioCfg);  // 初始化

        //MOSI
        gpioCfg.altFun =  BSP_SPI1_MOSI_AF;           // 复用功能
        SR_HalGpioInit(BSP_SPI1_MOSI_PIN, &gpioCfg);  // 初始化

        //MISO
        gpioCfg.altFun =  BSP_SPI1_MISO_AF;           // 复用功能
        gpioCfg.gpioMode = SR_GPIO_INPUT;             // 输入
        SR_HalGpioInit(BSP_SPI1_MISO_PIN, &gpioCfg);  // 初始化

    }
    else
    {
        /* SPI2 clock enable */
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_SPI2, ENABLE);
   	
        //SCK
        gpioCfg.gpioMode = SR_GPIO_AF_OUTPUT;   // 复用推挽输出
        gpioCfg.altFun =  BSP_SPI2_SCK_AF;      // 复用功能
        gpioCfg.pull = SR_GPIO_NP;				// 无上下拉
        SR_HalGpioInit(BSP_SPI2_SCK_PIN, &gpioCfg);  // 初始化

        //MOSI
        gpioCfg.altFun =  BSP_SPI2_MOSI_AF;           // 复用功能
        SR_HalGpioInit(BSP_SPI2_MOSI_PIN, &gpioCfg);  // 初始化

        //MISO
        gpioCfg.altFun =  BSP_SPI2_MISO_AF;           // 复用功能
        gpioCfg.gpioMode = SR_GPIO_INPUT;             // 输入
        SR_HalGpioInit(BSP_SPI2_MISO_PIN, &gpioCfg);  // 初始化

    }

}

void HAL_SPI_MspDeInit(SPI_Module *instance)
{

  if(instance==SPI1)
    {
        /* SPI1 clock disable */
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_SPI1, DISABLE);

        SR_HalGpioDeinit(BSP_SPI1_MOSI_PIN);
        SR_HalGpioDeinit(BSP_SPI1_MISO_PIN);
        SR_HalGpioDeinit(BSP_SPI1_SCK_PIN);
    }
    else
    {
        /* SPI1 clock disable */
        RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_SPI2, DISABLE);

        SR_HalGpioDeinit(BSP_SPI2_MOSI_PIN);
        SR_HalGpioDeinit(BSP_SPI2_MISO_PIN);
        SR_HalGpioDeinit(BSP_SPI2_SCK_PIN);

    }
}

#endif  //end of SR_USE_SPI
