//===========================================================================
//文件名称：task_rf_recv.c
//功能概要：放置RF接收数据帧任务
//版权所有：苏州大学飞思卡尔嵌入式中心(sumcu.suda.edu.cn)
//版本更新：可根据项目需要对函数放置位置进行调整、增加command_proc()函数功能
//===========================================================================
#include "01_app_include.h"    //应用任务公共头文件

//内部函数声明
uint_8 RFTest(uint_8*rec_buf,uint_8*send_buf);
uint_8 FrameCheck(uint_8 *rec_buf);
uint_8 FrameDataCheck(uint_8 *rec_buf);
uint_8 command_proc(uint_8 *rec_buf,uint_8 *send_buf);


//----------------------以下为内部函数存放处---------------------------------------
//============================================================================
//函数名称: FrameCheck
//功能概要: 数据帧帧格式校验,对接收到的数据的帧头,帧长,硬件地址,帧尾进行校验,如果都正确则返回0,否则
//返回1
//参数说明: 将接收到的一帧数据作为参数传入:rec_buf,接收到的一帧数据
//函数返回: 返回帧格式校验的结果
//============================================================================
uint_8 FrameCheck(uint_8 *rec_buf)
{
	uint_8 ret = 0;                                 //置全部校验正确返回0
	//帧头
	if(rec_buf[0] != HEAD_PC)                   //帧头校验
	{
		ret = 1;
		goto Exit_FrameCheck;
	}
	//长度
	if(rec_buf[1] > 61)                        //帧长校验
	{
		ret = 1;
		goto Exit_FrameCheck;
	}
	//硬件地址
	if(rec_buf[2] != (uint_8)g_tinfo.hd_addr)  //硬件地址校验
	{
		ret = 1;
		goto Exit_FrameCheck;
	}
	//帧尾
	if(rec_buf[2 + rec_buf[1]] != END_PC)  //帧尾校验
	{
		ret = 1;
		goto Exit_FrameCheck;
	}

Exit_FrameCheck:
	return ret;      //返回校验结果
}

//============================================================================
//函数名称: FrameDataCheck
//功能概要: 数据帧节点信息校验,对网络地址和网内地址进行校验,如果校验成功则返回0，否则返回1
//参数说明: 将接收到的一帧数据作为参数传入:rec_buf,接收到的一帧数据
//函数返回: 返回节点信息校验的结果
//============================================================================
uint_8 FrameDataCheck(uint_8 *rec_buf)
{
	uint_8 ret = 0;                   //置校验成功返回数据0
	uint_16 netid, nodeid;

	netid = rec_buf[3];
	netid <<= 8;                     //左移八位,使netid的高位存放网络地址高字节
	netid |= rec_buf[4];        //netid的低位存放网络地址低字节
	nodeid = rec_buf[5];
	nodeid <<= 8;                    //左移八位,使ndeid的高位存放网内地址高字节
	nodeid |= rec_buf[6];       //ndeid的低位存放网内地址低字节

	if(netid != g_tinfo.netid || nodeid != g_tinfo.nodeid)  //网络网内地址校验
		ret = 1;                    //校验失败返回数据1

	return ret;   //返回校验结果
}

//============================================================================
//函数名称: command_proc
//功能概要: 命令处理，根据数据中第八位的命令,如果是RF转发命令,则调用RF转换函数把接收到的数据转移到发
//送缓冲区,并返回数据总长度,否则则置数据总长度为0
//参数说明: rec_buf:接收到的一帧数据,send_buf:发送缓冲区
//函数返回: 回发帧数据总长度
//============================================================================
uint_8 command_proc(uint_8 *rec_buf,uint_8 *send_buf)
{
	switch(rec_buf[7])
	{
		case eAPPCMD_RF:
			g_rf_sentBufLength = RFTest(rec_buf,send_buf);  //是RF命令,调用RF数据转换函数
			break;
		default:
			g_rf_sentBufLength = 0; //不是RF命令,数据长度置0
			break;
	}

	return g_rf_sentBufLength;   //返回数据总长度
}

//============================================================================
//函数名称: RFTest
//功能概要: RF数据转换,把接收数据放入发送缓冲区,并返回数据总长度
//参数说明: rec_buf:接收到的一帧数据,send_buf:发送缓冲区
//函数返回: 回发帧数据总长度
//============================================================================
uint_8 RFTest(uint_8*rec_buf,uint_8*send_buf)
{
	uint_8 offset,n;
	n = rec_buf[1] + 3;             //获取数据总长度
	for(offset=0;offset<n;offset++)
	{
		send_buf[offset] = rec_buf[offset]; //接受数据放入发送缓冲区
	}
	return n;      //返回数据总长度
}

//----------------------------内部函数结束-------------------------------------

//===========================================================================
//任务名称：task_rf_recv
//功能概要：判断RF接收事件位EVENT_RF_RECV，置一后调用FrameCheck()、
//         FrameDataCheck()函数对数据帧进行校验，校验成功后调用command_proc()函数
//         对帧命令解析与处理，并对需要回发数据的帧进行组帧、置RF发送事件位，然后
//         清除RF接收事件位，继续等待RF接收事件位置一。
//参数说明：未使用
//===========================================================================
void task_rf_recv(uint32_t initial)
{	
	//1. 声明任务使用的变量
	uint_8 i;
	uint_32 g_port_recvBuf_32[64];
	uint_32 g_port_sentBuf_32[64];
	uint_8 cc;

	//2. 给有关变量赋初值

	//3. 进入任务循环体
	while(TRUE) 
	{

		//以下加入用户程序--------------------------------------------------------
		//1）无限等待rf_rev_queue消息队列
		_lwmsgq_receive((pointer) rf_rev_queue, g_port_recvBuf_32,
					    		          LWMSGQ_RECEIVE_BLOCK_ON_EMPTY, 0, 0);
		for (i=0;i<g_port_recvBuf_32[1]+3;i++)	g_rf_sentBuf[i]=g_port_recvBuf_32[i];
		//2）数据帧帧格式、节点信息校验
		if(FrameCheck(&g_rf_recvBuf[0]) == 0 && FrameDataCheck(&g_rf_recvBuf[0]) == 0)
		{
		    g_rf_sentBufLength = 0;

			//命令解析，对需要回发数据的帧命令组帧
			g_rf_sentBufLength = command_proc(&g_rf_recvBuf[0],&g_rf_sentBuf[0]);  //接收的数据的总长度

			if(g_rf_sentBufLength > 3)  //表示节点有数据需要回发
			{
				g_rf_sentBuf[0] = HEAD_TERMINAL;           //帧头
				g_rf_sentBuf[1] = g_rf_sentBufLength - 3;  //有效数据长度
				g_rf_sentBuf[2] = g_rf_recvBuf[2];         //硬件地址
				g_rf_sentBuf[g_rf_sentBufLength - 1] = END_TERMINAL;   //帧尾


		    	for(cc=0;cc<64;cc++)
		    	{
		    		g_port_sentBuf_32[cc]=g_rf_sentBuf[cc];
		    	}
				//发送g_uart_recvBuf_32至rf_send_queue消息队列，触发task_rf_send任务
				_lwmsgq_send((pointer)rf_send_queue, g_port_sentBuf_32,
						                              LWMSGQ_SEND_BLOCK_ON_FULL);
			}
		}

	}//任务循环体end_while
}
