
#include "soft_tattu.h"
#include "string.h"
#include "soft_flash.h"
#include "soft_okcell.h"

#define TATTU_MAXLEN 200


//_TATTU_INFO ttu_inf = {0};

/*
Field             Bits   Description
Start of transfer 1      See below
End of transfer   1      See below
Toggle bit        1      See below
Transfer ID       5      The transfer ID value

注意:数据为小端
*/


/*
Field                Bits   Allowed       values Description
Priority             5      0-31          默认填最高优先级:0
Message type ID      16     0x1092        查询模式
Service or message   1      0             0x1092----此位为 0；
Source node ID       7      1…127        0 是保留的，代表一个未知的节点;自身的节点 Id;
Destination Node Id  7      1…127        0 是保留的，代表一个未知的节点;对方的节点 Id。
Request not response 1      0 or 1        1 表示该帧是 Request 请求帧；0 表示该帧是 Response 应答帧；

注意:数据为小端
*/
#pragma pack(1)
typedef struct 
{
    unsigned char  canid_prio    :5;
    unsigned short canid_msgid   :16;
    unsigned char canid_som      :1;
    unsigned char canid_srcid    :7;
    /*unsigned char canid_desid:7;
    unsigned char canid_rnr:1;*/
}_TATTU_CANID;
#pragma pack()

_TATTU_DEVICE tattu_device1 = {.Tattu_Link.connect_status = COMP_NOEXIST}, 
               tattu_device2 = {.Tattu_Link.connect_status = COMP_NOEXIST};

void TattuCanRecvHookFunction(uint32_t ttuCanID, uint8_t data[], uint8_t len)
{
    //获取数据中的最后一位
    _TATTU_DEVICE *taptr = NULL;
    uint8_t can_msgid = 0;
    can_msgid = ttuCanID & 0x7f;

    if(can_msgid == 0x16)
    {
        taptr = &tattu_device1;
    }
    else
    {
        taptr = &tattu_device2;
    }

    memcpy(&taptr->ttu_tailbyte, &data[len - 1], sizeof(uint8_t));

    //找到开头
    if(taptr->ttu_tailbyte.tail_start == 1){
        taptr->Tattu_recv_index = 0;
        taptr->Tattu_get_s = true;
    }
    
    //溢出检测
    if(taptr->Tattu_recv_index + len > TATTU_MAXLEN)
    {
        memset(taptr->Tattu_recv_buf,0,taptr->Tattu_recv_index);
        taptr->Tattu_recv_index = 0;
        taptr->Tattu_get_s = false;
    }
    
    //获取到正确的开始位则接收数据
    if(taptr->Tattu_get_s == true){
        //复制有效数据,最后一个字节不是有效数据
        memcpy(&taptr->Tattu_recv_buf[taptr->Tattu_recv_index], data, len-1);
        taptr->Tattu_recv_index += (len-1);
    }

    
    //找到结尾，开始解析
    if(taptr->Tattu_get_s == true && taptr->ttu_tailbyte.tail_end == 1)
    {
        taptr->Tattu_get_s = false;
        
        taptr->Tattu_Link.connect_status = COMP_NORMAL;
        //更新电池数据到来时间
        taptr->Tattu_Link.recv_time = HAL_GetTick();
            
        //如果是单帧完整数据
        if(taptr->ttu_tailbyte.tail_start == 1 || taptr->Tattu_recv_index <= 7)
        {
            //单帧数据不需要校验
        }
        //多帧拼包
        else
        {
            //CRC校验，验证通过，暂不开启
            CCITT_CRC16Init(&taptr->Tattu_recv_buf[2],taptr->Tattu_recv_index-2);
            if(CCITT_CRC16 == (taptr->Tattu_recv_buf[0] + (taptr->Tattu_recv_buf[1]<<8)))
            {
                //避免电池单方面增加协议造成溢出,格式电池12s跟14s兼容有问题，飞控自己做处理
                //后两个字节是自己添加的用来识别电池串数
                if(taptr->Tattu_recv_index-2 <= (sizeof(_TATTU_INFO)-2))
                {
                    //stm32为小段模式，TATTU发送过来的数据为小端模式，可直接使用memcpy
                    //12S
                    if(taptr->Tattu_recv_index-2 == (sizeof(_TATTU_INFO)-2-4-16))
                    {
                        taptr->ttu_inf.tattu_cnum = 12;
                        //前12s信息
                        memcpy(&taptr->ttu_inf,&taptr->Tattu_recv_buf[2],40);
                        //后边信息
                        memcpy(&taptr->ttu_inf.tattu_descapa,&taptr->Tattu_recv_buf[40+2],8);
                        
                    }
                    //添加序列号后的12s
                    else if(taptr->Tattu_recv_index-2 == (sizeof(_TATTU_INFO)-2-4))
                    {
                        taptr->ttu_inf.tattu_cnum = 12;
                        //前12s信息
                        memcpy(&taptr->ttu_inf,&taptr->Tattu_recv_buf[2],40);
                        //后边信息
                        memcpy(&taptr->ttu_inf.tattu_descapa,&taptr->Tattu_recv_buf[40+2],24);
                    }
                    //14s
                    else if(taptr->Tattu_recv_index-2 == (sizeof(_TATTU_INFO)-2-16) || taptr->Tattu_recv_index-2 == (sizeof(_TATTU_INFO)-2))
                    {
                        taptr->ttu_inf.tattu_cnum = 14;
                        
                        //14s信息
                        memcpy(&taptr->ttu_inf,&taptr->Tattu_recv_buf[2],taptr->Tattu_recv_index-2);
                    }
                    
                }else{
                    //清空电池信息数据
                    memset(&taptr->ttu_inf, 0, sizeof(_TATTU_INFO));
                }
            }
        }
        //清理buff
        memset(taptr->Tattu_recv_buf,0,taptr->Tattu_recv_index);
        
        //包数完整重新计数
        taptr->Tattu_recv_index = 0;
    }
}

/*
格氏电池的CRC校验
*/
#define CRC_CCITT_INIT 0xFFFF
#define CRC_CCITT_POLY 0x1021U

uint16_t CCITT_CRC16 = 0;

void CCITT_CRC16Init(uint8_t const *bytes, uint16_t len)
{
    CCITT_CRC16 = CRC_CCITT_INIT;
    CCITT_CRC_ARRAY(bytes, len);
}


void CCITT_CRCStep(uint8_t byte)
{
    uint32_t j;
    CCITT_CRC16 ^= ((uint16_t)byte << 8);
    for (j = 0; j < 8; j++)
    {
        CCITT_CRC16=(CCITT_CRC16 & 0x8000U)?((CCITT_CRC16 << 1) ^ CRC_CCITT_POLY):(CCITT_CRC16 << 1);
    }
}


void CCITT_CRC_ARRAY(uint8_t const * bytes, uint16_t len)
{
    while (len--)   CCITT_CRCStep(*bytes++);
} 
 
 




