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

/*
*********************************************************************************************************
*                                             INCLUDE FILES
*********************************************************************************************************
*/
#include  <includes.h>

// ETHERNET串口接收的循环缓冲
#define ETHERNET_DATA_COUNT 200
loopbuff_t Ethernet_Buff;
uint8_t Ethernet_Buff_Data[sizeof(uint8_t) * (ETHERNET_DATA_COUNT + 1)] = {0};
// ETHERNET串口接收的消息通知
SemaphoreHandle_t	   Ethernet_semQ = NULL;

// ETHERNET串口AT命令接收的循环缓冲
#define ETHERNET_ATDATA_COUNT 50
loopbuff_t Ethernet_ATBuff;
uint8_t Ethernet_ATBuff_Data[sizeof(uint8_t) * (ETHERNET_ATDATA_COUNT + 1)] = {0};

// 网口初始化状态
uint8_t Ethernet_initStatus = 0, Ethernet_connected = 0;

static void Ethernet_IRQHandler(USART_Handle *huart)
{
	BaseType_t xHigherPriorityTaskWoken;

	uint8_t c = (uint8_t) huart->Instance->DR;
	// 加入缓冲
	LoopBuff_PutItem(&Ethernet_Buff, &c);
	// 发消息给任务
	xSemaphoreGiveFromISR(Ethernet_semQ, &xHigherPriorityTaskWoken);
}

static void Ethernet_ATHandler(USART_Handle *huart)
{
	uint8_t c = (uint8_t) huart->Instance->DR;
	// 加入缓冲
	LoopBuff_PutItem(&Ethernet_ATBuff, &c);
}

void Ethernet_Send(char *buf)
{
	UART_Transmit(&huart3, (uint8_t *) buf, strlen(buf));
}

// 非中断方式，直接从串口接收数据
uint16_t Ethernet_Recv(char *buf, uint16_t wait_cnt)
{
	uint16_t recv_cnt = 0;
	uint32_t stop_seconds;
	char c;
	
	stop_seconds = rf_get_seconds() + 2;
	while(rf_get_seconds() < stop_seconds)
	{
		if(LoopBuff_GetCount(&Ethernet_ATBuff) > 0)
		{
			c = *(uint8_t *) LoopBuff_GetDataPtr(&Ethernet_ATBuff, Ethernet_ATBuff.info.rdPtr);
			LoopBuff_RemoveItems(&Ethernet_ATBuff, 1);
			printf("%c", c);
			if(c != '\r' && c != '\n')
			{
				buf[recv_cnt++] = c;
				if(recv_cnt == wait_cnt)
					break;
			}
		}
	}
	
	return recv_cnt;
}

// 进入AT命令模式
uint8_t Ethernet_ATMode()
{
	uint8_t try_cnt;
	char buf[3] = {0};
	
	// 进入AT命令模式
	for(try_cnt = 0; try_cnt < 3; try_cnt++)
	{
		// 先进入AT命令模式
		delay_ms(100);
		Ethernet_Send("+++");
		if(Ethernet_Recv(buf, 1) < 1 || buf[0] != 'a')
			continue;
		
		Ethernet_Send("a");
		if(Ethernet_Recv(buf, 3) < 3 || strncmp(buf, "+ok", 3) != 0)
			continue;
		
		// 成功进入AT命令模式
		delay_ms(100);
		return 1;
	}
	
	return 0;
}

uint8_t Ethernet_ATCmd(char *cmd, char *ok_str, char *err_str)
{
	char buf[21], c;
	uint8_t try_cnt;
	uint16_t recv_cnt = 0;
	uint32_t stop_seconds;
	
	memset(buf, 0, sizeof(buf));
	for(try_cnt = 0; try_cnt < 3; try_cnt++)
	{
		// 清空串口缓冲区
		LoopBuff_Clear(&Ethernet_ATBuff);
		// 发送命令
		Ethernet_Send(cmd);
		Ethernet_Send("\r");
		// 等待返回数据
		stop_seconds = rf_get_seconds() + 2;
		while(rf_get_seconds() < stop_seconds)
		{
			if(LoopBuff_GetCount(&Ethernet_ATBuff) > 0)
			{
				c = *(uint8_t *) LoopBuff_GetDataPtr(&Ethernet_ATBuff, Ethernet_ATBuff.info.rdPtr);
				LoopBuff_RemoveItems(&Ethernet_ATBuff, 1);
				printf("%c", c);
				if(c != '\r' && c != '\n')
				{
					buf[recv_cnt++] = c;
					if(strstr(buf, ok_str) != NULL)
						return 1;
					if(strstr(buf, err_str) != NULL)
						return 0;
				}
			}
		}
	}

	return 0;
}

void Ethernet_Open()
{
	// 创建消息队列
	LoopBuff_Create(&Ethernet_Buff, sizeof(uint8_t), ETHERNET_DATA_COUNT, 0, (uint32_t) Ethernet_Buff_Data);
	LoopBuff_Create(&Ethernet_ATBuff, sizeof(uint8_t), ETHERNET_ATDATA_COUNT, 0, (uint32_t) Ethernet_ATBuff_Data);

	// 创建信号量
	Ethernet_semQ = xSemaphoreCreateBinary();

	SET_BIT(USART3->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE);
	LL_USART_Enable(USART3);
}

// 本函数要用到中断，只能在任务启动以后执行
void Ethernet_Config()
{
	huart3.RxISR = Ethernet_ATHandler;
	
	delay_ms(100);
	VCC_ETHERNET_ON();
	delay_ms(1000);
	
	// 设置状态
	Ethernet_initStatus = 0;
	Ethernet_connected = 0;
	
	// 设置Usr_K3工作方式
#if 1	
	// 进入AT命令模式
	if(!Ethernet_ATMode())
		return;
	// 设置命令不回显
	if(!Ethernet_ATCmd("AT+E=OFF", "+OK", "+ERR"))
		return;
	// 设置DHCP
	if(!Ethernet_ATCmd("AT+WANN=DHCP", "+OK", "+ERR"))
//	if(!Ethernet_ATCmd("AT+WANN=STATIC,192.168.0.3,255.255.255.0,192.168.0.1", "+OK", "+ERR"))
		return;
	// 设置DNS（如DHCP配置可不设DNS)
//	if(!Ethernet_ATCmd("AT+DNS=202.106.0.20", "+OK", "+ERR"))
//		return;
	// 设置TCP模式、服务器、端口
	if(RF_APP == RF_APP_AJH)
	{
//		if(!Ethernet_ATCmd("AT+SOCKA1=TCPC,171.88.5.52,8061", "+OK", "+ERR"))	// 公司路由器
		if(!Ethernet_ATCmd("AT+SOCKA1=TCPC,extra.cd-ls.cn,8061", "+OK", "+ERR"))
//		if(!Ethernet_ATCmd("AT+SOCKA1=TCPC,data.ajhiot.com,8088", "+OK", "+ERR"))
//		if(!Ethernet_ATCmd("AT+SOCKA1=TCPC,114.55.209.85,8088", "+OK", "+ERR")) // data.ajhiot.com
//		if(!Ethernet_ATCmd("AT+SOCKA1=TCPC,192.168.0.2,8061", "+OK", "+ERR"))	  // 直连电脑
			return;
	}
	else if(RF_APP == RF_APP_PRAX)
	{
		if(!Ethernet_ATCmd("AT+SOCKA1=TCPC,tts.praxair.com.cn,7005", "+OK", "+ERR"))
			return;
	}
	else
	{
		if(!Ethernet_ATCmd("AT+SOCKA1=TCPC,data.cd-ls.cn,8088", "+OK", "+ERR"))
			return;
	}
		
	// 关闭串口心跳包
	if(!Ethernet_ATCmd("AT+HEARTEN1=OFF", "+OK", "+ERR"))
		return;
	// 关闭串口注册包
	if(!Ethernet_ATCmd("AT+REGEN1=OFF", "+OK", "+ERR"))
		return;
	// 关闭短连接功能
	if(!Ethernet_ATCmd("AT+SOCKSL1=OFF", "+OK", "+ERR"))
		return;
	// 设置超时重启时间：60秒
	if(!Ethernet_ATCmd("AT+RSTIM=60", "+OK", "+ERR"))
		return;
	// 连接前是否清理串口缓存？
	if(!Ethernet_ATCmd("AT+UARTCLBUF=ON", "+OK", "+ERR"))
		return;
	// 设为默认参数
	if(!Ethernet_ATCmd("AT+CFGTF", "saved", "+ERR"))
		return;
	// 重启模块
	if(!Ethernet_ATCmd("AT+Z", "OK", "+ERR"))
		return;
#endif

    /* Enable UART3 interrupt */
	huart3.RxISR = Ethernet_IRQHandler;
	
	// 设置状态
	Ethernet_initStatus = 1;
}

// 检查服务器连接情况
uint8_t Ethernet_IsConnected()
{
	u8 try_count;
	u8 atMode = 0, connected = 0, tranMode = 0;
	
	huart3.RxISR = Ethernet_ATHandler;

	// 清除串口缓冲数据
	LoopBuff_Clear(&Ethernet_ATBuff);
	
	// 进入AT命令模式，3次不成功则复位
	for(try_count = 0; try_count < 3; try_count++)
	{
		if(Ethernet_ATMode())
		{
			atMode = 1;
			break;
		}
		osDelay(500);
	}
	
	if(atMode)
	{
		// 检查是否连上网络
		connected = Ethernet_ATCmd("AT+SOCKLKA1", "+OK=CONNECTED", "+OK=CONNECTING");

		// 进入透传模式，3次不成功则复位
		for(try_count = 0; try_count < 3; try_count++)
		{
			if(Ethernet_ATCmd("AT+ENTM", "+OK", "+ERR"))
			{
				tranMode = 1;
				break;
			}
			osDelay(500);
		}
	}
	
	huart3.RxISR = Ethernet_IRQHandler;
	
	return (atMode && connected && tranMode);
}
