#include "update_protocol.h"
#include "string.h"

static struct
{
    update_send_t   pfnSend;
  update_callback_t EventCb;
}g_update_protoc;

uint16_t CRC_Modbus(uint16_t wBase, uint8_t* para, uint16_t length)
{
    uint16_t crc = 0xffff;

    uint16_t index, i;

    for (index = 0 ; index < length; index++)
    {
        crc ^= para[index];

        for (i = 0; i < 8; i++)
        {
            if (crc & 1)
            {
                crc >>= 1;
                crc ^= wBase;
            }
            else
                crc >>= 1;
        }
    }

    return crc;
}

void update_send_cmd(uint8_t Cmd, uint16_t Indx, int PageNum)
{
    uint8_t sData[24]={0};
    uint8_t sLen =0;
    uint16_t crc16;

    update_protocol_hd_t *Frame = (update_protocol_hd_t*)sData;

    Frame->Header = 0x7a;
    Frame->SlvAddr = 0x01;
    Frame->Cmd = Cmd;

    if (Cmd == 0x01)
    {
        Frame->PayloadLen = 1;
        sData[sizeof(update_protocol_hd_t)] = Indx;
    }
    else if (Cmd == 0x02)
    {
        Frame->PayloadLen = 4;
        update_protocol_get_t *GDData = (update_protocol_get_t*)&sData[sizeof(update_protocol_hd_t)];
        GDData->PackageIndex = Indx;
        GDData->PackageNum   = PageNum;
    }

    sLen = sizeof(update_protocol_hd_t) + Frame->PayloadLen;
    crc16 = CRC_Modbus(CRC16_BASE, sData, sLen);
    sData[sLen++] = crc16;
    sData[sLen++] = (crc16 >> 8) & 0x00ff;

    g_update_protoc.pfnSend(sData, sLen);
}

void update_init(update_send_t pCbs)
{
  g_update_protoc.pfnSend =pCbs;
}

void update_event_cbs_reg(update_callback_t pCbs)
{

  g_update_protoc.EventCb = pCbs;
    
}

uint8_t update_unpack(uint8_t* rxData, int rLen,uint8_t *cmd,  void *pload, int *pLen){

    uint16_t crc16;
    
    uint16_t    check;

    check = CRC_Modbus(CRC16_BASE, rxData, rLen - 2);
    
    crc16 = (rxData[rLen - 1] << 8) | rxData[rLen - 2];

    if (check != crc16 || rxData[0] !=0x7a || pload ==0)
    {
        return 0;
    }

    update_protocol_hd_t *Frame = (update_protocol_hd_t*)rxData;

    *cmd = Frame->Cmd;
    
    if (Frame->Cmd == 0x81){
        
        //update_protocol_req_t *UpData = (update_protocol_req_t*)&rxData[sizeof(update_protocol_hd_t)];
 
        pload =  0;
        
        *pLen = 0;
        
        
    }else if (Frame->Cmd == 0x82){

        update_protocol_rsp_t *DownData = (update_protocol_rsp_t *)&rxData[sizeof(update_protocol_hd_t)];
        
        memcpy(pload , &rxData[sizeof(update_protocol_hd_t) + sizeof(update_protocol_rsp_t)],DownData->DataLen);

        *pLen = DownData->DataLen;
 
    }else{
        
        return 0;
    }
       
    return 1;
}
