#include "includes.h"
#include <string.h>
#include <stdarg.h>

/**
 * BLV_C8_PB 串口使用情况
 * 	UART1 用与RCU进行双向通讯		115200  -> 对应设置 416
 * 	UART0 用于PB数据发送，没有接收	9600	-> 对应设置 5000
 * */
UART_t g_uart0;		
UART_t g_uart1;	
UART_t g_uart;	
MULIT_t m_send;	


void UARTx_Init(UART_IDX uart_id, Uart_prt prt_cf) {
	switch((U8_T)uart_id){
		case UART_0:
			UART0_DeInit();                                               //clear all UART Register
			UART_IO_Init(IO_UART0,0);                                     //use PA0.1->RXD0, PA0.0->TXD0
//			UARTInit(UART0,5000,UART_PAR_NONE);							  //baudrate=sysclock 48M/1000=4800
			UARTInitRxTxIntEn(UART0,5000,UART_PAR_EVEN);				  //baudrate=sysclock 48M/1000=4800,tx rx int enabled 
			UART0_Int_Enable();
			
			memset(&g_uart0,0,sizeof(UART_t));
	
			g_uart0.RecvTimeout = Recv_9600_TimeOut;
			g_uart0.processing_cf = prt_cf;				
			
			break;
		case UART_1:
			memset(&g_uart1,0,sizeof(UART_t));
			memset(&m_send,0,sizeof(MULIT_t));
	
			g_uart1.RecvTimeout = Recv_9600_TimeOut;
			g_uart1.processing_cf = prt_cf;
			
			m_send.BusState_Tick = SysTick_1ms;
			m_send.HighBit_Flag = 0x01;			
		
			//串口1-RX接收中断，用于串口2的通讯总线繁忙状态判断，2025-04-16
			GPIO_PullHigh_Init(GPIOA0,15);
			GPIO_IntGroup_Set(PA0,15,Selete_EXI_PIN15); 					//EXI0 set PB0.2
			GPIOA0_EXI_Init(EXI15); 										//PB0.2 as input
			EXTI_trigger_CMD(ENABLE,EXI_PIN15,_EXIFT); 					//ENABLE falling edge
			EXTI_trigger_CMD(ENABLE,EXI_PIN15,_EXIRT);
			EXTI_interrupt_CMD(ENABLE,EXI_PIN15); 						//enable EXI
			GPIO_EXTI_interrupt(GPIOA0,0b1000000000000000); 			//enable GPIOB02 as EXI
			EXI4_Int_Enable(); 			
		
	
			UART1_DeInit();                                                 //clear all UART Register
			UART_IO_Init(IO_UART1,2);                                    	//use PA0.13->RXD1, PB0.0->TXD1
			//UARTInit(UART1,416,UART_PAR_NONE);							  //baudrate=sysclock 48M/416=115200
			UARTInitRxTxIntEn(UART1,5000,UART_PAR_NONE);					//baudrate=sysclock 48M/416=115200 tx rx int enabled 
			UART1_Int_Enable();

			
			GPIO_Init(GPIOA0,LED_HLW_PIN,Output);
			GPIO_Init(GPIOA0,LED_BUS_PIN,Output);			
			GPIO_Init(GPIOB0,LED_STATUS_PIN,Output);
			HLW_LED_ON;
			BUS_LED_ON;
			STATUS_LED_ON;

			//485使能引脚初始化
			GPIO_Init(GPIOA0,UART485_DR_PIN,Output);
			GPIO_DriveStrength_EN(GPIOA0,UART485_DR_PIN);
			WRITE_LOW_DR;
	
			break;
		case UART_2:
			UART2_DeInit();                                                 //clear all UART Register
			UART_IO_Init(IO_UART2,2);                                    	//use PB0.4->RXD1, PB0.5->TXD1
			//UARTInit(UART2,416,UART_PAR_NONE);							  //baudrate=sysclock 48M/416=115200
			UARTInitRxTxIntEn(UART2,5000,UART_PAR_NONE);					//baudrate=sysclock 48M/416=115200 tx rx int enabled ,
			//CSP_UART_SET_CTRL(UART2,UART_TX_DONE_INT);					//UART_PAR_EVEN,偶校验.
			UART2_Int_Enable();
			
			memset(&g_uart,0,sizeof(UART_t));
	
			g_uart.RecvTimeout = Recv_9600_TimeOut;
			g_uart.processing_cf = prt_cf;			
			
			break;
	}
}


/*******************************************************************************
* Function Name  : UART0_RecvINT_Processing 
* Description    : 串口0 接收中断处理函数 - 接收中断调用
*******************************************************************************/
void UART0_RecvINT_Processing(char data){
	if((g_uart0.RecvLen + 1) >= USART_BUFFER_SIZE) g_uart0.RecvLen = 0;
	g_uart0.RecvBuffer[g_uart0.RecvLen++] = (U8_T)data;
	
	HLW_LED_OFF;
	
	g_uart0.RecvIdleTiming = SysTick_1ms;
	g_uart0.Receiving = 0x01;
}

void UART0_TASK(void){
	U8_T rev = 0xFF;
	if(g_uart0.Receiving == 0x01){
		if(SysTick_1ms - g_uart0.RecvIdleTiming > g_uart0.RecvTimeout){
			
			SYSCON_Int_Disable();					//2025-03-19,复制接收缓冲到数据处理缓冲内
			g_uart0.RecvIdleTiming = SysTick_1ms;
			memcpy(g_uart0.DealBuffer,g_uart0.RecvBuffer,g_uart0.RecvLen);
			g_uart0.DealLen = g_uart0.RecvLen;
			g_uart0.RecvLen = 0;
			g_uart0.Receiving = 0;
			SYSCON_Int_Enable();

#if DBG_LOG_EN
		//	Dbg_Println(DBG_BIT_SYS_STATUS, "UART0 revLen %d", g_uart0.DealLen);
		//	Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"UART0 buff",g_uart0.DealBuffer,g_uart0.DealLen);
#endif
			if(g_uart0.processing_cf != NULL){
                rev = g_uart0.processing_cf(g_uart0.DealBuffer,g_uart0.DealLen);
            }
			HLW_LED_ON;
			memset(g_uart0.DealBuffer,0,USART_BUFFER_SIZE);	
		}
	}
}


/*******************************************************************************
* Function Name  : UART1_RecvINT_Processing 
* Description    : 串口1 接收中断处理函数 - 接收中断调用
*******************************************************************************/
void UART1_RecvINT_Processing(char data){
	if((g_uart1.RecvLen + 1) >= USART_BUFFER_SIZE) g_uart1.RecvLen = 0;
	g_uart1.RecvBuffer[g_uart1.RecvLen++] = (U8_T)data;
	BUS_LED_OFF;
	g_uart1.RecvIdleTiming = SysTick_1ms;
	g_uart1.Receiving = 0x01;
	
}

void UART1_TASK(void){
	U8_T rev = 0xFF;	
	if(g_uart1.Receiving == 0x01){
		if(SysTick_1ms - g_uart1.RecvIdleTiming > g_uart1.RecvTimeout){
			
			SYSCON_Int_Disable();					//2025-03-19,复制接收缓冲到数据处理缓冲内
			g_uart1.RecvIdleTiming = SysTick_1ms;
			memcpy(g_uart1.DealBuffer,g_uart1.RecvBuffer,g_uart1.RecvLen);
			g_uart1.DealLen = g_uart1.RecvLen;
			g_uart1.RecvLen = 0;
			g_uart1.Receiving = 0;
			SYSCON_Int_Enable();

#if DBG_LOG_EN
		//	Dbg_Println(DBG_BIT_SYS_STATUS, "UART1 recv Len %d", g_uart1.DealLen);
		//	Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"UART1 buff",g_uart1.DealBuffer,g_uart1.DealLen);
#endif
			if(g_uart1.processing_cf != NULL){
                rev = g_uart1.processing_cf(g_uart1.DealBuffer,g_uart1.DealLen);
            }
			/*Boot处理函数 */
			if(rev != 0x00)
			{
				Boot_Comm_UpgradeProcess(g_uart1.DealBuffer,g_uart1.DealLen);
			}

			BUS_LED_ON;
			memset(g_uart1.DealBuffer,0,USART_BUFFER_SIZE);	
		}
	}
}

/*******************************************************************************
* Function Name  : UART2_RecvINT_Processing 
* Description    : 串口2 接收中断处理函数 - 接收中断调用
*******************************************************************************/
void UART2_RecvINT_Processing(char data){
	if((g_uart.RecvLen + 1) >= USART_BUFFER_SIZE) g_uart.RecvLen = 0;
	g_uart.RecvBuffer[g_uart.RecvLen++] = (U8_T)data;
	STATUS_LED_OFF;
	g_uart.RecvIdleTiming = SysTick_1ms;
	g_uart.Receiving = 0x01;
}

void UART2_TASK(void){
	U8_T rev = 0xFF;
	if(g_uart.Receiving == 0x01){
		if(SysTick_1ms - g_uart.RecvIdleTiming > g_uart.RecvTimeout){
			
			SYSCON_Int_Disable();					//2025-03-19,复制接收缓冲到数据处理缓冲内
			g_uart.RecvIdleTiming = SysTick_1ms;
			memcpy(g_uart.DealBuffer,g_uart.RecvBuffer,g_uart.RecvLen);
			g_uart.DealLen = g_uart.RecvLen;
			g_uart.RecvLen = 0;
			g_uart.Receiving = 0;
			SYSCON_Int_Enable();

#if DBG_LOG_EN
		//	Dbg_Println(DBG_BIT_SYS_STATUS, "UART2 revLen %d", g_uart.DealLen);
		//	Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"UART2 buff",g_uart.DealBuffer,g_uart.DealLen);
#endif
			if(g_uart.processing_cf != NULL){
                rev = g_uart.processing_cf(g_uart.DealBuffer,g_uart.DealLen);
            }
			
			if(rev != 0x00)
			{
				//UARTTransmit(UART2,g_uart.DealBuffer,g_uart.DealLen);//回返
			//	BT_Uart_Packing(g_uart.DealBuffer,g_uart.DealLen,REG_BTDEBUG_FLAG);
			}
			STATUS_LED_ON;
			memset(g_uart.DealBuffer,0,USART_BUFFER_SIZE);	
			
		}
	}
}


/*因为开启了UART_TX_DONE_S 中断，发送完成需要清楚该中断标志位，因此每次调用串口输出后，需调用该函数，否则会在中断出不来
 * 已取消
 * */
void UART_Waiting_For_Send(CSP_UART_T *uart){
	unsigned int Dataval = 0,delay_cnt = 0;
	
	do{
		Dataval = CSP_UART_GET_ISR(uart);
		
		Dataval = Dataval & UART_TX_DONE_S;
		delay_cnt ++;
		if(delay_cnt >= 50000){
			break;
		}
	}while(Dataval == 0x00);    //发送完成
	uart->ISR=UART_TX_DONE_S;
}

volatile int RS485_Comm_Flag = 0,RS485_Comm_Start = 0,RS485_Comm_End = 0,RS485_Comming = 0;
void MCU485_SendData(U8_T *buff,U16_T len){
	unsigned int Dataval = 0,delay_cnt = 0;

	//等待通讯发送完成
	while(RS485_Comming == 0x01){
		delay_nus(100);
		
		delay_cnt ++;
		if(delay_cnt >= 100){
			break;
		}

		REVERISE_DR;//GPIO_Reverse(GPIOA0,7);
	}
	
	CK_CPU_DisAllNormalIrq();

	WRITE_HIGH_DR;	//GPIO_Write_High(GPIOA0,7);
	
	RS485_Comm_Flag = 0x01;
	RS485_Comm_Start = 0x00;
	RS485_Comm_End = 0x00;
	CK_CPU_EnAllNormalIrq();
	
	UARTTransmit(UART1,buff,len);
	
	do{
		delay_nus(100);
		
		delay_cnt ++;
		if(delay_cnt >= 100){
			break;
		}
		
	}while((RS485_Comm_Start < len) || (RS485_Comm_End < len));    //发送完成

	CK_CPU_DisAllNormalIrq();
	WRITE_LOW_DR;	//GPIO_Write_Low(GPIOA0,7);
	
	RS485_Comm_Flag = 0x00;
	CK_CPU_EnAllNormalIrq();
}

/**********************************************************
 * @brief	带总线状态判断的485发送
 * 			buff:发送数据
 * 			len：数据长度
 * @retval 	
 * */
U8_T BUS485_Send(U8_T *buff,U16_T len)
{
	unsigned int Dataval = 0,delay_cnt = 0;

	//等待通讯发送完成
	while(RS485_Comming == 0x01){
		delay_nus(100);
		
		delay_cnt ++;
		if(delay_cnt >= 100){
			break;
		}
		
		REVERISE_DR;	//485_DR
	}

	if(m_send.BusState_Flag == UART_BUSIDLE){	//总线空闲
		
		CK_CPU_DisAllNormalIrq();	
		
		WRITE_HIGH_DR;	//485_DR
		
		RS485_Comm_Flag = 0x01;
		RS485_Comm_Start = 0x00;
		RS485_Comm_End = 0x00;		
		
		m_send.BusState_Flag = UART_BUSBUSY;//发送前总线置位繁忙
		m_send.BUSBUSY_LOCK = 0x01;			//锁定总线状态

		CK_CPU_EnAllNormalIrq();		
		
		UARTTransmit(UART1,buff,len);
		do{
			delay_nus(100);
			delay_cnt ++;
			if(delay_cnt >= 100){
				break;
			}
			
		}while((RS485_Comm_Start < len) || (RS485_Comm_End < len));    //发送完成

		CK_CPU_DisAllNormalIrq();	

		WRITE_LOW_DR;	//485_DR
		
		RS485_Comm_Flag = 0x00;			
		
		m_send.BusState_Tick = SysTick_1ms;
		m_send.BUSBUSY_LOCK = 0x00;			//解锁总线状态
		
		CK_CPU_EnAllNormalIrq();			
		
		return UART_BUSIDLE;	//发送成功
	}
	else 	//总线繁忙
	{ 		
		return UART_BUSBUSY;	//发送失败
	}	
	
	return 0x02;		//传入状态无效
}

/**********************************************************
 * @brief	重发、数据有效期、超时发送判断，2025-03-25
 * 			buff:发送数据
 * 			len：数据长度
 * 			DatSd：发送标记,0x00:无发送，0x01：有数据发送
 * 
 * @retval 	0x00:发送成功	0x01:等待发送	0x02:数据无效
 * */
U8_T MultSend_Task(U8_T *buff,U16_T len,U8_T DatSd)
{
	if( (len == 0)||(len > USART_SEND_SIZE) ) return LEN_ERR;
	
	if(DatSd == 0x01)	
	{
		if( m_send.ResendCnt < m_send.TotalCnt)	//判断数据是否还在有效期，是否还有发送次数
		{
			if(SysTick_1ms - m_send.BusbusyTimeout < m_send.DataValid_Time)
			{
				if((m_send.ResendCnt == 0x00)||(SysTick_1ms - m_send.ASend_Tick >= m_send.DataWait_Time)){//数据发送间隔
					if(BUS485_Send(buff,len) == UART_BUSIDLE){	//发送数据
						m_send.ASend_Tick = SysTick_1ms;
						m_send.ResendCnt++;

						return BUSSEND_SUCC;//数据发送成功
					}
				}
			}else{
				return DATA_END;//数据有效期结束
			}
		}else{
			return RETRY_END;//没有重发次数
		}
	}
	return BUSSEND_WAIT;//等待
}
/**********************************************************
 * @brief	设置发送标志、组包、选择数据有效期档位，2025-03-25
 * 			data : 		发送数据
 * 			sled ：		数据长度
 * 			SCnt :		设置数据发送次数
 * 			indate ：	设置数据有效期
 * 			tim_val :	发送时间间隔
 * @retval 	None
 * */
void Set_GroupSend(U8_T *data,U16_T sled,U8_T SCnt,U32_T indate,U32_T tim_val)
{
	if((sled == 0x00)|| (sled > USART_SEND_SIZE)) return;
	
	memset(m_send.SendBuffer,0, USART_SEND_SIZE);
	memcpy(m_send.SendBuffer,data,sled);
	m_send.SendLen = sled;
	
	m_send.DataValid_Time = indate;//数据有效期
	m_send.TotalCnt = SCnt;			//数据发送次数
	m_send.DataWait_Time = tim_val;//发送数据间隔
	
	m_send.ASend_Flag = 0x01;
	m_send.SendState = BUSSEND_WAIT;
	m_send.ResendCnt = 0x00;
	m_send.BusbusyTimeout = SysTick_1ms;
}
//清除发送标志
void Clear_SendFlag(void)
{
	m_send.ASend_Flag = 0x00;
	m_send.SendState = BUSSEND_SUCC;
}

void BUS485_Jump_Boot(U8_T jump)
{
	m_send.Jump_Flag = jump;
}

//485发送任务
void BUS485Send_Task(void)	//2025-03-29
{	
	//空闲等待
	if(m_send.ASend_Flag == 0x01)
	{
		m_send.SendState = MultSend_Task(m_send.SendBuffer,m_send.SendLen,m_send.ASend_Flag);
		
		if( (m_send.SendState == DATA_END)||(m_send.SendState == RETRY_END) )//判断发送数据是否有效
		{
			Dbg_Println(DBG_BIT_DEVICE_STATUS,"send end");
			
			m_send.ASend_Flag = 0x00;		//清除发送标志位
			/*设置波特率*/


			if(m_send.Jump_Flag == 0x01){
				Dbg_Println(DBG_BIT_DEVICE_STATUS,"Jump Boot");
				
				SYSCON->UREG3 = g_boot.bootTimeout;		//向Boot 设定Boot超时时间
				
				SYSCON_Software_Reset();
			}	
		}
	}
}
//获取当前BUS485 发送状态，获取完状态后清除当前状态
U8_T Get_BUS485_Send_State(void)
{
	U8_T rev_state = 0x0F;
	
	if(m_send.ASend_Flag == 0x01){
		
		rev_state |= 0x80;
	}
	
	rev_state |= (m_send.SendState & 0x0F);
	
	return rev_state;
}
/**********************************************************
 * @brief	2025-03-25，检测总线空闲，在定时器中断里调用
 * @retval 	None
 * */
void BusIdle_Task(void)
{
	if((m_send.BusState_Flag != UART_BUSIDLE)&&(m_send.BUSBUSY_LOCK != 0x01))
	{
		CK_CPU_DisAllNormalIrq();
		if( (m_send.HighBit_Flag == 0x01)&&(SysTick_1ms - m_send.BusState_Tick >= (6 + m_send.Bus_DelayTime)) )
		{
			m_send.BusState_Flag = UART_BUSIDLE;
		}	
		CK_CPU_EnAllNormalIrq();
	}
}
/*******************************************************************
 * @brief	检测总线繁忙，在串口接收RX引脚的外部中断服务函数里调用
 * @retval 	None
 * */
void BusBusy_Task(void)
{
	CK_CPU_DisAllNormalIrq();
	m_send.BusState_Flag = UART_BUSBUSY;
	m_send.BusState_Tick = SysTick_1ms;
	m_send.Bus_DelayTime = (SysTick_1ms - m_send.ASend_Tick)%10;//随机延时

	if(READ_RX_LEVEL_STATE == 0x01){
		m_send.HighBit_Flag = 0x01;			//高电平标志置位
	}else if(READ_RX_LEVEL_STATE == 0x00){
		m_send.HighBit_Flag = 0x00;			//低电平
	}	
	CK_CPU_EnAllNormalIrq();
}


/*调试信息输出接口*/
U32_T Dbg_Switch = (DBG_OPT_Debug_STATUS << DBG_BIT_Debug_STATUS)
        + (DBG_OPT_DEVICE_STATUS << DBG_BIT_DEVICE_STATUS)
        + (DBG_OPT_SYS_STATUS << DBG_BIT_SYS_STATUS)
		+ (DBG_OPT_BT_STATUS << DBG_BIT_BT_STATUS)
		+ (DBG_OPT_BTDebug_STATUS << DBG_BIT_BTDebug_STATUS);

#if DBG_LOG_EN

char Dbg_Buffer[128] = {0};
U32_T SysTick_Now = 0, SysTick_Last = 0, SysTick_Diff = 0;

#endif

void Dbg_Print(int DbgOptBit, const char *cmd, ...){

#if DBG_LOG_EN
	U16_T str_offset = 0;

	if (Dbg_Switch & (1 << DbgOptBit)) {
        SysTick_Now = SysTick_1ms;
        SysTick_Diff = SysTick_Now - SysTick_Last;      //上一次打印时间差
        SysTick_Last = SysTick_Now;
        str_offset = snprintf(Dbg_Buffer, sizeof(Dbg_Buffer),"%8d [%6d]: ", SysTick_Now, SysTick_Diff);
		DBG_Printf(Dbg_Buffer,str_offset);
		
        va_list args;       	//定义一个va_list类型的变量，用来储存单个参数
        va_start(args, cmd); 	//使args指向可变参数的第一个参数
        str_offset = vsnprintf(Dbg_Buffer, sizeof(Dbg_Buffer) ,cmd, args);  //必须用vprintf等带V的
        va_end(args);       	//结束可变参数的获取
        
		DBG_Printf(Dbg_Buffer,str_offset);
		
    }

#endif	
}

void Dbg_Println(int DbgOptBit, const char *cmd, ...){

#if DBG_LOG_EN
	U16_T str_offset = 0;

	if (Dbg_Switch & (1 << DbgOptBit)) {
        SysTick_Now = SysTick_1ms;
        SysTick_Diff = SysTick_Now - SysTick_Last;      //上一次打印时间差
        SysTick_Last = SysTick_Now;
        str_offset = snprintf(Dbg_Buffer, sizeof(Dbg_Buffer) , "%8ld [%6ld]: ", SysTick_Now, SysTick_Diff);
		DBG_Printf(Dbg_Buffer,str_offset);
		
        va_list args;       	//定义一个va_list类型的变量，用来储存单个参数
        va_start(args, cmd); 	//使args指向可变参数的第一个参数
        str_offset = vsnprintf(Dbg_Buffer, sizeof(Dbg_Buffer) ,cmd, args);  //必须用vprintf等带V的
        va_end(args);       	//结束可变参数的获取
        
		DBG_Printf(Dbg_Buffer,str_offset);
		
		DBG_Printf("\r\n",2);
		
		
    }

#endif	
}


void Dbg_Print_Buff(int DbgOptBit, const char *cmd, U8_T *buff,U16_T len){
#if DBG_LOG_EN
	U16_T str_offset = 0;

	if (Dbg_Switch & (1 << DbgOptBit)) {
        SysTick_Now = SysTick_1ms;
        SysTick_Diff = SysTick_Now - SysTick_Last;      //上一次打印时间差
        SysTick_Last = SysTick_Now;
        str_offset = snprintf(Dbg_Buffer, sizeof(Dbg_Buffer) , "%8ld [%6ld]: ", SysTick_Now, SysTick_Diff);
		DBG_Printf(Dbg_Buffer,str_offset);
		
        for (uint32_t i = 0; i < len; i++) {
			str_offset = snprintf(Dbg_Buffer, sizeof(Dbg_Buffer) , "%02X ", buff[i]);
            DBG_Printf(Dbg_Buffer,str_offset);
        }
		
		DBG_Printf("\r\n",2);
    }

#endif	
}

void Dbg_BT_Println(int DbgOptBit, const char *cmd, ...){
#if DBG_LOG_EN
	U16_T str_offset = 0;

	if (Dbg_Switch & (1 << DbgOptBit)) {
        va_list args;       	//定义一个va_list类型的变量，用来储存单个参数
        va_start(args, cmd); 	//使args指向可变参数的第一个参数
        str_offset = vsnprintf(Dbg_Buffer, sizeof(Dbg_Buffer) ,cmd, args);  //必须用vprintf等带V的
        va_end(args);       	//结束可变参数的获取
        
		DBG_BTPrintf(Dbg_Buffer,str_offset);
		
		DBG_BTPrintf("\r\n",2);
    }

#endif	
}





