#include "ramses.h"

osThreadId_t Ramses_Handle;
const osThreadAttr_t Ramses_attributes = {
	.name = "RAMSES",
	.stack_size = 1024,
	.priority = (osPriority_t)osPriorityBelowNormal,
};

// 事件
osEventFlagsId_t Ramses_EventHandle;
const osEventFlagsAttr_t Ramses_Event_attributes = {
	.name = "Ramses_Event"};

extern UART_HandleTypeDef huart1;
UART_HandleTypeDef *pRamsesUart = &huart1;

// local rcv_str = string.fromHex("23000080A8008101")
// local rcv_str_sn = string.fromHex("23000080B0000001")

uint8_t Ramses_SN_Command[8] = {0x23, 0x00, 0x00, 0x80, 0xB0, 0x00, 0x00, 0x01};
uint8_t Ramses_Measure_Command[8] = {0x23, 0x00, 0x00, 0x80, 0xA8, 0x00, 0x81, 0x01};
uint8_t Ramses_Auot_Integration[8] = {0x23, 0x00, 0x00, 0x30, 0x78, 0x05, 0x00, 0x01}; // 00 自动积分


uint8_t Ramses_Rcv_Buf[1024] = {0};

UART_HELPER_TypeDef *Ramses_uart_helper;

Ramses_TypeDef ramses = {
	Ramses_Init,
	Ramses_Port,
	Ramses_Test,
	Ramses_Start,
	Ramses_Stop,
	NULL,
	0,	  // state
	0,	  // data_ok
	{0},  // buf
	0,	  // size_received

    0,  // flag;
    0,  //  flag_ip;
    0,  // data_index;    recv_buf数组的索引
    0,  // recv_buf_p;    recv_buf每组的元素下标
    0,  // data_size;
    0,  // recv_flag_40;
    {0}, // cmd_buf[Ramses_CMD_SIZE];

    {0},  // RAMSES_Info_TypeDef information;
    {0},  // RAMSES_IP_TypeDef ip;
    {0},  // RAMSES_Data_TypeDef data[Ramses_DATA_NUM];
    {0},  // uint8_t recv_buf[Ramses_DATA_SIZE];
    0xFFFF,  //sn
    0,  // error;

    0,  // uint64_t  timebase_ticks;
    0,  //uint64_t  timeout_ticks;
};

int Ramses_Init()
{
	Ramses_uart_helper = UART_HELPER_Init();

	if (Ramses_uart_helper == NULL)
		return -1;

	// TODO 接口
	UART_HELPER_Set_Huart(Ramses_uart_helper, pRamsesUart);
	UART_HELPER_Set_Interface_Type(Ramses_uart_helper, Uart_Interface_Max3160_485);

	//  传输
	UART_HELPER_Setup_Trans_mode(Ramses_uart_helper, Uart_Trans_DMA);
	// UART_HELPER_Setup_Rcv_mode( Ramses_uart_helper, Uart_Trans_IT );
	UART_HELPER_Set_enable_idle(Ramses_uart_helper, Uart_IDLE_IT_ENABLE);

	//  回调GPIO 操作 数据操作
	UART_HELPER_Set_trans_GPIO(Ramses_uart_helper, Ramses_Trans_GPIO); // enbale rcv
	UART_HELPER_Set_trans_cplt_GPIO(Ramses_uart_helper, Ramses_Trans_Cplt_GPIO);

	UART_HELPER_Set_Callback(Ramses_uart_helper, &ramses, Ramses_CallBack);

	// 设置 Buf, 如果启用消息队列，不启用trans_buf
	UART_HELPER_Set_Rcv_Buf(Ramses_uart_helper, Ramses_Rcv_Buf, sizeof(Ramses_Rcv_Buf));
	UART_HELPER_Set_Trans_Buf(Ramses_uart_helper, Ramses_SN_Command, sizeof(Ramses_SN_Command));

	//  GPIO 操作
	switch (Ramses_uart_helper->interface_type)
	{
	case Uart_Interface_Default:
		break;
	case Uart_Interface_485:
		usart6_send_enable();
		break;
	case Uart_Interface_Max3160_232:
		Ramses_MAX3160_232();
		break;
	case Uart_Interface_Max3160_485:
		max3160_485_receive_mode();
		break;
	default:
		break;
	}
	ramses.state = MODULE_RAMSES_STATE_WAIT;
	ramses.timebase_ticks = osKernelGetTickCount();

	// TODO enable trans queue
	// 最大队列数 8, 消息类型， 值传递（内含的buf为指针，如何包含大空间的buf,可选择指针传递 ）
	// ramses.transQueue = osMessageQueueNew(8, sizeof(Record_Trans_Rcv_TypeDef), NULL);
}

void Ramses_Port( )
{
	Ramses_Handle = osThreadNew(Ramses_Task, (void*)&ramses, &Ramses_attributes);
	// Ramses_EventHandle = osEventFlagsNew( &Ramses_Event_attributes );
}

int Ramses_Test( )
{
	// SN
 
	// 改变操作状态
	ramses.state = MODULE_RAMSES_STATE_TEST; // 操作状态
	return 0;
}

 

void Ramses_Start( )
{
	// 装Data

	ramses.state = MODULE_RAMSES_STATE_START; // 操作状态
	// osEventFlagsSet( Ramses_EventHandle, Ramses_Event_Get_Data );  // 事件
}

void Ramses_Stop( )
{
	ramses.state = MODULE_RAMSES_STATE_STOP;
	// TODO stop  task？
}

void Ramses_Task(void *arg)
{
	// ramses.event_flag = 0;
	uint64_t ticks;
	static int err_con = 0;
	static int st = 0;
	// Ramses_TypeDef *pRamses = arg;

	for (;;)
	{
        switch ( ramses.state )
        {
            case MODULE_RAMSES_STATE_WAIT:
				osDelay(20);
                break;
            // case MODULE_RAMSES_STATE_START:
			// 	err_con = 0;
            //     ramses.state = MODULE_RAMSES_STATE_TEST;
            //     break;

            case MODULE_RAMSES_STATE_TEST:
                ramses.timebase_ticks = osKernelGetTickCount();
                // sensor_enable();
				ramses.size_received = 0;
				memset( ramses.result_buf, 0, sizeof(ramses.result_buf) );
				UART_HELPER_Set_Trans_Buf( Ramses_uart_helper, Ramses_SN_Command, sizeof(Ramses_SN_Command) );
				Ramses_Receive();
				Ramses_Transmit();
                ramses.state = MODULE_RAMSES_STATE_TESTING;
                break;

            case MODULE_RAMSES_STATE_TESTING:
				//  查找获得信息帧的标记
				log_d( " ramses.flag :: %d   %d",  ramses.flag, ramses.flag&Ramses_FLAG_MASK_RECVED_INFO);
				if (  (ramses.flag&Ramses_FLAG_MASK_RECVED_INFO)!=0 )
				{
					ramses.sn = ramses.information.serial_number;
				}
				if ( ramses.sn != 0xFFFF ) 
				{
					// TODO: send auto integrations		
					UART_HELPER_Set_Trans_Buf( Ramses_uart_helper, Ramses_Auot_Integration, sizeof(Ramses_Auot_Integration) );
					Ramses_Transmit();			
					ramses.state = MODULE_RAMSES_STATE_READY;
					log_d("  SN :  %04X", ramses.sn);
					break;
				}
				if ( (osKernelGetTickCount() - ticks) > 2000 )
				{
					log_w( " Ramses_ State_SN_Getting -> retry : %d  " , err_con    );
					err_con++;
					if ( err_con > 5)
					{
						log_w(" Ramses_ testing  ... error ");
						err_con = 0;
						ramses.state = MODULE_RAMSES_STATE_ERROR;
						break;
					}
					ramses.state = MODULE_RAMSES_STATE_TEST;   // 重新发送取出来的队列
				}
				osDelay(1);
                break;

            case MODULE_RAMSES_STATE_READY:
				log_d( "MODULE_RAMSES_STATE_READY ..... "   );
				osDelay(20);
                break;

            case MODULE_RAMSES_STATE_START:
				log_d( "MODULE_RAMSES_STATE_START ..... "   );
				err_con = 0;
				ramses.state = MODULE_RAMSES_STATE_SEND_CMD;
				continue;

            case MODULE_RAMSES_STATE_SEND_CMD:

				ramses.flag&=~Ramses_FLAG_MASK_RECVED_INFO;

                // sensor_enable();
                ramses.timebase_ticks = osKernelGetTickCount();
				ramses.size_received = 0;
				memset( ramses.result_buf, 0, sizeof(ramses.result_buf) );
				UART_HELPER_Set_Trans_Buf(Ramses_uart_helper, Ramses_SN_Command, sizeof(Ramses_SN_Command));
				Ramses_Receive();
				Ramses_Transmit();
                ramses.state = MODULE_RAMSES_STATE_CHECK_SENSOR;
                continue;;

			//  每次测量前信息帧check_sensor 状态
            case MODULE_RAMSES_STATE_CHECK_SENSOR:
				log_d( "MODULE_RAMSES_STATE_START ..... "   );
				if (  (ramses.flag&Ramses_FLAG_MASK_RECVED_INFO)!=0 )
				{
					log_d("  info frame is received, send cmd" );
					ramses.flag&=~Ramses_FLAG_MASK_RECVED_DATA;
					ramses.size_received = 0;
					memset( ramses.result_buf, 0, sizeof(ramses.result_buf) );
					UART_HELPER_Set_Trans_Buf(Ramses_uart_helper, Ramses_Measure_Command, sizeof(Ramses_Measure_Command));
					Ramses_Receive();
					Ramses_Transmit();
					ramses.state = MODULE_RAMSES_STATE_GET_DATA;
					break;
				}
				if ( (osKernelGetTickCount() - ticks) > 2000 )
				{
					log_w( " Ramses_ State Check sensor -> retry : %d  " , err_con    );
					err_con++;
					if ( err_con > 5)
					{
						log_w(" Ramses_ State Check sensor  ... error ");
						err_con = 0;
						ramses.state = MODULE_RAMSES_STATE_ERROR;
						break;
					}
					ramses.state = MODULE_RAMSES_STATE_SEND_CMD;   // 重新发送 
				}
				osDelay(1);
				break;
            case MODULE_RAMSES_STATE_GET_DATA:
				if (  (ramses.flag&Ramses_FLAG_MASK_RECVED_DATA)!=0 )
				{
					log_d("  data frame is received, send cmd" );
					ramses.state = MODULE_RAMSES_STATE_OK;
					break;
				}
				if ( (osKernelGetTickCount() - ticks) > 10000 )
				{
					log_w( " Ramses_ State Check sensor -> retry : %d  " , err_con    );
					err_con++;
					if ( err_con > 5)
					{
						log_w(" Ramses_ State Check sensor  ... error ");
						err_con = 0;
						ramses.state = MODULE_RAMSES_STATE_ERROR;
						break;
					}
					ramses.state = MODULE_RAMSES_STATE_SEND_CMD;   // 重新发送 
				}
				osDelay(1);
				break;
            case MODULE_RAMSES_STATE_OK:
				osDelay(200);
                break;
            case MODULE_RAMSES_STATE_ERROR:
				log_w(" MODULE_RAMSES_STATE_ERROR ....  ");
				err_con = 0;
				ramses.size_received = 0;
				memset( ramses.result_buf, 0, sizeof(ramses.result_buf) );
				osDelay(200);
                break;
            case MODULE_RAMSES_STATE_STOP:
				osDelay(200);
                break;
            default:
                ramses.state=MODULE_RAMSES_STATE_WAIT;
                break;
        }
		osDelay(20);
	}
}

void Ramses_Trans_GPIO(void)
{
	// HAL_GPIO_WritePin(R_W_GPIO_Port,R_W_Pin, SET);
	// HAL_GPIO_WritePin(NULL,0, SET);
	HAL_GPIO_WritePin(SEL_232_485_GPIO_Port, SEL_232_485_Pin, SET);
	HAL_GPIO_WritePin(HDPLX_GPIO_Port, HDPLX_Pin, RESET);
	HAL_GPIO_WritePin(DE485_GPIO_Port, DE485_Pin, SET);
}

void Ramses_Trans_Cplt_GPIO(void)
{
	// HAL_GPIO_WritePin(R_W_GPIO_Port,R_W_Pin, RESET);
	// HAL_GPIO_WritePin(NULL,0, RESET);
	HAL_GPIO_WritePin(SEL_232_485_GPIO_Port, SEL_232_485_Pin, SET);
	HAL_GPIO_WritePin(HDPLX_GPIO_Port, HDPLX_Pin, SET);
	HAL_GPIO_WritePin(DE485_GPIO_Port, DE485_Pin, RESET);
}

int Ramses_Transmit()
{
	//  TODO 结合队列
	ramses.size_received = 0;
	if (Ramses_uart_helper->transferring == 0)
	{
		return UART_HELPER_Trans(Ramses_uart_helper, Ramses_uart_helper->trans_record->buf, Ramses_uart_helper->trans_record->size);
	}
	return 0;
}

int Ramses_Receive()
{
	return UART_HELPER_Start_Rcv(Ramses_uart_helper, Ramses_uart_helper->rcv_buf, Ramses_uart_helper->rcv_size);
	// return 0;
}

void Ramses_Set_Timeout_ms(uint64_t ms_ticks)
{
	ramses.timeout_ticks = ms_ticks;
}

int Ramses_Validate()
{
	return CRC16_Check(ramses.result_buf ,ramses.size_received);
}



int Ramses_CallBack(Ramses_TypeDef *pRamses, uint8_t *buf, uint16_t size)
{
	log_d(" Ramses_CallBack  -- state %d   size %d", ramses.state, size);

    int i;
    int j = 0;

    for(i=0;i<size;i++){
					// log_i("recv_buf i %d",i);
        if ( ramses.recv_buf_p==0 && buf[i]!=0x23 ){  // 下标为0，找0x23 可以过滤0x13 0x11
            continue; 
        }
        if(ramses.recv_flag_40==1){
            if(buf[i]==0x64){
                ramses.recv_buf[ramses.recv_buf_p++]=0x40;
            }
            else if(buf[i]==0x65){
                ramses.recv_buf[ramses.recv_buf_p++]=0x23;
            }
            else if(buf[i]==0x66){
                ramses.recv_buf[ramses.recv_buf_p++]=0x11;
            }
            else if(buf[i]==0x67){
                ramses.recv_buf[ramses.recv_buf_p++]=0x13;
            }
            else{
                ramses.data_index=0;
                ramses.recv_flag_40=0;
                ramses.recv_buf_p=0;
                continue;
            }
            ramses.recv_flag_40=0;
        }
        else if(buf[i]==0x40){
            ramses.recv_flag_40=1;
        }
        else{  //  每帧 recv_buf中的 数组下标
            ramses.recv_buf[ramses.recv_buf_p++]=buf[i];
			// j++;
        }
	
		//    每帧数据数量 大于7 判断类型，且长度校验通过 
        if(ramses.recv_buf_p>7 && ramses.recv_buf_p==8+(2<<(ramses.recv_buf[1]>>5))){
            if(ramses.recv_buf[4]==0xff){   // 0xff  表征 SN信息帧
				// log_i(" info frame .... ") ;
                if(ramses.recv_buf_p!=Ramses_INFO_SIZE){
                    ramses.recv_flag_40=0;
                    ramses.recv_buf_p=0;
                    continue;
                }
                ramses.information.dev_id=((uint16_t)ramses.recv_buf[1]<<8)+ramses.recv_buf[2];
                ramses.information.module_id=ramses.recv_buf[3];
                ramses.information.serial_number=((uint16_t)ramses.recv_buf[8]<<8)+ramses.recv_buf[7];
                ramses.information.firmware_number[0]=ramses.recv_buf[10];
                ramses.information.firmware_number[1]=ramses.recv_buf[9];
                memcpy(ramses.information.individual_information,&ramses.recv_buf[7],Ramses_INFO_SIZE-12);
                ramses.recv_buf_p=0;
                ramses.flag|=Ramses_FLAG_MASK_RECVED_INFO;
                ramses.flag&=~Ramses_FLAG_MASK_BUSY;
            }
            else if(ramses.recv_buf[4]==0xfe){  // 0xfe错误
                ramses.data_index=0;
                ramses.recv_flag_40=0;
                ramses.recv_buf_p=0;
                continue;
            }
            else{
                if(ramses.recv_buf[3]==0x80 || ramses.recv_buf[3]==0x30 || ramses.recv_buf[3]==0x00){
                    // log_i("....  0x80 0x 30  0x00");
                    if((ramses.flag&Ramses_FLAG_MASK_RECVED_DATA)!=0){  // 判断为数据帧
                        ramses.data_index=0;
                        ramses.recv_flag_40=0;
                        ramses.recv_buf_p=0;
                        continue;
                    }
                    if(ramses.recv_buf_p!=Ramses_DATA_SIZE){
                        ramses.recv_flag_40=0;
                        ramses.recv_buf_p=0;
                        continue;
                    }
                    if(ramses.recv_buf[4]!=Ramses_DATA_NUM-1-ramses.data_index){
                        ramses.data_index=0;
                        ramses.recv_flag_40=0;
                        ramses.recv_buf_p=0;
                        continue;
                    }
                    memcpy(ramses.data[ramses.data_index].raw,ramses.recv_buf,Ramses_DATA_SIZE);
                    ramses.data[ramses.data_index].dev_id=((uint16_t)ramses.recv_buf[1]<<8)+ramses.recv_buf[2];
                    ramses.data[ramses.data_index].module_id=ramses.recv_buf[3];
                    ramses.data[ramses.data_index].framebyte=ramses.recv_buf[4];
                    ramses.data[ramses.data_index].data=&ramses.data[ramses.data_index].raw[7];
                    ramses.data[ramses.data_index].data_size=Ramses_DATA_SIZE-8;
                    ramses.data_index++;
                    ramses.recv_buf_p=0;
                    if(ramses.data_index==Ramses_DATA_NUM){
                        ramses.data_index=0;
                        ramses.flag|=Ramses_FLAG_MASK_RECVED_DATA;
                        ramses.flag&=~Ramses_FLAG_MASK_BUSY;
                    }
                }
                else if(ramses.recv_buf[3]==0x20){
                    if((ramses.flag&Ramses_FLAG_MASK_RECVED_IP)!=0){  // 判断为IP帧
                        ramses.data_index=0;
                        ramses.recv_flag_40=0;
                        ramses.recv_buf_p=0;
                        continue;
                    }
                    if(ramses.recv_buf_p!=Ramses_IP_SIZE){
                        ramses.recv_flag_40=0;
                        ramses.recv_buf_p=0;
                        continue;
                    }
                    memcpy(ramses.ip.raw,ramses.recv_buf,Ramses_IP_SIZE);
                    ramses.ip.dev_id=((uint16_t)ramses.recv_buf[1]<<8)+ramses.recv_buf[2];
                    ramses.ip.module_id=ramses.recv_buf[3];
                    ramses.ip.framebyte=ramses.recv_buf[4];
                    ramses.ip.data=&ramses.ip.raw[7];
                    ramses.ip.data_size=Ramses_IP_SIZE-8;
                    ramses.recv_buf_p=0;
                    ramses.flag|=Ramses_FLAG_MASK_RECVED_IP;
                }
                else{
                    ramses.data_index=0;
                    ramses.recv_flag_40=0;
                    ramses.recv_buf_p=0;
                    continue;
                }
            }
        }
    
	}
	// log_i("cb   i %d  j %d",i,j);
	return 0;
}


// int Ramses_CallBack2(Ramses_TypeDef *pRamses, uint8_t *buf, uint16_t size)
// {
//     uint16_t size_tmp;
//     size_tmp =size;
// 	if (size_tmp == 0)  return 0;

// 	if ((size + ramses.size_received) >= sizeof(ramses.result_buf) )
// 	{
// 		size_tmp = sizeof(ramses.result_buf) - ramses.size_received;
// 	}
// 	// TODO: busy -> protect
// 	ramses.flag = 1;
// 	memcpy( (uint32_t)(ramses.result_buf+ramses.size_received), Ramses_uart_helper->rcv_buf, size_tmp );
// 	ramses.size_received += size_tmp;
// 	ramses.flag = 0;

// 	return 0;
// }