/*
*********************************************************************************************************
*                                       IAR Development Kits
*                                              on the
*
*                                    M451
*
* Filename      : uart_RFGateway.h
* Version       : V1.00
* Programmer(s) : Qian Xianghong
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                             INCLUDE FILES
*********************************************************************************************************
*/
#include "includes.h"

extern IWDG_HandleTypeDef hiwdg;

const uint8_t RF_APP = RF_APP_AJH;
const uint8_t RF_PROTOCOL_VER = RF_PROTOCOL_VER_1;	

uint8_t RF_UP_CHANNEL = 9;	// 上行信道: 498M
uint8_t RF_DOWN_CHANNEL = 8;	// 下行信道: 499M
const uint8_t RF_BROADCAST_PSN[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
const uint8_t RF_EMPTYPSN[6] = {0, 0, 0, 0, 0, 0};
uint8_t RF_GatewayPSN[6] = {0, 0, 0, 0, 0, 0};
#define RF_SelfPSN (dcBuff.configBottle.PSN)

uint8_t RF_MAC_FN = 0;
uint8_t RF_APP_PN = 0;
uint8_t RF_APP_IDX = 0;

// 发送、接收、处理帧
rf_frame_t RF_Send_Frame, RF_RecvFrame, RF_ProcFrame;
// 发送、上传队列记录
rf_send_queue_t RF_Send_Rec, RF_Send_Rec1;

// RF串口接收帧的循环缓冲
#define RF_TASKM_DATA_COUNT 256
loopbuff_t RF_TaskM;
uint8_t RF_TaskM_Data[sizeof(rf_frame_t) * (RF_TASKM_DATA_COUNT + 1)] = {0};
// 射频初始化状态
uint8_t RF_initStatus = 0;
uint32_t RF_seconds = 0;

// RF串口接收的消息通知
SemaphoreHandle_t	   RF_TaskQ = NULL;    // 二值信号量句柄
SemaphoreHandle_t	   RF_semAck = NULL;    // 二值信号量句柄
SemaphoreHandle_t	   RF_semGateway = NULL;    // 二值信号量句柄
SemaphoreHandle_t	   RF_semResp = NULL;    // 二值信号量句柄	

// RF串口发送帧的循环缓冲
#define RF_SENDM_DATA_COUNT 512
loopbuff_t RF_SendM;
uint8_t RF_SendM_Data[sizeof(rf_send_queue_t) * (RF_SENDM_DATA_COUNT + 1)] = {0};
// RF串口接收的消息通知
SemaphoreHandle_t	   RF_SendQ = NULL;    // 二值信号量句柄

loopbuff_t RF_GatewayBuff;
uint8_t RF_GatewayBuff_Data[6 * (4 + 1)] = {0};
loopbuff_t RF_AckBuff;
uint8_t RF_AckBuff_Data[sizeof(rf_ack_t) * (2 + 1)] = {0};
loopbuff_t RF_RespBuff;
uint8_t RF_RespBuff_Data[sizeof(rf_resp_t) * (2 + 1)] = {0};

#define RF_MOD_MD0_1()	LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_5)
#define RF_MOD_MD0_0()	LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_5)
#define RF_MOD_MD1_1()	LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_6)
#define RF_MOD_MD1_0()	LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_6)

volatile uint8_t RF_hasPowered = 0;

// 多项式为x16+x15+x2+1，LSB顺序
// 同ibutton的crc算法，不同于modbus的crc算法
uint16_t rf_crc_16(uint8_t *message, int16_t len)
{
#if 0	
    int16_t i, j;
    uint16_t crc_reg = 0;
    uint16_t current;
       
    for (i = 0; i < len; i++)
    {
        current = message[i];
        for (j = 0; j < 8; j++)
        {
            if ((crc_reg ^ current) & 0x0001)
                crc_reg = (crc_reg >> 1) ^ 0xA001;
            else
                crc_reg >>= 1;
            current >>= 1;
        }
    }
    // 交换高低字节顺序
    return ((crc_reg & 0xFF) << 8) | ((crc_reg >> 8) & 0xFF);
#else
	return MODBUS_RTU_CRC16(message, len);
#endif	
}

// 计算自启动以来经过的秒数
uint32_t rf_get_seconds()
{
    S_RTC_TIME_DATA_T sRTC;
	
	RTC_GetDateAndTime(&sRTC);
	return Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
			sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
}

// 设置网关
void rf_set_gateway(uint8_t PSN[6])
{
	memmove(RF_GatewayPSN, PSN, 6);
}

// 清除网关
void rf_clear_gateway()
{
	memmove(RF_GatewayPSN, RF_EMPTYPSN, 6);
}

// 计算通信地址，用于定点传输
uint16_t rf_get_addr(uint8_t PSN[6])
{
	uint16_t addr = rf_crc_16(PSN, 6);
	if(addr == 0xFFFF)	// 不能为广播地址
		return 0;
	return addr;
}

// 物理层校验
uint8_t rf_phy_valid(rf_frame_t *frame)
{
	if(frame->vendor_id != RF_MARK_LS ||  frame->app_id != RF_APP || frame->protocol_ver != RF_PROTOCOL_VER)
	{
		// 物理层校验失败
		return 0;
	}
	return 1;
}

// mac层校验
uint8_t rf_mac_valid(rf_frame_t *frame, uint8_t dir)
{
	if(frame->dir != dir 
		|| (memcmp(frame->destPSN, RF_SelfPSN, 6) != 0 && (dir == RF_DIR_DOWN || memcmp(frame->destPSN, RF_BROADCAST_PSN, 6) != 0))
	)
	{
		// mac层校验失败
		return 0;
	}
	return 1;
}

// 重新寻找SOF
void RF_SearchSOF(uint8_t *buf, uint16_t fromPos, uint16_t *len)
{
	uint16_t i;
	
	for(i = fromPos; i < *len && buf[i] != RF_FRAME_SOF; i++)
	{
	}
	
	*len -= i;
	memmove(buf, buf + i, *len);
}

// 分析串口数据，组帧
void RF_ParseFrame(uint8_t c)
{
	BaseType_t xHigherPriorityTaskWoken;
	static uint16_t RdIdx = 0;
	uint8_t *RF_ModuleData = (uint8_t *) &RF_RecvFrame;
	uint8_t frameOk, frameErr;

	if(RdIdx == 0 && c != RF_FRAME_SOF)
		return;
	
	RF_ModuleData[RdIdx++] = c;

	do
	{
		frameErr = (RdIdx >= 2 &&
			(RF_ModuleData[1] < RF_MIN_FRAME_LEN || RF_ModuleData[1] > RF_MAX_FRAME_LEN));
		if(frameErr)
		{
			// 从1开始寻找SOF
			RF_SearchSOF(RF_ModuleData, 1, &RdIdx);
		}

		frameOk = (RdIdx >= 2 && RF_ModuleData[1] >= RF_MIN_FRAME_LEN && RF_ModuleData[1] <= RF_MAX_FRAME_LEN
			&& RdIdx >= RF_ModuleData[1]);
		if(frameOk)
		{
			if(rf_crc_16(RF_ModuleData, RF_ModuleData[1]) == 0)
			{
				if(rf_phy_valid(&RF_RecvFrame) && rf_mac_valid(&RF_RecvFrame, RF_DIR_UP))
				{
					LoopBuff_PutItem(&RF_TaskM, RF_ModuleData);
				}
				
				// 继续寻找下一帧
				RdIdx -= RF_ModuleData[1];
				memmove(RF_ModuleData, RF_ModuleData + RF_ModuleData[1], RdIdx);
				// 从0开始寻找SOF
				RF_SearchSOF(RF_ModuleData, 0, &RdIdx);

				// 发消息给任务
				xSemaphoreGiveFromISR(RF_TaskQ, &xHigherPriorityTaskWoken);
			}
			else
			{
				// 从1开始寻找SOF
				RF_SearchSOF(RF_ModuleData, 1, &RdIdx);
			}
		}
	} while(frameOk || frameErr);
}

void RF_IRQHandler(USART_Handle *huart)
{
	uint8_t c = (uint8_t) huart->Instance->DR;
	
//	printf("%02X ", c);
	// 直接解析帧
	RF_ParseFrame(c);
}

// 初始化

void RF_Uart_Open(u32 baudrate)
{
	LL_USART_InitTypeDef USART_InitStruct = {0};

  USART_InitStruct.BaudRate = baudrate;
  USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
  USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
  USART_InitStruct.Parity = LL_USART_PARITY_NONE;
  USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
  USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
  USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
  LL_USART_Init(UART8, &USART_InitStruct);
  LL_USART_ConfigAsyncMode(UART8);
  LL_USART_Enable(UART8);

	huart8.RxISR = RF_IRQHandler;
	SET_BIT(UART8->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE);
	LL_USART_Enable(UART8);	
}

void RF_Open()
{
//	dcBuff.configBottle.PSN[0] = 0xFE;
//	dcBuff.configBottle.PSN[1] = 0xFE;
//	dcBuff.configBottle.PSN[2] = 0xFE;
//	dcBuff.configBottle.PSN[3] = 0xFE;
//	dcBuff.configBottle.PSN[4] = 0xFE;
//	dcBuff.configBottle.PSN[5] = 0xFE;

	// 用PSN的CRC校验值作为伪随机数的种子
	srand(rf_crc_16(dcBuff.configBottle.PSN, 6));
	
	RF_MAC_FN = rand() % 256;
	RF_APP_PN = rand() % 256;

	// 创建消息队列
	LoopBuff_Create(&RF_GatewayBuff, 6, 4, 0, (uint32_t) RF_GatewayBuff_Data);
	LoopBuff_Create(&RF_AckBuff, sizeof(rf_ack_t), 2, 0, (uint32_t) RF_AckBuff_Data);
	LoopBuff_Create(&RF_RespBuff, sizeof(rf_resp_t), 2, 0, (uint32_t) RF_RespBuff_Data);
	// 创建消息队列
	LoopBuff_Create(&RF_TaskM, sizeof(rf_frame_t), RF_TASKM_DATA_COUNT, 0, (uint32_t) RF_TaskM_Data);
	LoopBuff_Create(&RF_SendM, sizeof(rf_send_queue_t), RF_SENDM_DATA_COUNT, 0, (uint32_t) RF_SendM_Data);

	// 创建信号量
	RF_TaskQ = xSemaphoreCreateBinary();
	RF_SendQ = xSemaphoreCreateBinary();
	RF_semAck = xSemaphoreCreateBinary();
	RF_semGateway = xSemaphoreCreateBinary();
	RF_semResp = xSemaphoreCreateBinary();
	
	// 创建互斥锁

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init UART                                                                                               */
    /*---------------------------------------------------------------------------------------------------------*/
	
	// 模块上电，设置硬件参数
	RF_PowerOn();
}

// 初始化帧
void rf_initial_frame(rf_frame_t *frame)
{
	memset((uint8_t *) frame, 0, sizeof(rf_frame_t));
	frame->len = RF_MIN_FRAME_LEN;
}

// 追加负载数据
uint8_t rf_append_payload(rf_frame_t *frame, uint8_t payload_len, uint8_t *payload)
{
	if(frame->len < RF_MIN_FRAME_LEN || frame->len + payload_len > RF_MAX_FRAME_LEN)
		return 0;
	
	if(payload_len > 0)
		memmove(frame->app_payload + (frame->len - RF_MIN_FRAME_LEN), payload, payload_len);
	frame->len += payload_len;
	return 1;
}

// 物理层发送
uint8_t  rf_uart_send(rf_frame_t *frame)
{
	uint8_t phy_header[3];
	uint16_t crc;
	uint16_t dst;
	uint8_t i;

	// 填写固定字段
	frame->sof = RF_FRAME_SOF;
	frame->vendor_id = RF_MARK_LS;
	frame->app_id = RF_APP;
	frame->protocol_ver = RF_PROTOCOL_VER;
	memmove(frame->srcPSN, RF_SelfPSN, 6);
	crc = rf_crc_16((uint8_t *) frame, frame->len - 2);
	((uint8_t *) frame)[frame->len - 2] = crc >> 8;
	((uint8_t *) frame)[frame->len - 1] = crc & 0xFF;
	
	// 计算目的地址
	if(frame->dir == RF_DIR_UP)
		dst = rf_get_addr((uint8_t *) RF_BROADCAST_PSN);
	else
		dst = rf_get_addr(frame->destPSN);
#if 0	
//	phy_header[0] = dst >> 8;
//	phy_header[1] = dst & 0xFF;
//	// 信道
//	if(frame->dir == RF_DIR_UP)
//		phy_header[2] = RF_UP_CHANNEL;
//	else
//		phy_header[2] = RF_DOWN_CHANNEL;

////	while(!RF_READY());

////	delay_ms((rand() % 10) * (70 + rand() % 20));	// 多个中继器，避免冲突
//	delay_ms((rand() % 3) * (10 + rand() % 10));	// 单个中继器，提高效率
//	
//	printf("\nRF send to Module (%02X %02X %02X, %d bytes):\n", 
//		phy_header[0], phy_header[1], phy_header[2], frame->len);
//	for(i = 0; i < frame->len; i++)
//		printf(" %02X", ((uint8_t *) frame)[i]);
//	printf("\n");
//	
//	// 定点发送
//	// 因为射频模块接收数据不能中断超过3个字节的时间，故不允许打断。
//	__disable_irq();	
//	UART_Transmit(&huart8, phy_header, 3);
//	UART_Transmit(&huart8, (uint8_t *) frame, frame->len);
//	__enable_irq();
#else
	// 信道
//	if(frame->dir == RF_DIR_UP)
//	{
//		phy_header[0] = (dcBuff.configBottle.lora_freq%3)*2+7;//RF_UP_CHANNEL;
//		phy_header[1] = (dcBuff.configBottle.lora_freq%3)*2+6;//RF_DOWN_CHANNEL;
//	}
//	else
//	{}
		phy_header[0] = (dcBuff.configBottle.lora_freq%3)*2+7;//RF_DOWN_CHANNEL;
		phy_header[1] = (dcBuff.configBottle.lora_freq%3)*2+6;//RF_UP_CHANNEL;
	

//	while(!RF_READY());

//	delay_ms((rand() % 10) * (70 + rand() % 20));	// 多个中继器，避免冲突
	delay_ms((rand() % 3) * (10 + rand() % 10));	// 单个中继器，提高效率
	
	printf("\nRF send to Module (%02X, %d bytes):\n", 
		phy_header[0], frame->len);
	for(i = 0; i < frame->len; i++)
		printf(" %02X", ((uint8_t *) frame)[i]);
	printf("\n");
	
	// 定点发送
	// 因为射频模块接收数据不能中断超过3个字节的时间，故不允许打断。
	__disable_irq();	
	UART_Transmit(&huart8, phy_header, 2);
	UART_Transmit(&huart8, (uint8_t *) frame, frame->len);
	__enable_irq();
#endif
	
	return 1;
}

// mac层发送: ACK
uint8_t rf_mac_send_ack(uint8_t oriDir, uint8_t oriMac_fn, uint8_t oriPSN[6])
{
	rf_initial_frame(&RF_Send_Frame);

	if(oriDir == RF_DIR_UP)
		RF_Send_Frame.dir = RF_DIR_DOWN;
	else
		RF_Send_Frame.dir = RF_DIR_UP;
	RF_Send_Frame.mac_type = RF_MAC_TYPE_ACK;
	RF_Send_Frame.mac_ack_req = 0;
	RF_Send_Frame.mac_fn = oriMac_fn;
	memmove(RF_Send_Frame.destPSN, oriPSN, 6);
	// 调用物理层发送
	return rf_uart_send(&RF_Send_Frame);
}

// mac层发送: 数据
uint8_t rf_mac_send_data(rf_frame_t *frame, uint8_t dir, uint8_t fn, uint8_t destPSN[6])
{
	rf_ack_t ack;
	uint32_t stop_seconds;
	uint8_t count;

	// 清除回应
	xSemaphoreTake(RF_semAck, 10);
	LoopBuff_Clear(&RF_AckBuff);

	// 数据来自上层
	frame->dir = dir;
	frame->mac_type = RF_MAC_TYPE_DATA;
	if(frame->dir == RF_DIR_UP && frame->net_type == RF_NET_TYPE_DATA)
		frame->mac_ack_req = 1;
	else
		frame->mac_ack_req = 0;
	frame->mac_fn = RF_MAC_FN;
	memmove(frame->destPSN, destPSN, 6);
	// 调用物理层发送
	if(!rf_uart_send(frame))
		return 0;

	// 无须ACK确认
	if(!frame->mac_ack_req)
	{
		RF_MAC_FN++;
		return 1;
	}

	// 等待ACK确认
	stop_seconds = rf_get_seconds() + 3;
	while(rf_get_seconds() < stop_seconds)
	{
		xSemaphoreTake(RF_semAck, 500);
		count = LoopBuff_GetCount(&RF_AckBuff);
		while(count--)
		{
			memmove(&ack, LoopBuff_GetDataPtr(&RF_AckBuff, RF_AckBuff.info.rdPtr), sizeof(ack));
			LoopBuff_RemoveItems(&RF_AckBuff, 1);
			if(ack.mac_fn == RF_MAC_FN && memcmp(ack.srcPSN, destPSN, 6) == 0)
			{
				RF_MAC_FN++;
				return 1;
			}
		}
	}
	return 0;
}

// net层发送：寻找中继器
uint8_t rf_net_send_find_relay()
{
	// 清除回应
	xSemaphoreTake(RF_semGateway, 10);
	LoopBuff_Clear(&RF_GatewayBuff);

	rf_initial_frame(&RF_Send_Frame);

	RF_Send_Frame.net_type = RF_NET_TYPE_FIND_RELAY;
	// 调用mac层发送
	return rf_mac_send_data(&RF_Send_Frame, RF_DIR_UP, RF_MAC_TYPE_DATA, (uint8_t *) RF_BROADCAST_PSN);
}

// net层发送：回应中继器
uint8_t rf_net_send_resp_relay(uint8_t oriPSN[6])
{
	rf_initial_frame(&RF_Send_Frame);

	RF_Send_Frame.net_type = RF_NET_TYPE_RESP_RELAY;
	// 调用mac层发送
	return rf_mac_send_data(&RF_Send_Frame, RF_DIR_DOWN, RF_MAC_TYPE_DATA, oriPSN);
}

// net层发送：数据
uint8_t rf_net_send_data(rf_frame_t *frame, uint8_t dir, uint8_t destPSN[6])
{
	// 数据来自应用层

	frame->net_type = RF_NET_TYPE_DATA;
	// 调用mac层发送
	return rf_mac_send_data(frame, dir, RF_MAC_TYPE_DATA, destPSN);
}

// 应用层发送：回应
uint8_t rf_app_send_resp(uint8_t oriPSN[6], uint8_t oriApp_pn, uint8_t payload_len, uint8_t *payload)
{
	rf_initial_frame(&RF_Send_Frame);
	rf_append_payload(&RF_Send_Frame, payload_len, payload);
	
	RF_Send_Frame.app_pn = oriApp_pn;
	RF_Send_Frame.app_idx = 0;	// 暂不实现分包组包
	RF_Send_Frame.app_tbc = 0;
	// 调用net层发送
	return rf_net_send_data(&RF_Send_Frame, RF_DIR_DOWN, oriPSN);
}

// 应用层发送：数据
uint8_t rf_app_send_data(uint8_t payload_len, uint8_t *payload)
{
	rf_resp_t resp;
	uint32_t stop_seconds;
	uint8_t count;

	// 清除回应
	xSemaphoreTake(RF_semResp, 10);
	LoopBuff_Clear(&RF_RespBuff);
	
	rf_initial_frame(&RF_Send_Frame);
	rf_append_payload(&RF_Send_Frame, payload_len, payload);
	
	RF_Send_Frame.app_pn = RF_APP_PN;
	RF_Send_Frame.app_idx = 0;	// 暂不实现分包组包
	RF_Send_Frame.app_tbc = 0;
	// 调用net层发送
	if(rf_net_send_data(&RF_Send_Frame, RF_DIR_UP, RF_GatewayPSN) == 0)
		return 0;
	
	// 等待服务器返回：15秒
	stop_seconds = rf_get_seconds() + 15;
	while(rf_get_seconds() < stop_seconds)
	{
		xSemaphoreTake(RF_semResp, 500);
		count = LoopBuff_GetCount(&RF_RespBuff);
		while(count--)
		{
			memmove(&resp, LoopBuff_GetDataPtr(&RF_RespBuff, RF_RespBuff.info.rdPtr), sizeof(resp));
			LoopBuff_RemoveItems(&RF_RespBuff, 1);
			if(resp.app_pn == RF_APP_PN && memcmp(resp.srcPSN, RF_GatewayPSN, 6) == 0)
			{
				// print app_payload
				RF_APP_PN++;
				return 1;
			}
		}
	}
	return 0;
}

// 终端模块搜寻网关：发送搜寻命令，等待回应。
// 搜寻5次，取回应次数最多的作为通信网关。
// 最多接收10个网关
uint8_t rf_check_gateway()
{
	uint8_t PSN_List[10][6];		// 接收到的网关PSN列表
	uint8_t CNT_List[10];			// 接收到网关应答的次数
	uint8_t PSN[6];
	uint32_t stop_seconds;
	uint8_t i, j, k;
	uint8_t count;

	// 当前存在网关，直接返回
	if(memcmp(RF_GatewayPSN, RF_EMPTYPSN, 6) != 0)
		return 1;
	
	// 重新搜索网关
	memset(PSN_List, 0, sizeof(PSN_List));
	memset(CNT_List, 0, sizeof(CNT_List));
	
	// 搜寻5次
	for(i = 0; i < 5; i++)
	{
		// 发送搜寻命令
		rf_net_send_find_relay();
		// 5秒内没有收到网关回应，则停止等待
		stop_seconds = rf_get_seconds() + 5;
		while(rf_get_seconds() <= stop_seconds)
		{
			count = LoopBuff_GetCount(&RF_GatewayBuff);
			while(count--)
			{
				memmove(PSN, LoopBuff_GetDataPtr(&RF_GatewayBuff, RF_GatewayBuff.info.rdPtr), 6);
				LoopBuff_RemoveItems(&RF_GatewayBuff, 1);
				
				for(j = 0; j < 10; j++)
				{
					// 找到该PSN所在位置，或者第一个空位置
					if(memcmp(PSN_List[j], PSN, 6) == 0 || CNT_List[j] == 0)
					{
						memmove(PSN_List[j], PSN, 6);
						CNT_List[j]++;
						break;
					}
					// 没有位置则丢弃
				}
				// 延迟等待3秒
				stop_seconds = rf_get_seconds() + 3;
			}
		}
	}
	
	// 使用收到次数最多的一个
	k = 0;
	i = CNT_List[0];
	for(j = 1; j < 10; j++)
	{
		if(CNT_List[j] > i)
		{
			k = j;
			i = CNT_List[j];
		}
	}
	if(i == 0)
		return 0;

	rf_set_gateway(PSN_List[k]);
	return 1;
}

// 模块上电，设置硬件参数
void RF_PowerOn()
{
	uint16_t recv_cnt = 0;
	uint32_t stop_seconds;
	char last_c = 0, c;
	uint8_t cfg[6];
	uint16_t addr = rf_get_addr((uint8_t *) RF_BROADCAST_PSN);
	
	if(RF_hasPowered)
		return;
	
	printf("\nRF power on ...\n");
	// 将串口更改为9600bps
	LL_USART_Disable(huart8.Instance);
	RF_Uart_Open(9600);
	NVIC_DisableIRQ(UART8_IRQn);

	VCC_RF_ON();
	delay_ms(500);

//	while(!RF_READY());
	
	// 进入休眠模式：模式3
	RF_MOD_MD1_1();
	RF_MOD_MD0_1();
	delay_ms(50);
	
	cfg[0] = 0xC2;	// 设置的参数掉电不保存，每次上电都重新设置
	cfg[1] = addr >> 8;
	cfg[2] = addr & 0xFF;
	cfg[3] = 6 | (7 << 3) | (0 << 6);	// 115200bps
	cfg[4] = (dcBuff.configBottle.lora_freq%3)*2+6;//RF_UP_CHANNEL;
	cfg[5] = 1 | (1 << 2) | (9 << 3) | (0 << 7);		// freqcast=1, bw=500kHz, unicast=0 
	
	printf("\nInitialize RF Module: %02X %02X %02X %02X %02X %02X\n", 
		cfg[0], cfg[1], cfg[2], cfg[3], cfg[4], cfg[5]);
	
	UART_Transmit(&huart8, cfg, 6);
	stop_seconds = rf_get_seconds() + 2;
	while(rf_get_seconds() < stop_seconds)
	{
		if(huart8.Instance->SR & USART_SR_RXNE)
		{
			c = huart8.Instance->DR;
			printf("%c", c);
			if(c == 'K' && last_c == 'O')
			{
				// 设置状态
				RF_initStatus = 1;
				break;
			}
			last_c = c;
		}
	}	

	// 进入工作模式：模式0
	RF_MOD_MD1_0();
	RF_MOD_MD0_0();
	delay_ms(50);

//	while(!RF_READY());

	// 将串口更改为115200bps
	LL_USART_Disable(huart8.Instance);
	RF_Uart_Open(115200ul);
	NVIC_EnableIRQ(UART8_IRQn);
	
	RF_hasPowered = 1;
}

void RF_PowerOff()
{
	if(!RF_hasPowered)
		return;
	
	RF_hasPowered = 0;

	printf("\nRF power off ...\n");
	VCC_RF_OFF();
	delay_ms(200);
}

// 网关任务主体：处理接收帧（串口成帧在中断里完成）
void RF_GatewayTask(void *p_arg)
{
	uint16_t count;
	uint16_t i;
	uint32_t seconds;
	uint8_t oldRequest, incCount, newPSN;
	int16_t idx;
	ext_bottle_t	bottleRec;
	
	while(TRUE)
	{
		// 本任务读取处理队列里的帧
		// 这条语句用于任务切换（让其它任务有机会得到执行）
		xSemaphoreTake(RF_TaskQ, 0);

		count = LoopBuff_GetCount(&RF_TaskM);
		while(count--)
		{
			// 取出帧
			RF_ProcFrame = *(rf_frame_t *) LoopBuff_GetDataPtr(&RF_TaskM, RF_TaskM.info.rdPtr);
			LoopBuff_RemoveItems(&RF_TaskM, 1);

			printf("\nRF recv from Module (%d bytes):\n", RF_ProcFrame.len);
			for(i = 0; i < RF_ProcFrame.len; i++)
				printf(" %02X", ((uint8_t *) &RF_ProcFrame)[i]);
			printf("\n");
			
			seconds = rf_get_seconds();
			RF_seconds = seconds;
			
			// 未获取到绝对时间，不能存储和转发，故不能应答
			if(RTC_offsetSeconds == 0)
			{
				printf("\nRTC_offsetSeconds = 0, ignored ...\n");
			//apex	continue;
			}
			
			// 处理帧
      idx = Ext_Lookup_Bottle_PSN(RF_ProcFrame.srcPSN, bottleCnt.count);
			if(idx == -1) continue;
			// 是否需要回应ack
			if(RF_ProcFrame.mac_ack_req)
			{
				// 生成确认帧
				RF_Send_Rec.type = 0;
				memmove(RF_Send_Rec.oriPSN, RF_ProcFrame.srcPSN, 6);
				RF_Send_Rec.fn_pn = RF_ProcFrame.mac_fn;
				// 统一加到发送队列
				LoopBuff_PutItem(&RF_SendM, (uint8_t *) &RF_Send_Rec);

				// 发消息给任务
				xSemaphoreGive(RF_SendQ);
			}
			
			if(RF_ProcFrame.net_type == RF_NET_TYPE_FIND_RELAY)
			{
				// 生成中继应答帧
				RF_Send_Rec.type = 1;
				memmove(RF_Send_Rec.oriPSN, RF_ProcFrame.srcPSN, 6);
				RF_Send_Rec.fn_pn = RF_ProcFrame.app_pn;
				// 统一加到发送队列
				LoopBuff_PutItem(&RF_SendM, (uint8_t *) &RF_Send_Rec);

				// 发消息给任务
				xSemaphoreGive(RF_SendQ);
			}
			else if(RF_ProcFrame.net_type == RF_NET_TYPE_DATA)
			{
				printf("\n*** PSN: 20%02d%02d%02d%02d%03d ***, ", 
					RF_ProcFrame.srcPSN[0], RF_ProcFrame.srcPSN[1], RF_ProcFrame.srcPSN[2], RF_ProcFrame.srcPSN[3],
						(RF_ProcFrame.srcPSN[4] << 8) | RF_ProcFrame.srcPSN[5]);

				// 查找并维护该节点的状态
				oldRequest = 0;
				incCount = 0;
				newPSN = 1;

//				idx = Ext_Lookup_Bottle_PSN(RF_ProcFrame.srcPSN, bottleCnt.count);
				if(idx >= 0)
				{
					newPSN = 0;				// 已有PSN
					FRAM_BufferRead(FRAM_BOTTLE_DATA_BASE + sizeof(ext_bottle_t) * bottlePSN[idx].recNo, (uint8_t *) &bottleRec, sizeof(ext_bottle_t));
					oldRequest = (bottleRec.pn == RF_ProcFrame.app_pn && RTC_offsetSeconds + seconds < bottleRec.recvTime + 72 * 3600);
				}
				if(idx == -1 && bottleCnt.count < FRAM_BOTTLE_COUNT)
				{
					incCount = 1;			// 添加一个PSN
					idx = bottleCnt.count;	
					bottlePSN[idx].recNo = idx;
				}
				if(idx == -1)
				{
					for(i = 0; i < FRAM_BOTTLE_COUNT; i++)
					{
						FRAM_BufferRead(FRAM_BOTTLE_DATA_BASE + sizeof(ext_bottle_t) * bottlePSN[i].recNo, (uint8_t *) &bottleRec, sizeof(ext_bottle_t));
						if(bottleRec.lastData == -1) // 取代一个无历史数据的PSN
						{
							idx = i;
							break;
						}
					}
				}

				if(idx >= 0)
				{
					// 修改储罐档案 
					if(incCount || newPSN)
					{
						memset(&bottleRec, 0, sizeof(ext_bottle_t));
						bottleRec.lastData = -1;
					}
					memmove(bottleRec.PSN, RF_ProcFrame.srcPSN, 6);
					bottleRec.pn = RF_ProcFrame.app_pn;
					bottleRec.recvTime = RTC_offsetSeconds + seconds;
					FRAM_BufferWrite(FRAM_BOTTLE_DATA_BASE + sizeof(ext_bottle_t) * bottlePSN[idx].recNo, (uint8_t *) &bottleRec, sizeof(ext_bottle_t));
					// 修改总数
					if(incCount)
					{
						bottleCnt.count++;
						FRAM_SaveInfo(FRAM_BOTTLE_INFO_BASE, (uint8_t *) &bottleCnt, sizeof(ext_count_t));
					}
					// 重建索引
					if(incCount || newPSN)
					{
						memmove(bottlePSN[idx].PSN, bottleRec.PSN, 6);
						Ext_Sort_Bottle_PSN(bottlePSN, 0, bottleCnt.count - 1);
					}
				}

				if(!oldRequest) // 新节点或新记录，需要转发给服务器
				{
					printf("\nNew request, add to queue\n");

					// 生成上传记录，加到上传队列
					memmove(Ext_Data_Rec.oriPSN, RF_ProcFrame.srcPSN, 6);
					Ext_Data_Rec.payload_len = RF_ProcFrame.len - RF_MIN_FRAME_LEN;
					memmove(Ext_Data_Rec.payload, RF_ProcFrame.app_payload, Ext_Data_Rec.payload_len);
					Ext_Data_Rec.recvTime = RTC_offsetSeconds + seconds;
					
					// 加到上传队列
					Data_PutToQueue(&Ext_Data_Rec);
				}
			
				// 直接生成返回数据帧（上传记录存到flash里）
				RF_Send_Rec.type = 2;
				memmove(RF_Send_Rec.oriPSN, RF_ProcFrame.srcPSN, 6);
				RF_Send_Rec.fn_pn = RF_ProcFrame.app_pn;
				RF_Send_Rec.payload_len = 2;
				RF_Send_Rec.payload[0] = 0xFF;
				RF_Send_Rec.payload[1] = 0xFF;				
				// 统一加到发送队列
				LoopBuff_PutItem(&RF_SendM, (uint8_t *) &RF_Send_Rec);
			
				// 发消息给任务
				xSemaphoreGive(RF_SendQ);
			}
		}
	}
}

// 网关任务主体：处理上传帧
void RF_TranTask(void *p_arg)
{
	uint32_t stop_seconds;
	uint16_t i;
	uint32_t checkTick = 30000;
	static int Ethernet_fail_count = 0;
	S_RTC_TIME_DATA_T sRTC;
	
	while(TRUE)
	{
		// 每30秒检查一次网络连接情况
		if(IsTickOut(checkTick))
		{
			checkTick = GetDelayTick(30000);
			
			Ethernet_connected = IS_VCC_ETHERNET_ON() && Ethernet_IsConnected();
			if(IS_VCC_ETHERNET_ON() && !Ethernet_connected)
				Ethernet_fail_count++;
		}

		// 获取锁（4G优先，4G不能发送时才用网口发送）
		if(xSemaphoreTake(RF_TranLock, 500) != pdTRUE)
		{
			VCC_ETHERNET_OFF();
			Ethernet_connected = 0;
			continue;
		}
		
//		// 多次失败，重启网络模块（因网络模块设置了超时重启，故此处不用人工重启）
//		if(Ethernet_fail_count >= 6)
//			VCC_ETHERNET_OFF();
		if(!IS_VCC_ETHERNET_ON())
		{
			Ethernet_fail_count = 0;
			Ethernet_Config();
		}
		
		// 掉电有效，如果未获取到UTC时间，不转发
		if(RTC_offsetSeconds > 0 && LoopBuff_GetCount(&RF_TranM) > 0 && Ethernet_connected)
		{
			if(!SFlash_LoadInfo(LoopBuff_GetDataPos(&RF_TranM, RF_TranM.info.rdPtr), (uint8_t *) &Ext_Data_Rec1, sizeof(ext_data_t)))
			{
				LoopBuff_RemoveItems(&RF_TranM, 1);
				// 保存到铁电
				FRAM_SaveInfo(RF_TranM.info_base, (uint8_t *) &RF_TranM.info, sizeof(RF_TranM.info));
			}
			else
			{
				i = pack_gprs_tran_data(&Ext_Data_Rec1, 0);
				
				delay_ms(20);
				
				// 先清除接收消息和缓冲区
				do
				{
					LoopBuff_Clear(&Ethernet_Buff);
				} while(xSemaphoreTake(Ethernet_semQ, 100) == pdTRUE || LoopBuff_GetCount(&Ethernet_Buff) > 0);
				
				// TODO: 发送到服务器，并等待返回
				printf("\nEthernet send to server\n");
				UART_Transmit(&huart3, Task_sendBuff, i);

				// 先预设发送失败，以防止假连接状态
				Ethernet_fail_count++;
				
				stop_seconds = rf_get_seconds() + 6;
				while(rf_get_seconds() < stop_seconds)
				{
					// 这条语句用于任务切换（让其它任务有机会得到执行）
					xSemaphoreTake(Ethernet_semQ, 500);
					if(LoopBuff_GetCount(&Ethernet_Buff) >= 2) // 服务器有返回
					{
						printf("\nResponse from server:");
						while(LoopBuff_GetCount(&Ethernet_Buff) > 0)
						{
							printf(" %02X", *LoopBuff_GetDataPtr(&Ethernet_Buff, Ethernet_Buff.info.rdPtr));
							LoopBuff_RemoveItems(&Ethernet_Buff, 1);
						}
						printf("\n");

						// 发送成功，失败次数清零
						Ethernet_connected = IS_VCC_ETHERNET_ON();
						Ethernet_fail_count = 0;
						
						// 删除当前记录
						LoopBuff_RemoveItems(&RF_TranM, 1);
						// 保存到铁电
						FRAM_SaveInfo(RF_TranM.info_base, (uint8_t *) &RF_TranM.info, sizeof(RF_TranM.info));
						// 记录发送成功的时间
						RTC_GetDateAndTime(&sRTC);
						DTU_succTime = Calc_SecondsFromYear(INITIAL_YEAR, sRTC.u32Year, sRTC.u32Month, sRTC.u32Day,
								sRTC.u32Hour, sRTC.u32Minute, sRTC.u32Second);
						break;
					}
				}
			}
		}
		
		// 释放锁（4G优先，让4G有机会发送）
		xSemaphoreGive(RF_TranLock);
	}
}

// 网关任务主体：处理发送帧
void RF_SendTask(void *p_arg)
{
	uint16_t count;
	
	while(TRUE)
	{
		// 喂狗
		HAL_IWDG_Refresh(&hiwdg);
		
		// 本任务读取发送队列的记录
		// 这条语句用于任务切换（让其它任务有机会得到执行）
		xSemaphoreTake(RF_SendQ, 1000);

		count = LoopBuff_GetCount(&RF_SendM);
		while(count--)
		{
			// 取出记录
			RF_Send_Rec1 = *(rf_send_queue_t *) LoopBuff_GetDataPtr(&RF_SendM, RF_SendM.info.rdPtr);
			LoopBuff_RemoveItems(&RF_SendM, 1);
			
			if(RF_Send_Rec1.type == 0) // 发送MAC_ACK
				rf_mac_send_ack(RF_DIR_UP, RF_Send_Rec1.fn_pn, RF_Send_Rec1.oriPSN);
			else if(RF_Send_Rec1.type == 1) // 发送RESP_RELAY
				rf_net_send_resp_relay(RF_Send_Rec1.oriPSN);
			else if(RF_Send_Rec1.type == 2) // 发送应用层返回数据
				rf_app_send_resp(RF_Send_Rec1.oriPSN, RF_Send_Rec1.fn_pn, RF_Send_Rec1.payload_len, RF_Send_Rec1.payload);
			// 延时，让设备端处理
			osDelay(250);
		}		
	}
}
