/*
                         \\\|///
                       \\  - -  //
                        (  @ @  )
+---------------------oOOo-(_)-oOOo-------------------------+
|   Author   :lo_                                           |
|   Data     :2018.07.10                                    |
|   Version  :V_0.03                                        |
|                                                           |
|   Function :                                              |
|                                                           |
|   History  : 2018.07.11 第一版本 v 0.01                   |
|                2018.07.12 v 0.02,更改串口初始化方法，     |
|               和opcode处理方法                            |
|               2018.07.12 更改串口发送端口                 |
|                             Oooo                          |
+-----------------------oooO--(   )-------------------------+
                       (   )   ) /
                        \ (   (_/
                         \_)     

readme: 使用方法
    1.先调用函数tp_usart_init(串口初始化)，和tp_function_init(串口发送初始化，opcode数据解析初始化)
    2.transparent_msg_recive放到串口中断中接收函数
    3.transprent_time_manage放到计时器中，用来记入时间
    4.transparent_msg_deal放到循环中，用来处理数据
    5.opcode_check_status_report，opcode_netwwork_back_deal，opcode_netwwork_back_deal是解析网络，退网 和强制重启的
    6.cc2530_msg_send 可以用来发送串口信息
*/ 

#include "CC2530_transparent_analyze.h"
#include "hardware_init.h"
#include "Key.h"

/**************************************************************************************************************
此文件内部使用，不允许外部使用，不用更改
***************************************************************************************************************/
static RECIVE_USART_DATA_DEAL static_transparent_msg_info;                               //串口1接受的数据
static RECIVE_USART_BUFF    static_transprent_buff;                                       //透传数据接收的缓存

static TP_bool status_check_flag = TP_false;
static TP_u32  status_check_time = 0x00;
static void send_crc_error(TP_u16 seq_data);

static TP_u8  Usart_recive_write_buff(TP_uc8 *data,TP_uc16 len);
TP_u16 CreateCrc16(TP_uc8* msg, TP_u8 len);

static void (*uart_data_send)(TP_uc8* msg,TP_u32 len);
static void (*non_permeable_opcode_analysis)(PROTOCOL_DEAL protocol_data);
static void (*transparent_opcode_analysis)(PROTOCOL_DEAL protocol_data);

static TP_ErrorStatus transparent_protocol_analysis(TP_uc8 *data,TP_uc8 len);
static u8   Record_Last_Seq = 0xFF;
/**************************************************************************************************************
全局变量，用于 transparent_protocol_send
***************************************************************************************************************/
//查询网络信息
TP_uc8 opcode_check_status_arg = 0x00;
const PROTOCOL_SEND opcode_check_status = {0x00,0x1001,0x10,&opcode_check_status_arg,1};
//设备退网
TP_uc8 opcode_network_back_arg = 0x00;
const PROTOCOL_SEND opcode_network_back = {0x00,0x0001,0x10,&opcode_network_back_arg,1};
//强制重启
TP_uc8 opcode_force_assert_arg = 0X00;
const PROTOCOL_SEND opcode_force_assert = {0x00,0x0002,0x10,&opcode_force_assert_arg,1};
//SEQ
TP_u16 tp_report_seq_num = 0;

#if 1 // add by dingmz_frc.20201215
extern u8 g_u8Temp_Buffer[];
extern u8 g_u8Temp_Length;
#endif

#define EXAMPLE
/**************************************************************************************************************
OPCODE处理  ，非透传数据解析例子
***************************************************************************************************************/
#ifdef EXAMPLE
//void opcode_check_status_report(TP_uc8 *recive_data);
//void opcode_netwwork_back_deal(TP_uc8 *recive_data);
//void opcode_forced_to_restart_deal(TP_uc8 *recive_data);

//void non_permeable_opcode_analysis_EXAMPLE(PROTOCOL_DEAL protocol_data)
//{
//   switch(protocol_data.Opcode)
//    {
//        case _OPCODE_CHECK_STATUS:
//                opcode_check_status_report(protocol_data.ARG);
//            break;
//        case _OPCODE_NETWORK_BACK:
//                opcode_netwwork_back_deal(protocol_data.ARG);
//            break;
//        case _OPCODE_FORCE_TO_RESTART:
//                opcode_forced_to_restart_deal(protocol_data.ARG);
//            break;
//    }
//}

/*******************************************************************************
*函数名称：void opcode_check_status_report(u8 status,u8 net_data)
*
*入口参数：status：是否执行成功表示位
            0：成功   1：失败
            net_data:网络状态
            0：未组网  1：组网中 2：已组网
*
*出口参数：无
*
*功能说明：opcode 0000 查询设备状态返回数据解析
*******************************************************************************/
void opcode_check_status_report(TP_uc8 *recive_data)
{
    if(*(recive_data) == 0x00)              //执行成功
    {
        switch(*(recive_data + 1))
        {
            case no_network:
                //未组网
                break;
            case networking:
                //组网中
                break;
            case in_network:
                //网络中
                break;  
            default:
                //错误
                break;
        }
    }
}
/*******************************************************************************
*函数名称：void opcode_netwwork_back_deal(u8 status)
*
*入口参数：status：是否执行成功表示位
            0：成功   1：失败
*
*出口参数：无
*
*功能说明：opcode 0001 设备退网返回数据解析
*******************************************************************************/

void opcode_netwwork_back_deal(TP_uc8 *recive_data)
{
    if(*(recive_data) == 0x00)
    {
        //退网执行成功
    }
    else 
    {
        //退网执行失败
    }
}
/*******************************************************************************
*函数名称：void opcode_forced_to_restart_deal(u8 status)
*
*入口参数：status：是否执行成功表示位
            0：成功   1：失败
*
*出口参数：无
*
*功能说明：opcode 0002 设备强制重启返回数据解析
*******************************************************************************/

void opcode_forced_to_restart_deal(TP_uc8 *recive_data)
{
    if(*(recive_data) == 0x00)
    {
        //强制重启执行成功
    }
    else 
    {
        //强制重启执行失败
    }
}
#endif


/*******************************************************************************
*函数名称：void tp_usart_init(void (*usart_init)())
*
*入口参数：usart_init 串口初始化的函数
*
*出口参数：无
*
*功能说明：串口的初始化程序
*******************************************************************************/
void tp_usart_init(void (*usart_init)())
{
    usart_init();
}

/*******************************************************************************
*函数名称：u8 tp_function_init
*
*入口参数：send_drive ：串口发送函数
           transparent_function_point：透传解析函数
           non_permeable_function_point：非透传解析函数
*
*出口参数：无
*
*功能说明：串口发送函数
*******************************************************************************/
TP_ErrorStatus tp_function_init(void (*send_drive)(TP_uc8* msg,TP_u32 len),
                        void (*transparent_function_point)(PROTOCOL_DEAL protocol_data),
                        void (*non_permeable_function_point)(PROTOCOL_DEAL protocol_data))
{
    if((send_drive == NULL) || (transparent_function_point == NULL) || (non_permeable_function_point == NULL))
    {
        return TP_ERROR;
    }
    uart_data_send = send_drive;
    transparent_opcode_analysis = transparent_function_point;
    non_permeable_opcode_analysis = non_permeable_function_point;
    return TP_SUCCESS;
}   

/*******************************************************************************
*函数名称：void transparent_msg_recive(TP_uc8 RcvChar)
*
*入口参数：RcvChar：中断中接收到的数据
*
*出口参数：无
*
*功能说明：中断接收函数，使用时只需要把这个放在串口中断中即可
*******************************************************************************/
void transparent_msg_recive(TP_uc8 RcvChar)
{
    //时间位清零，规定时间内接收不到数据，放弃数据
    static_transparent_msg_info.time = 0x00;

    if((RcvChar == SOF_HIGH_BYTE_DEF) && (static_transparent_msg_info.Recive_len == 0x00))     //判断数据头
    {
        static_transparent_msg_info.Data[static_transparent_msg_info.Recive_len ++] = SOF_HIGH_BYTE_DEF;
    }
    else if((RcvChar == SOF_LOW_BYTE_DEF)  &&  (static_transparent_msg_info.Recive_len == 0x01))   //判断数据头
    {
        static_transparent_msg_info.Data[static_transparent_msg_info.Recive_len ++] = SOF_LOW_BYTE_DEF;
    }
    else if(static_transparent_msg_info.Recive_len == 2)
    {
        if((RcvChar < (USART_RECIVE_LEN_DEF - 5)) && (RcvChar > 4))       //长度在正常值之间
        {
            static_transparent_msg_info.Data[static_transparent_msg_info.Recive_len ++] = RcvChar;
            static_transparent_msg_info.Data_len = RcvChar;
        }
        else 
        {
            static_transparent_msg_info.Recive_len = 0x00;                //这串数据不对
        }
    }
    else if((static_transparent_msg_info.Recive_len > 2) && (static_transparent_msg_info.Recive_len < (USART_RECIVE_LEN_DEF - 2))) //接受数据
    {
        static_transparent_msg_info.Data[static_transparent_msg_info.Recive_len ++] = RcvChar;
        
        if(static_transparent_msg_info.Recive_len > (static_transparent_msg_info.Data_len + 4))
        {
            Usart_recive_write_buff((TP_uc8*)static_transparent_msg_info.Data,(TP_uc16)static_transparent_msg_info.Recive_len);
            static_transparent_msg_info.time = 0x00;
            static_transparent_msg_info.Recive_len = 0x00;
        }
    }
    else
    {
        static_transparent_msg_info.Recive_len = 0x00;                //这串数据不对,重新接受
    }
}
/*******************************************************************************
*函数名称：void transparent_time_manage(TP_uc8 timer)
*
*入口参数：timer：定时中断的时间（ms）
*
*出口参数：无
*
*功能说明：需要用的时间管理
*******************************************************************************/
extern void Set_Uart_Detect_Flag(void);
void transparent_time_manage(TP_uc8 timer)
{
    if(static_transparent_msg_info.Recive_len != 0x00)
    {
        static_transparent_msg_info.time += timer;
        
        if(static_transparent_msg_info.time > DEF_TRANSPARENT_MAXIMUM_INTERVAL)
        {
            static_transparent_msg_info.Recive_len = 0x00;
        }
    }
#if(defined DEF_STATUS_CHECK_INTERVAL_TIME != 0x00)
    status_check_time += timer;
    if(status_check_time > DEF_STATUS_CHECK_INTERVAL_TIME)
    {
        status_check_time = 0x00;
        status_check_flag = TP_true;
		Set_Uart_Detect_Flag();
    }
#endif
}
/*******************************************************************************
*函数名称：void transparent_msg_deal(void)
*
*入口参数：无
*
*出口参数：无
*
*功能说明       1.数据取出缓存并且处理
                2.发送设备查询状态
                此函数得一直扫描，不然数据处理数据来不及
*******************************************************************************/
void transparent_msg_deal(void)
{
    TP_u8 i = 0;
    
    i = static_transprent_buff.Buff_send_serial_num;
    
    if(static_transprent_buff.Buff_send_serial_num != static_transprent_buff.Download_serial_num)
    {
        if(static_transprent_buff.Buff_send_serial_num > (USART_RECIVE_DEPTH - 1))
        {
            static_transprent_buff.Buff_send_serial_num = 0;
            
            i = static_transprent_buff.Buff_send_serial_num; //add by YWQ
        }
        
        transparent_protocol_analysis((TP_uc8*)&static_transprent_buff.Usart_buff[i][0],(TP_uc32)static_transprent_buff.Usart_buff_len[i]);
        
        static_transprent_buff.Buff_send_serial_num++;
    }
    
#if(DEF_STATUS_CHECK_INTERVAL_TIME != 0x00)
    if(status_check_flag == TP_true)
    {
        status_check_flag = TP_false;
        transparent_protocol_send(opcode_check_status,tp_report_seq_num++);
    }
#endif
}

/*******************************************************************************
*函数名称：void cc2530_msg_send(SEND_MODE_ENUM send_mode)
*
*入口参数：    send_protocol:包含opcode，arg，len，controlfield
                seq：seq
*
*出口参数：无
*
*功能说明：发送给cc2530 的数据
*******************************************************************************/

void transparent_protocol_send(PROTOCOL_SEND send_protocol,TP_u16 SEQ)
{
    //static  TP_u8 KK_Buf[125] = {0};
	TP_u16 KK_CRC16_Num = 0;  //计算校验值
    
	//memset(KK_Buf,0,sizeof(KK_Buf));
    g_u8Temp_Buffer[0] = 0xAA;
    g_u8Temp_Buffer[1] = 0x55;	
    g_u8Temp_Buffer[2] = send_protocol.ARG_len + 6;      //长度 7
    g_u8Temp_Buffer[4] = (SEQ & 0xff);         //序列号L
    g_u8Temp_Buffer[3] = send_protocol.ControlField;  //控制域:  不需要ack

	g_u8Temp_Buffer[5] = send_protocol.ARG_len+3;
    g_u8Temp_Buffer[6] = send_protocol.Channel_ID;  //下行协议:  信道00
    g_u8Temp_Buffer[7] = ((send_protocol.Opcode >> 8) & 0xff);  //下行协议:  Opcode_H
    g_u8Temp_Buffer[8] = (send_protocol.Opcode & 0xff);  //下行协议:  Opcode_L
    memcpy(&g_u8Temp_Buffer[9],send_protocol.ARG,send_protocol.ARG_len);
		//KK_Buf[9] = 0X00;
    KK_CRC16_Num = CreateCrc16((TP_uc8*)&g_u8Temp_Buffer[3],g_u8Temp_Buffer[2]);
    g_u8Temp_Buffer[send_protocol.ARG_len + 9] = (KK_CRC16_Num>>8) & 0xff;  //校验值 CRC_H
    g_u8Temp_Buffer[send_protocol.ARG_len + 10] = KK_CRC16_Num & 0xff;  //校验值 CRC_L

    uart_data_send(g_u8Temp_Buffer,send_protocol.ARG_len + 11);
}


/*******************************************************************************
*函数名称：void report_device_status(PROTOCOL_DEAL recv_data, TP_uc8* arg, TP_u8 len)
*
*入口参数：    send_protocol:包含opcode，arg，len，controlfield
                seq：seq
*
*出口参数：无
*
*功能说明：系统命令反馈
*******************************************************************************/
void ack_dev_info(PROTOCOL_DEAL recv_data, TP_uc8* arg, TP_u8 len)
{
    PROTOCOL_SEND send_data;  
    
    TP_u16 send_data_SEQ;
    
    send_data.ARG          = arg;
    send_data.ARG_len      = len;
    send_data.Channel_ID   = recv_data.Channel_ID;
    send_data.ControlField = 0x00;
    send_data.Opcode       = recv_data.Opcode;
    
    send_data_SEQ          = recv_data.SEQ;
    
    transparent_protocol_send(send_data, send_data_SEQ);
}



/**************************************************************************************************************
此文件内部使用，不允许外部使用
***************************************************************************************************************/
/*
usatr 接收写缓存
把中断中的数据写到缓存中，然后主函数中处理
*/
static TP_u8  Usart_recive_write_buff(TP_uc8 *data,TP_uc16 len)
{
    TP_u8 rem_serial = 0;
    if(len > USART_RECIVE_LEN_DEF)
    {
        //DEBUG_USATR1("data too long");
        return 0;
    }
    
    rem_serial = static_transprent_buff.Download_serial_num;
    
    if(static_transprent_buff.Download_serial_num > (USART_RECIVE_DEPTH - 1))
    {
        static_transprent_buff.Download_serial_num = 0;
        
        rem_serial = static_transprent_buff.Download_serial_num; //add by YWQ
    }
    
    memcpy(&static_transprent_buff.Usart_buff[rem_serial][0],data,len);
    static_transprent_buff.Usart_buff_len[static_transprent_buff.Download_serial_num] = len;
    static_transprent_buff.Download_serial_num ++;
    
    if(static_transprent_buff.Download_serial_num == static_transprent_buff.Buff_send_serial_num)
    {
        //printf("data deal too slow");
        static_transprent_buff.Download_serial_num = rem_serial;
		static_transprent_buff.Buff_send_serial_num = rem_serial;
        return 0;
    }
    
    return 1;
}

/*******************************************************************************
*函数名称：u8 transparent_protocol_analysis(uc8 *data,u8 len)
*
*入口参数：*data 需要处理的数据
            len  处理数据的长度
*
*出口参数：无
*
*功能说明：数据具体解析，需要添加解析
*******************************************************************************/
//AA 55 07 80 01 04 00 10 11 01 F5 91
//0  1  2  3  4  5  6  7  8  9  10  11
static TP_ErrorStatus transparent_protocol_analysis(TP_uc8 *data, TP_uc8 len)
{	
    PROTOCOL_DEAL    Usart_protocol_deal = {0};
    if((data == NULL) || (len < 5) || (len > USART_RECIVE_LEN_DEF))
	{
		//printf("non valied msg,discard it all\r\n");
		return TP_ERROR;
	}
	
	Usart_protocol_deal.SEQ = *(data + 4);		                             //记录 seq 的值
	
	if(Usart_protocol_deal.SEQ == Record_Last_Seq)
		return TP_ERROR;
	if(BYTE_MOVE(*(data + len -2),*(data + len -1))  != CreateCrc16(data+ 3,len - 5))                //CRC校验
    {                                                                                                //校验不对
        send_crc_error(Usart_protocol_deal.SEQ);
        return TP_ERROR;
	}
    Record_Last_Seq =  Usart_protocol_deal.SEQ; 
	
    Usart_protocol_deal.Opcode = BYTE_MOVE(*(data + 7),*(data + 8));                                  //赋值功能码
    Usart_protocol_deal.Channel_ID = *(data + 6);
    Usart_protocol_deal.ControlField = *(data + 3);
    Usart_protocol_deal.ARG = (data + 9);
    Usart_protocol_deal.ARG_len = (*(data + 2) - 6);    //根据协议，此处应该 data + 2
	
    //DEBUG_USATR1("[cc->stm]RECIVE OPCODE: %16x \r\n",Usart_protocol_deal.Opcode);

    if((Usart_protocol_deal.ControlField & 0x80) == 0x80)//非透传的数据
    {
        non_permeable_opcode_analysis(Usart_protocol_deal);     //非透传数据处理
    }
    else
    {
        transparent_opcode_analysis(Usart_protocol_deal);       //透传数据处理
    }
    
    return TP_SUCCESS;
}	

/*
接收到的数据crc错误回复
*/
static void send_crc_error(TP_u16 seq_data)
{
    TP_u8 send_data[8];
    TP_u16 crc;
    send_data[0] = 0xAA;
    send_data[1] = 0x55;
    send_data[2] = 0x03;
    send_data[3] = 0x22;
    send_data[4] = (seq_data >> 8);
    crc = CreateCrc16(&send_data[3],2);
    send_data[5] = (crc >> 8);
    send_data[6] = (crc & 0xff);
    uart_data_send(send_data,7);
}

/*
接收到的数据crc错误回复
*/
TP_u16 CreateCrc16(u8* msg, TP_u8 len)
{
    TP_u16 crc = 0xFFFF;
    TP_u8 i, j = 0;

    for (i = 0; i < len; i++) 
    {
        for (j = 0; j < 8; j++) 
        {
            //强制转换 ADD BY YWQ
            TP_bool c15 = (TP_bool)((crc >> 15 & 1) == 1);
            TP_bool bit = (TP_bool)((msg[i] >> (7 - j) & 1) == 1);
            
            crc <<= 1;
            
            if (c15 ^ bit) 
            {
                crc ^= 0x1021;
            }
        }
    }
    return crc;
}


