#include "hal_spi.h"
#include "hc32_ll_dma.h"
#include "hc32_ll_aos.h"
#include "hc32_ll_interrupts.h"




void bsp_spi_init(void);
void bsp_spi_deinit(void);
void bsp_spi_active(void);
void bsp_spi_inactive(void);
int32_t bsp_spi_trans(const uint8_t *pu8TxBuf, uint32_t u32Size);
int32_t bsp_spi_receive(uint8_t *pu8RxBuf, uint32_t u32Size);

/*******************************************************************************
 * Local variable definitions ('static')
 ******************************************************************************/
stc_w25qxx_ll_t m_stcW25qxxLL = {
    .Delay    = DDL_DelayMS,
    .Init     = bsp_spi_init,
    .DeInit   = bsp_spi_deinit,
    .Active   = bsp_spi_active,
    .Inactive = bsp_spi_inactive,
    .Trans    = bsp_spi_trans,
    .Receive  = bsp_spi_receive,
};

 
void bsp_spi_active(void)
{
    BSP_SPI_CS_ACTIVE();
}

 
void bsp_spi_inactive(void)
{
    BSP_SPI_CS_INACTIVE();
}


void bsp_spi_init(void)
{
    stc_gpio_init_t stcGpioInit;
	
    stc_spi_init_t  stcSpiInit;
    stc_spi_delay_t stcSpiDelayCfg;
	

//    (void)GPIO_StructInit(&stcGpioInit);
//    stcGpioInit.u16PinDrv = PIN_HIGH_DRV;
//    (void)GPIO_Init(BSP_SPI_SCK_PORT, BSP_SPI_SCK_PIN, &stcGpioInit);
//    (void)GPIO_Init(BSP_SPI_MOSI_PORT, BSP_SPI_MOSI_PIN, &stcGpioInit);
//		(void)GPIO_Init(BSP_SPI_MISO_PORT, BSP_SPI_MISO_PIN, &stcGpioInit);
//	
//		GPIO_SetDebugPort(GPIO_PIN_TDI, DISABLE);
//    stcGpioInit.u16PinDir = PIN_DIR_OUT;
//    stcGpioInit.u16PinState = PIN_STAT_SET;
//    (void)GPIO_Init(BSP_SPI_CS_PORT, BSP_SPI_CS_PIN,  &stcGpioInit);
	
		GPIO_SetDebugPort(GPIO_PIN_TDI, DISABLE);
 		GPIO_SetFunc(BSP_SPI_CS_PORT, BSP_SPI_CS_PIN, BSP_SPI_CS_PIN_FUNC);
    GPIO_SetFunc(BSP_SPI_SCK_PORT, BSP_SPI_SCK_PIN, BSP_SPI_SCK_PIN_FUNC);
    GPIO_SetFunc(BSP_SPI_MOSI_PORT, BSP_SPI_MOSI_PIN, BSP_SPI_MOSI_PIN_FUNC);
    GPIO_SetFunc(BSP_SPI_MISO_PORT, BSP_SPI_MISO_PIN, BSP_SPI_MISO_PIN_FUNC);

    /* Clear initialize structure */
    (void)SPI_StructInit(&stcSpiInit);
    (void)SPI_DelayStructInit(&stcSpiDelayCfg);

    /* Configure peripheral clock */
    FCG_Fcg1PeriphClockCmd(BSP_SPI_PERIPH_CLK, ENABLE);

    /* SPI De-initialize */
    SPI_DeInit(BSP_SPI_UNIT);
    /* Configuration SPI structure */
    stcSpiInit.u32WireMode          = SPI_4_WIRE;
    stcSpiInit.u32TransMode         = SPI_FULL_DUPLEX;
    stcSpiInit.u32MasterSlave       = SPI_MASTER;
    stcSpiInit.u32ModeFaultDetect   = SPI_MD_FAULT_DETECT_DISABLE;
    stcSpiInit.u32Parity            = SPI_PARITY_INVD;
    stcSpiInit.u32SpiMode           = SPI_MD_0;
    stcSpiInit.u32BaudRatePrescaler = SPI_BR_CLK_DIV4;
    stcSpiInit.u32DataBits          = SPI_DATA_SIZE_8BIT;
    stcSpiInit.u32FirstBit          = SPI_FIRST_MSB;
    (void)SPI_Init(BSP_SPI_UNIT, &stcSpiInit);

    stcSpiDelayCfg.u32IntervalDelay = SPI_INTERVAL_TIME_8SCK;
    stcSpiDelayCfg.u32ReleaseDelay  = SPI_RELEASE_TIME_8SCK;
    stcSpiDelayCfg.u32SetupDelay    = SPI_SETUP_TIME_1SCK;
    (void)SPI_DelayTimeConfig(BSP_SPI_UNIT, &stcSpiDelayCfg);
    SPI_Cmd(BSP_SPI_UNIT, ENABLE);




//    stc_spi_init_t stcSpiInit;

//    /* Configure Port */
//    GPIO_SetFunc(BSP_SPI_CS_PORT,   BSP_SPI_CS_PIN,   BSP_SPI_CS_PIN_FUNC);
//    GPIO_SetFunc(BSP_SPI_SCK_PORT,  BSP_SPI_SCK_PIN,  BSP_SPI_SCK_PIN_FUNC);
//    GPIO_SetFunc(BSP_SPI_MOSI_PORT, BSP_SPI_MOSI_PIN, BSP_SPI_MOSI_PIN_FUNC);
//    GPIO_SetFunc(BSP_SPI_MISO_PORT, BSP_SPI_MISO_PIN, BSP_SPI_MISO_PIN_FUNC);

//    /* Configuration SPI */
//    FCG_Fcg1PeriphClockCmd(BSP_SPI_PERIPH_CLK, ENABLE);
//    SPI_StructInit(&stcSpiInit);
//    stcSpiInit.u32WireMode          = SPI_4_WIRE;
//    stcSpiInit.u32TransMode         = SPI_FULL_DUPLEX;
//    stcSpiInit.u32MasterSlave       = SPI_MASTER;
//    stcSpiInit.u32Parity            = SPI_PARITY_INVD;
//    stcSpiInit.u32SpiMode           = SPI_MD_0;
//    stcSpiInit.u32BaudRatePrescaler = SPI_BR_CLK_DIV96;
//    stcSpiInit.u32DataBits          = SPI_DATA_SIZE_8BIT;
//    stcSpiInit.u32FirstBit          = SPI_FIRST_MSB;
//    stcSpiInit.u32FrameLevel        = SPI_1_FRAME;
//    (void)SPI_Init(BSP_SPI_UNIT, &stcSpiInit);
//    SPI_Cmd(BSP_SPI_UNIT, ENABLE);
}

 
void bsp_spi_deinit(void)
{
    /* SPI De-initialize */
    SPI_DeInit(BSP_SPI_UNIT);
}

 
int32_t bsp_spi_trans(const uint8_t *pu8TxBuf, uint32_t u32Size)
{
    return SPI_Trans(BSP_SPI_UNIT, pu8TxBuf, u32Size, BSP_SPI_TIMEOUT);
}

 
int32_t bsp_spi_receive(uint8_t *pu8RxBuf, uint32_t u32Size)
{
    return SPI_Receive(BSP_SPI_UNIT, pu8RxBuf, u32Size, BSP_SPI_TIMEOUT);
}

 
void bsp_w25qxx_init(void)
{
    (void)W25QXX_Init(&m_stcW25qxxLL);
}

 
void BSP_W25QXX_DeInit(void)
{
    (void)W25QXX_DeInit(&m_stcW25qxxLL);
}

 
int32_t BSP_W25QXX_Write(uint32_t u32Addr, const uint8_t *pu8Data, uint32_t u32NumByteToWrite)
{
    uint32_t u32TempSize;
    uint32_t u32AddrOfst = 0UL;
    int32_t i32Ret = LL_ERR_INVD_PARAM;

    DDL_ASSERT((u32Addr + u32NumByteToWrite) <= W25Q64_MAX_ADDR);

    if ((pu8Data != NULL) && (u32NumByteToWrite > 0UL)) {
        while (u32NumByteToWrite != 0UL) {
            if (u32NumByteToWrite >= W25Q64_PAGE_SIZE) {
                u32TempSize = W25Q64_PAGE_SIZE;
            } else {
                u32TempSize = u32NumByteToWrite;
            }

            i32Ret = W25QXX_PageProgram(&m_stcW25qxxLL, u32Addr, (const uint8_t *)&pu8Data[u32AddrOfst], u32TempSize);
            if (i32Ret != LL_OK) {
                break;
            }
            u32NumByteToWrite -= u32TempSize;
            u32AddrOfst += u32TempSize;
            u32Addr  += u32TempSize;
        }
    }

    return i32Ret;
}

void W25QXX_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)   
{ 			 		 
	uint16_t pageremain;	   
	pageremain=256-WriteAddr%256; //单页剩余的字节数		 	    
	if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//不大于256个字节
	while(1)
	{	   
		W25QXX_PageProgram(&m_stcW25qxxLL,WriteAddr,pBuffer,NumByteToWrite);
		if(NumByteToWrite==pageremain)break;//写入结束了
	 	else //NumByteToWrite>pageremain
		{
			pBuffer+=pageremain;
			WriteAddr+=pageremain;	

			NumByteToWrite-=pageremain;			  //减去已经写入了的字节数
			if(NumByteToWrite>256)pageremain=256; //一次可以写入256个字节
			else pageremain=NumByteToWrite; 	  //不够256个字节了
		}
	}	    
} 
uint8_t flash_data_buffer[4096];
void spi_flash_write(uint32_t WriteAddr,uint8_t* pBuffer,uint16_t NumByteToWrite)   
{ 
	uint32_t secpos;
	uint16_t secoff;
	uint16_t secremain;	   
 	uint16_t i;    
	
 
	secpos=WriteAddr/4096;//扇区地址 0~511 for w25x16
	secoff=WriteAddr%4096;//在扇区内的偏移
	secremain=4096-secoff;//扇区剩余空间大小   

	if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大于4096个字节
	while(1) 
	{	
		BSP_W25QXX_Read(secpos*4096,flash_data_buffer,4096);
		
		for(i=0;i<secremain;i++)//校验数据
		{
			if(flash_data_buffer[secoff+i]!=0XFF)break;//需要擦除
		}
		if(i<secremain)//需要擦除
		{
			BSP_W25QXX_EraseSector(secpos);//擦除这个扇区

			for(i=0;i<secremain;i++)	   //复制
			{
				flash_data_buffer[i+secoff]=pBuffer[i];	
			}			

			W25QXX_Write_NoCheck(flash_data_buffer,secpos*4096,4096);//写入整个扇区  
	
		}
		else 
		{
			W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间.
		}
		if(NumByteToWrite==secremain)break;//写入结束了
		else//写入未结束
		{
			secpos++;//扇区地址增1
			secoff=0;//偏移位置为0 	 

			pBuffer+=secremain;  //指针偏移
			WriteAddr+=secremain;//写地址偏移	   
			NumByteToWrite-=secremain;				//字节数递减
			if(NumByteToWrite>4096)secremain=4096;	//下一个扇区还是写不完
			else secremain=NumByteToWrite;			//下一个扇区可以写完了
		}	 
	}
}
int32_t spi_flash_read(uint32_t u32Addr, uint8_t *pu8Data, uint32_t u32NumByteToRead)
{
    DDL_ASSERT((u32Addr + u32NumByteToRead) <= W25Q64_MAX_ADDR);
    return W25QXX_ReadData(&m_stcW25qxxLL, u32Addr, pu8Data, u32NumByteToRead);
}

int32_t BSP_W25QXX_Read(uint32_t u32Addr, uint8_t *pu8Data, uint32_t u32NumByteToRead)
{
    DDL_ASSERT((u32Addr + u32NumByteToRead) <= W25Q64_MAX_ADDR);
    return W25QXX_ReadData(&m_stcW25qxxLL, u32Addr, pu8Data, u32NumByteToRead);
}

 
int32_t BSP_W25QXX_EraseSector(uint32_t u32Addr)
{
    DDL_ASSERT(u32Addr < W25Q64_MAX_ADDR);
    return W25QXX_EraseSector(&m_stcW25qxxLL, u32Addr);
}

 
int32_t BSP_W25QXX_EraseChip(void)
{
    return W25QXX_EraseChip(&m_stcW25qxxLL);
}



