#include <stdlib.h>
#include "bsp.h"
#include "ff.h"

/*****************************************************************************************
 * System Clock
 ****************************************************************************************/

/*****************************************************************************************
* 函数名称: SystemClockConfig
* 功能描述: 系统时钟设置
* 参    数: 无
* 返 回 值: 无
*****************************************************************************************/
static void SystemClockConfig(void)
{
	stc_clk_sysclk_cfg_t    stcSysClkCfg;
	stc_clk_xtal_cfg_t      stcXtalCfg;
	stc_clk_mpll_cfg_t      stcMpllCfg;
	stc_sram_config_t       stcSramConfig;

	MEM_ZERO_STRUCT(stcSysClkCfg);
	MEM_ZERO_STRUCT(stcXtalCfg);
	MEM_ZERO_STRUCT(stcMpllCfg);
	MEM_ZERO_STRUCT(stcSramConfig);

	/* Set bus clk div. */
	stcSysClkCfg.enHclkDiv  = ClkSysclkDiv1;
	stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;
	stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;
	stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;
	stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;
	stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;
	stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;
	CLK_SysClkConfig(&stcSysClkCfg);

	/* Config Xtal and Enable Xtal */
    stcXtalCfg.enMode = ClkXtalModeOsc;
    stcXtalCfg.enDrv = ClkXtalLowDrv;
    stcXtalCfg.enFastStartup = Enable;
    CLK_XtalConfig(&stcXtalCfg);
    CLK_XtalCmd(Enable);

//	/* Config Hrc and enable HRC */
//	CLK_HrcTrim(SystemCoreClock);
//	CLK_HrcCmd(Enable);
	
	/* sram init include read/write wait cycle setting */
	stcSramConfig.u8SramIdx = Sram12Idx | Sram3Idx | SramHsIdx | SramRetIdx;
	stcSramConfig.enSramRC = SramCycle2;
	stcSramConfig.enSramWC = SramCycle2;
	SRAM_Init(&stcSramConfig);

	/* flash read wait cycle setting */
	EFM_Unlock();
	EFM_SetLatency(EFM_LATENCY_5);
	EFM_Lock();

	/* MPLL config (XTAL / pllmDiv * plln / PllpDiv = 200M). */
	stcMpllCfg.pllmDiv = 1ul;
	stcMpllCfg.plln    = 50ul;
	stcMpllCfg.PllpDiv = 2ul;
	stcMpllCfg.PllqDiv = 2ul;
	stcMpllCfg.PllrDiv = 2ul;
	CLK_SetPllSource(ClkPllSrcXTAL);
	CLK_MpllConfig(&stcMpllCfg);

	/* Enable MPLL. */
	CLK_MpllCmd(Enable);
	/* Wait MPLL ready. */
	while(Set != CLK_GetFlagStatus(ClkFlagMPLLRdy))
	{
			;
	}
	/* Switch driver ability */
	PWC_HS2HP();
	/* Switch system clock source to MPLL. */
	CLK_SetSysClkSource(CLKSysSrcMPLL);
}


/*****************************************************************************************
 * Debug Uart
 ****************************************************************************************/

/*****************************************************************************************
* 函数名称: DbgUartRec
* 功能描述: 调试串口接收函数
* 参    数: 无
* 返 回 值: 返回收到的字符
*****************************************************************************************/
static uint8_t DbgUartRec(void)
{
	uint16_t u16Data = USART_RecData(DBG_USART_CH);
	return (uint8_t)u16Data;
}


/*****************************************************************************************
* 函数名称: DBGUsartErrIrqCallback
* 功能描述: 调试串口错误中断回调函数
* 参    数: 无
* 返 回 值: 无
*****************************************************************************************/
static void DBGUsartErrIrqCallback(void)
{
	if(DBG_USART_CH->SR_f.ORE) {
		DBG_USART_CH->CR1_f.CORE = 1;
		USART_RecData(DBG_USART_CH);
	}
	
	if(DBG_USART_CH->SR_f.PE)
		DBG_USART_CH->CR1_f.CPE = 1;
	
	if(DBG_USART_CH->SR_f.FE)
		DBG_USART_CH->CR1_f.CFE = 1;
}

/*****************************************************************************************
* 函数名称: DbgUsartRxIrqCallback
* 功能描述: 调试串口接收中断回调函数
* 参    数: 无
* 返 回 值: 无
*****************************************************************************************/
static void DbgUsartRxIrqCallback(void)
{
	uint8_t rData = DbgUartRec();
	DbgRxIrqCallback(rData);
}

/*****************************************************************************************
* 函数名称: DbgUart_Config
* 功能描述: 调试串口配置函数
* 参    数: BaudRate 串口波特率
* 返 回 值: 无
*****************************************************************************************/
void DbgUart_Config(uint32_t BaudRate)
{
	stc_usart_uart_init_t stcInitCfg;
	stc_irq_regi_conf_t stcIrqRegiCfg;
	en_result_t enRet;
	stc_port_init_t stcPortInit;

	MEM_ZERO_STRUCT(stcPortInit);
	
	stcPortInit.enPinOType = Pin_OType_Cmos;
	PORT_Init(DBG_USART_RX_PORT, DBG_USART_RX_PIN, &stcPortInit);
	PORT_Init(DBG_USART_TX_PORT, DBG_USART_TX_PIN, &stcPortInit);
	
	stcInitCfg.enClkMode = UsartIntClkCkNoOutput;
	stcInitCfg.enClkDiv = UsartClkDiv_1;
	stcInitCfg.enDataLength = UsartDataBits8;
	stcInitCfg.enDirection = UsartDataLsbFirst;
	stcInitCfg.enStopBit = UsartOneStopBit;
	stcInitCfg.enParity = UsartParityNone;
	stcInitCfg.enSampleMode = UsartSampleBit8;
	stcInitCfg.enDetectMode = UsartStartBitFallEdge;
	stcInitCfg.enHwFlow = UsartRtsEnable;
	
	PWC_Fcg1PeriphClockCmd(DBG_FCG1_PERIPH, Enable);
	
	PORT_SetFunc(DBG_USART_RX_PORT, DBG_USART_RX_PIN, DBG_USART_RX_FUNC, Disable);
	PORT_SetFunc(DBG_USART_TX_PORT, DBG_USART_TX_PIN, DBG_USART_TX_FUNC, Disable);
	
	enRet = USART_UART_Init(DBG_USART_CH, &stcInitCfg);
	if(enRet != Ok) {
		Error_Handler();
	}
	enRet = USART_SetBaudrate(DBG_USART_CH, BaudRate);
	if(enRet != Ok) {
		Error_Handler();
	}
	
	stcIrqRegiCfg.enIRQn = DBGUART_IRQn;
	stcIrqRegiCfg.pfnCallback = &DbgUsartRxIrqCallback;
	stcIrqRegiCfg.enIntSrc = DBG_USART_RI_NUM;
	enIrqRegistration(&stcIrqRegiCfg);
	NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
	NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
	NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);


	/* Set USART RX error IRQ */
	stcIrqRegiCfg.enIRQn = DBGUART_EI_IRQn;
	stcIrqRegiCfg.pfnCallback = &DBGUsartErrIrqCallback;
	stcIrqRegiCfg.enIntSrc = DBG_USART_EI_NUM;
	enIrqRegistration(&stcIrqRegiCfg);
	NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
	NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
	NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
	
#if 0	
	/* Set USART TX IRQ */
	stcIrqRegiCfg.enIRQn = Int002_IRQn;
	stcIrqRegiCfg.pfnCallback = &UsartTxIrqCallback;
	stcIrqRegiCfg.enIntSrc = USART_TI_NUM;
	enIrqRegistration(&stcIrqRegiCfg);
	NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
	NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
	NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);

	/* Set USART TX complete IRQ */
	stcIrqRegiCfg.enIRQn = Int003_IRQn;
	stcIrqRegiCfg.pfnCallback = &UsartTxCmpltIrqCallback;
	stcIrqRegiCfg.enIntSrc = USART_TCI_NUM;
	enIrqRegistration(&stcIrqRegiCfg);
	NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
	NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
	NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
#endif	
	USART_FuncCmd(DBG_USART_CH, UsartTx, Enable);
	USART_FuncCmd(DBG_USART_CH, UsartRx, Enable);
	USART_FuncCmd(DBG_USART_CH, UsartRxInt, Enable);
}

/*****************************************************************************************
* 函数名称: DebugUartSend
* 功能描述: 调试串口发送函数
* 参    数: sData 发送数据入口指针
            sLen  发送数据长度
* 返 回 值: 无
*****************************************************************************************/
void DebugUartSend(uint8_t *sData, uint16_t sLen)
{
	for(int i = 0; i < sLen; i++) {
		USART_SendData(DBG_USART_CH, sData[i]);
		while(USART_GetStatus(DBG_USART_CH, UsartTxComplete) == Reset);
	}
}

/*****************************************************************************************
* 函数名称: GPIO_Config
* 功能描述: GPIO配置函数
* 参    数: 无
* 返 回 值: 无
*****************************************************************************************/
static void GPIO_Config(void)
{
	stc_port_init_t stcPortInit;
	stc_port_pub_set_t stcPortPub;
	
	PORT_DebugPortSetting(TDO_SWO, Disable);
	PORT_DebugPortSetting(TDI, Disable);
	PORT_DebugPortSetting(TRST, Disable);
	
	MEM_ZERO_STRUCT(stcPortInit);
	MEM_ZERO_STRUCT(stcPortPub);
	
	stcPortPub.enReadWait = WaitCycle3;
	PORT_PubSetting(&stcPortPub);
	
	stcPortInit.enPinMode = Pin_Mode_Out;
	stcPortInit.enPinOType = Pin_OType_Cmos;
	stcPortInit.enPinDrv = Pin_Drv_H;
	stcPortInit.enPullUp = Disable;
	
	PORT_Init(KEY_LED_PORT, KEY_LED_PIN, &stcPortInit);
	PORT_ResetBits(KEY_LED_PORT, KEY_LED_PIN);
	
	PORT_Init(BAT_LED_R_PORT, BAT_LED_R_PIN, &stcPortInit);
	PORT_ResetBits(BAT_LED_R_PORT, BAT_LED_R_PIN);
	
	PORT_Init(BAT_LED_G_PORT, BAT_LED_G_PIN, &stcPortInit);
	PORT_ResetBits(BAT_LED_G_PORT, BAT_LED_G_PIN);
	
	PORT_Init(STATE_LED_R_PORT, STATE_LED_R_PIN, &stcPortInit);
	PORT_ResetBits(STATE_LED_R_PORT, STATE_LED_R_PIN);
	
	PORT_Init(STATE_LED_G_PORT, STATE_LED_G_PIN, &stcPortInit);
	PORT_ResetBits(STATE_LED_G_PORT, STATE_LED_G_PIN);
}

void Error_Handler(void)
{
	while(1){ ; }
}

/*****************************************************************************************
 * Watch Dog
 ****************************************************************************************/

/*****************************************************************************************
* 函数名称: FeedDog
* 功能描述: 看门狗喂狗函数
* 参    数: 无
* 返 回 值: 无
*****************************************************************************************/
void FeedDog(void)
{
#if (WATCH_DOG == 1)	
	 SWDT_RefreshCounter();
#endif	
}

void BSP_Init(void)
{
	SystemClockConfig();
	GPIO_Config();
	DbgUart_Config(500000);

	FeedDog();
	SysTick_Init(1000);
	FeedDog();
}

void FlashWrite(uint32_t Addr, uint32_t *wData, uint8_t wLen)
{
//	while(Ok != Flash_SectorErase(BOOT_PARA_ADDRESS));
//	for(int i = 0; i < wLen / 4; i++) {
//		Flash_WriteWord(BOOT_PARA_ADDRESS + i * 4, wData[i]);
//	}

	EFM_Unlock();

	/* Enable flash. */
	EFM_FlashCmd(Enable);
	/* Wait flash ready. */
	while(Set != EFM_GetFlagStatus(EFM_FLAG_RDY)) {	; }
	/* Sequence program. */
	//EFM_SequenceProgram(FLASH_WRITE_ADDR, wLen, wData);
	for(int i = 0; i < wLen; i++) {
		EFM_SingleProgram(Addr + i * 4, wData[i]);
	}
	
	EFM_Lock();
}

static void FlashRead(uint32_t *rData, uint8_t rLen)
{
	uint32_t u32Addr = BOOT_PARA_ADDRESS;
	for(int i = 0; i < rLen / 4; i++) {
		rData[i] = *((volatile uint32_t*)(u32Addr + i * 4));
	}
}

void ReadBootPara(BootPara rData)
{
	FlashRead((uint32_t *)rData, sizeof(BootPara_t));
}

void WriteBootPara(BootPara wData)
{
	int wLen;
	uint32_t *Data;
	
	Data = (uint32_t *)wData;
	wLen = sizeof(BootPara_t) / 4;
	EFM_Unlock();
	
	/* Enable flash. */
	EFM_FlashCmd(Enable);
	/* Wait flash ready. */
	while(Set != EFM_GetFlagStatus(EFM_FLAG_RDY)) {	; }

	/* Erase sector. */
	EFM_SectorErase(BOOT_PARA_ADDRESS);
	
	for(int i = 0; i < wLen; i++) {
		EFM_SingleProgram(BOOT_PARA_ADDRESS + i * 4, Data[i]);
	}
	/* Lock EFM. */
	EFM_Lock();
}

void EraseFlash(void)
{
	EFM_Unlock();
	EFM_FlashCmd(Enable);
	while(Set != EFM_GetFlagStatus(EFM_FLAG_RDY)) {	; }
	
	for(int Addr = APP_ADDRESS; Addr < FLASH_SIZE; Addr += FLASH_SECTOR_SIZE) {
		EFM_SectorErase(Addr);
	}
	EFM_Lock();
}

/*****************************************************************************************
 * User Irq CallBack
 ****************************************************************************************/


/*****************************************************************************************
* 函数名称: DbgRxIrqCallback
* 功能描述: 调试串口接收中断外部重定向回调函数
* 参    数: 无
* 返 回 值: 无
*****************************************************************************************/
__weak void DbgRxIrqCallback(uint8_t rData)
{
	
}

/*****************************************************************************************
* 函数名称: RS485Ch1RxIrqCallback
* 功能描述: RS485通道1串口接收中断外部重定向回调函数
* 参    数: 无
* 返 回 值: 无
*****************************************************************************************/
__weak void RS485Ch1RxIrqCallback(uint8_t rData)
{
	
}

/*****************************************************************************************
* 函数名称: RS485Ch2RxIrqCallback
* 功能描述: RS485通道1串口接收中断外部重定向回调函数
* 参    数: 无
* 返 回 值: 无
*****************************************************************************************/
__weak void RS485Ch2RxIrqCallback(uint8_t rData)
{

}
