#include "emuart.h"

//帧头为0xa5,0x06；帧尾为0xb6,0x07
static uint_8 emuartFrameHead[2] = {0xa5,0x06}; //帧头
static uint_8 emuartFrameTail[2] = {0xb6,0x07};     //帧尾
static uint_8 UART_NO;      //emuart使用的串口

//======================内部函数声明====================================
//在函数定义处有详细说明
void sendFrame(uint_16 length,uint_8 *data);
//======================内部函数声明结束==================================

//=====================================================================
//函数名称：emuart_init
//函数返回： 无
//参数说明： uartNo：emuart使用的串口； baud：emuart的波特率。
//功能概要：初始化emuart
//更新记录：20180602，wb；
//=====================================================================
void emuart_init(uint_8 uartNo,uint_32 baud)
{
	uart_init(uartNo,baud);
	uart_enable_re_int(uartNo);
	UART_NO = uartNo;
}

//=====================================================================
//函数名称：emuart_send1
//函数返回： 无
//参数说明： a：待发送的一个字节数据
//功能概要：通过emuart发送一个字节数据
//更新记录：20180602，wb；
//=====================================================================
void emuart_send1(uint_8 a)
{
	sendFrame(1,&a);
}

//=====================================================================
//函数名称：emuart_sendN
//函数返回： 无
//参数说明： len：待发送数组的长度；buff：待发送数据缓冲区
//功能概要：通过emuart发送一个字节数组
//更新记录：20180602，wb；
//=====================================================================
void emuart_sendN(uint_8 len ,uint_8* buff)
{
	sendFrame(len,buff);
}

//=====================================================================
//函数名称：emuart_send_string
//函数返回： 无
//参数说明： buff：待发送的字符串
//功能概要：通过emuart发送一个字符串
//更新记录：20180602，wb；
//=====================================================================
void emuart_send_string(uint_8 * buff)
{
	uint_16 len=0;
	while(buff[len])len++;
	sendFrame(len,buff);
}

//===========================================================================
//函数名称：emuart_recv
//功能概要：组建数据帧，将待组帧数据加入到数据帧中。本函数应被放置于中断中。
//参数说明：ch：串口中断接收到的一个字节的串口数据；data：存放接收到的数据。
//函数返回：0：未接收到数据；非0：接收到一帧长度组帧成功，且返回值为接收到的数据长度
//备注：十六进制数据帧格式
//        帧头       + 数据长度         + 有效数据    +  帧尾
//        emuartFrameHead   +   len(1个字节)   + 有效数据     +  emuartFrameTail
//===========================================================================
uint_16 emuart_recv(uint_8 ch, uint_8 *data)
{
	static uint_16 index = 0;
	static uint_16 length = 0;
	uint_16 ret_val;
	uint_16 i;
	uint_8 CRC[2];
	uint_16 crc;
	if((index == 0 && ch != emuartFrameHead[0]) ||
			(index == 1 && ch != emuartFrameHead[1]))//未接收到数据或者未遇到帧头
	{
		index = 0;
		length = 0;
		ret_val = 0;     //接收数据错误
		goto uecom_recv_exit;
	}
	data[index++] = ch;//存入数据
	if(index == 4)//读取有效数据长度
	{
		length = ((uint_16)data[2]<<8) + data[3];
	}
	if(length != 0 && index >= length+8)//接收到的数据达到一帧长度。23为帧头帧尾等长度
	{
		//CRC校验
		crc = crc16(data+4,length);
		CRC[0] = (crc>>8)&0xff;
		CRC[1] = crc&0xff;

		if(data[index-2]!=emuartFrameTail[0] || data[index-1]!= emuartFrameTail[1]//未遇到帧尾
			||	CRC[0] != data[index-4] || CRC[1] != data[index-3])//CRC检验错误
		{
			index = 0;
			length = 0;
			ret_val = 0;
			goto uecom_recv_exit;
		}
		for(i=0;i<length;i++)
		{
			data[i] = data[i+4];
		}
		index = 0;
		ret_val = length;
		data[length] = 0;
		//若是上位机搜寻设备则自动回发
		if(length == 21 &&
			!strcmp(data,"[Are you an emuart??]"))
		{
			emuart_send_string("[Yes,I am an emuart!!]");
			ret_val = 0;
		}
		length = 0;
		goto uecom_recv_exit;
	}
	ret_val = 0;
uecom_recv_exit:
    return ret_val;
}

//======以下为内部函数====================================================
//=====================================================================
//函数名称：sendFrame
//函数返回： 无
//参数说明： length：待发送数据的长度；data：待发送数据缓冲区。
//功能概要：通过emuart发送指定长度的字节数组。
//更新记录：20180602，wb；
//=====================================================================
void sendFrame(uint_16 length,uint_8 *data)
{
	uint_16 crc,len;
	//计算得到CRC校验码
	crc = crc16(data,length);
	//发送帧头
	uart_send1(UART_NO,emuartFrameHead[0]);
	uart_send1(UART_NO,emuartFrameHead[1]);
	//发送帧长
	uart_send1(UART_NO,length>>8);
	uart_send1(UART_NO,length);
	//发送帧数据
	uart_sendN(UART_NO,length,data);
    //发送校验码
	uart_send1(UART_NO,crc>>8);
	uart_send1(UART_NO,crc);
	//发送帧尾
	uart_send1(UART_NO,emuartFrameTail[0]);
	uart_send1(UART_NO,emuartFrameTail[1]);
}

