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

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

UART_t g_uart[3];	
U8_T	DealBuffer[USART_BUFFER_SIZE] = {0};	//数据处理缓冲
U16_T	DealLen = 0x00;
MULIT_t m_send;	

void UARTx_Init(UART_IDX uart_id, Uart_prt prt_cf) {
	switch(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,416,UART_PAR_NONE);				  //baudrate=sysclock 48M/1000=4800,tx rx int enabled 
//			UART0_Int_Enable();
			
			memset(&g_uart[UART_0],0,sizeof(UART_t));
			
			g_uart[UART_0].RecvTimeout = Recv_115200_TimeOut;
			g_uart[UART_0].processing_cf = prt_cf;
			break;
		case UART_1:
			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();
			
			memset(&g_uart[UART_1],0,sizeof(UART_t));
			
			g_uart[UART_1].RecvTimeout = Recv_9600_TimeOut;
			g_uart[UART_1].processing_cf = prt_cf;
			
			GPIO_Init(GPIOA0,13,Output);
			GPIO_DriveStrength_EN(GPIOA0,13);
			GPIO_Write_Low(GPIOA0,13);			
			break;
		case UART_2:
			memset(&g_uart[UART_2],0,sizeof(UART_t));
			memset(&m_send,0,sizeof(MULIT_t));
			m_send.HighBit_Flag = 0x01;
			
			g_uart[UART_2].RecvTimeout = Recv_9600_TimeOut;
			g_uart[UART_2].processing_cf = prt_cf;		
		
			//2025-03-29，串口2的RX管脚外部中断，用于通讯总线繁忙判断。
			GPIO_PullHigh_Init(GPIOB0,5);								//RX,PB0.5
			GPIO_IntGroup_Set(PB0,5,Selete_EXI_PIN5); 					//EXI0 set PB0.2
			GPIOB0_EXI_Init(EXI5); 										//PB0.2 as input
			EXTI_trigger_CMD(ENABLE,EXI_PIN5,_EXIFT); 					//ENABLE falling edge，下降沿触发
			EXTI_trigger_CMD(ENABLE,EXI_PIN5,_EXIRT);					//上升沿触发
			EXTI_interrupt_CMD(ENABLE,EXI_PIN5); 						//enable EXI
			GPIO_EXTI_interrupt(GPIOB0,0b0000000000100000); 			//enable GPIOB02 as EXI
			EXI3_Int_Enable(); 				
		
		
			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 
			UART2_Int_Enable();
			
			GPIO_Init(GPIOB0,3,Output);
			GPIO_DriveStrength_EN(GPIOB0,3);
			GPIO_Write_Low(GPIOB0,3);
			break;
	}
}


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


void UART0_TASK(void){
	if(g_uart[UART_0].Receiving == 0x01){
		if(SysTick_1ms - g_uart[UART_0].RecvIdleTiming > g_uart[UART_0].RecvTimeout){
			g_uart[UART_0].RecvIdleTiming = SysTick_1ms;

			Dbg_Println(DBG_BIT_SYS_STATUS, "UART0 recv Len %d", g_uart[UART_0].RecvLen);
			Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"UART0 buff",g_uart[UART_0].RecvBuffer,g_uart[UART_0].RecvLen);
			
			if(g_uart[UART_0].processing_cf != NULL){
                g_uart[UART_0].processing_cf(g_uart[UART_0].RecvBuffer,g_uart[UART_0].RecvLen);
            }

            g_uart[UART_0].RecvLen = 0;
            g_uart[UART_0].Receiving = 0;
		}
	}
}



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


void UART1_TASK(void){
	U8_T rev = 0xFF;
	if(g_uart[UART_1].Receiving == 0x01){
		if(SysTick_1ms - g_uart[UART_1].RecvIdleTiming > g_uart[UART_1].RecvTimeout){

			SYSCON_Int_Disable();					//2025-03-19,复制接收缓冲到数据处理缓冲内
			g_uart[UART_1].RecvIdleTiming = SysTick_1ms;
			memcpy(DealBuffer,g_uart[UART_1].RecvBuffer,g_uart[UART_1].RecvLen);
			DealLen = g_uart[UART_1].RecvLen;
			g_uart[UART_1].RecvLen = 0;
			g_uart[UART_1].Receiving = 0;
			SYSCON_Int_Enable();

#if DBG_LOG_EN
			Dbg_Println(DBG_BIT_SYS_STATUS, "UART1 recv Len %d", DealLen);
			Dbg_Print_Buff(DBG_BIT_SYS_STATUS,"UART1 buff",DealBuffer,DealLen);
#endif
			if(g_uart[UART_1].processing_cf != NULL){
                rev = g_uart[UART_1].processing_cf(DealBuffer,DealLen);
            }

            memset(DealBuffer,0,USART_BUFFER_SIZE);		
		}
	}
}

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


void UART2_TASK(void){
	U8_T rev = 0xFF;
	if(g_uart[UART_2].Receiving == 0x01){
		if(SysTick_1ms - g_uart[UART_2].RecvIdleTiming > g_uart[UART_2].RecvTimeout){

			SYSCON_Int_Disable();					//2025-03-19,复制接收缓冲到数据处理缓冲内
			g_uart[UART_2].RecvIdleTiming = SysTick_1ms;
			memcpy(DealBuffer,g_uart[UART_2].RecvBuffer,g_uart[UART_2].RecvLen);
			DealLen = g_uart[UART_2].RecvLen;
			g_uart[UART_2].RecvLen = 0;
			g_uart[UART_2].Receiving = 0;
			SYSCON_Int_Enable();


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


			memset(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;
volatile int RS485_Comm_Flag1 = 0,RS485_Comm_Start1 = 0,RS485_Comm_End1 = 0,RS485_Comming1 = 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;
		}
		
		GPIO_Reverse(GPIOB0,3);
	}
	
	delay_nus(500);
	
	CK_CPU_DisAllNormalIrq();
	GPIO_Write_High(GPIOB0,3);
	
	RS485_Comm_Flag = 0x01;
	RS485_Comm_Start = 0x00;
	RS485_Comm_End = 0x00;
	CK_CPU_EnAllNormalIrq();
	
	UARTTransmit(UART2,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();
	GPIO_Write_Low(GPIOB0,3);
	
	RS485_Comm_Flag = 0x00;
	CK_CPU_EnAllNormalIrq();
}

//发送给设备端的485发送函数
void Controller485_SendData(U8_T *buff,U16_T len)
{
	unsigned int Dataval = 0,delay_cnt = 0;

	//等待通讯发送完成
	while(RS485_Comming1 == 0x01){
		delay_nus(100);
		
		delay_cnt ++;
		if(delay_cnt >= 100){
			break;
		}
		
		GPIO_Reverse(GPIOA0,13);
	}
	
	delay_nus(500);
	
	CK_CPU_DisAllNormalIrq();
	GPIO_Write_High(GPIOA0,13);
	
	RS485_Comm_Flag1 = 0x01;
	RS485_Comm_Start1 = 0x00;
	RS485_Comm_End1 = 0x00;
	CK_CPU_EnAllNormalIrq();
	
	UARTTransmit(UART1,buff,len);
	
	do{
		delay_nus(100);
		
		delay_cnt ++;
		if(delay_cnt >= 100){
			break;
		}
		
	}while((RS485_Comm_Start1 < len) || (RS485_Comm_End1 < len));    //发送完成

	CK_CPU_DisAllNormalIrq();
	GPIO_Write_Low(GPIOA0,13);
	
	RS485_Comm_Flag1 = 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;
		}
		GPIO_Reverse(GPIOB0,3);
	}

	if(m_send.BusState_Flag == UART_BUSIDLE){		//总线空闲
		
		CK_CPU_DisAllNormalIrq();	
		
		GPIO_Write_High(GPIOB0,3);
		
		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(UART2,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();	
		
		GPIO_Write_Low(GPIOB0,3);
		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++;
						Dbg_Println(DBG_BIT_SYS_STATUS,"SendCnt:%d success",m_send.ResendCnt);
						return BUSSEND_SUCC;//数据发送成功
					}
				}
			}else{
				Dbg_Println(DBG_BIT_SYS_STATUS,"data end");
				return DATA_END;//数据有效期结束
			}
		}else{
			Dbg_Println(DBG_BIT_SYS_STATUS,"retry end,%d",m_send.ResendCnt );
			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_SYS_STATUS,"send end");
			
			m_send.ASend_Flag = 0x00;		//清除发生标志位
			
			/*设置波特率*/
//			if( m_send.SetBaudFlag == 0x01 ){
//				
//				UARTx_ChangeBaud(UART_2,m_send.SetBaud);
//				m_send.SetBaudFlag = 0x00;
//				m_send.SetBaud = 0x00;
//			}
			
//			if(m_send.Jump_Flag == 0x01){
//				Dbg_Println(DBG_BIT_Debug_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_RXLEVEL_STATE == 0x01){
		m_send.HighBit_Flag = 0x01;			//高电平标志置位
	}else if(READ_RXLEVEL_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);
	
#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	
}








