#ifndef __PTZ_UPDATE_H_
#define __PTZ_UPDATE_H_

#include "comm_types.h"




#pragma pack(push,1)

#define HARD_WARE_TYPE_DEFAULT_K (*((u_int8_t *)"G"))
#define HARD_WARE_TYPE_DEFAULT_6 (*((u_int8_t *)"D"))

//程序升级包.hpk的文件头
typedef struct _UpdateFileHead_
{
        u_int32_t flag;                 // 4byte	标志，必须为"HYPK"	如果文件不是以此开头，则认为是非法文件
        u_int32_t head_len;             //4byte	头长度	文件头长度，包含"标志"
        u_int8_t file_type;             //1byte	文件类型，1	1：应用程序升级包 2:bootloader
        u_int16_t file_format_ver;      //2byte 文件格式版本号，1	用于确定文件的处理方式
        u_int8_t hardware_type[2];      //2byte	硬件类型	升级包适用的硬件类型
        u_int16_t hardware_ver;         //2byte	硬件版本	升级包适用的硬件版本
        u_int32_t software_ver;         //4byte	软件版本	本升级包的应用软件版本
        u_int32_t data_len;             //4byte 数据长度
        u_int32_t addr;                 //4byte 烧写地址
        u_int8_t head_checksum;         //1byte	头校验	以上内容的checksum，包括"标志"，单字节异或
}UpdateFileHead;

#define UPDATE_BUFF_SIZE      750 //接收数据包大小
#define UPDATE_BUFF_FIFO_NUM  2    //循环缓冲区存储的数据包个数

//升级文件类型
#define UPDATE_FILE_TYPE_APP         1 //升级文件类型是application，应用程序
#define UPDATE_FILE_TYPE_BOOT_LOADER 2 //升级文件类型是bootloader
#define UPDATE_FILE_TYPE_CERT        3 //加密芯片证书
#define UPDATE_FILE_TYPE_PUB_KEY     4 //公钥
#define UPDATE_FILE_TYPE_CFG_FILE    5 //配置文件
#define UPDATE_FILE_TYPE_CFG_IP      6 //IP配置文件
#define UPDATE_FILE_TYPE_NW_INFO     7 //南网台帐信息  

//升级协议帧类型
#define UPDATE_FRAME_TYPE_SEND 0X20 //云台发送升级数据
#define UPDATE_FRAME_TYPE_RECE 0X21 //云台接收升级数据

#define UPDATE_FRAME_TYPE_KEEP_ALIVE         0X01 //用以保持连接
#define UPDATE_FRAME_TYPE_GET_DEVICE_INFO    0X02 //用于获取设备信息，包括软硬件版本等
#define UPDATE_FRAME_TYPE_RESET_DEVICE       0X03 //设备复位
#define UPDATE_FRAME_TYPE_BOOT_APP           0X04 //要求设备载入应用
#define UPDATE_FRAME_TYPE_UPGRADE_REQ        0X05 //升级设备请求，数据内容是一个upgrade_request结构
#define UPDATE_FRAME_TYPE_UPGRADE_DATE       0X06 //升级设备数据，数据内容是一个upgrade_frame结构
#define UPDATE_FRAME_TYPE_UPGRADE_FINISH     0X07 //升级设备结束，SRV->Device数据内容空
                                             //Device->Srv数据内容是补报请求upgrade_retrans_table
#define UPDATE_FRAME_TYPE_ERROR              0XF0 //出错信息
#define UPDATE_FRAME_TYPE_VER_INFO           0XF1 //版本信息


#define UPDATE_FRAME_HEAD_FLAG               0X5AA5//帧头

#define DEVICE_ID_LEN                        17    //设备ID长度

#define PTZ_UPDATE_PORT                      9999  //云台升级端口

#define PTZ_UPDATE_SERV_IP_A                 "192.168.8.222"  //升级服务端IP地址
#define PTZ_UPDATE_SERV_IP_B                 "192.168.8.168"
#define PTZ_UPDATE_SERV_PORT_A               8880  //升级服务端端口
#define PTZ_UPDATE_SERV_PORT_B               8881  //升级服务端端口

#define BITS_PER_UNIT                        8     //一个字节的bit数                    

#define MAX_RETRANS_TABLE_LEN                256   //补包表大小

//提取每一帧的CRC16校验码
#define UPDATE_FRAME_GET_CRC16(x) (*(u_int16_t *)(&((x)->data[(x)->data_len])))
//计算帧头长度
#define UPDATE_FRAME_HEAD_SIZE(x) (((char *)((x)->data)) - (char *)(x))
//计算帧的总长度
#define UPDATE_FRAME_SIZE(x) (((char *)&((x)->data[(x)->data_len])) - (char *)(x) + sizeof(u_int16_t))
///计算升级文件总长度
#define UPDATE_FILE_TOTAL_LEN(x) ((x)->data_len + sizeof(*(x)) + sizeof(u_int16_t))
///计算补包表大小
#define UPDATE_RETRANS_TABLE_SIZE(x) (((x)->count * sizeof((x)->index[0])) +sizeof((x)->count))

#define ON_CHIP_FLASH_SECTOR_SIZE          2048

#define UPDATE_ON_CHIP_FLASH_SECTOR_SIZE   2048
#define UPDATE_EXT_FLASH_SECTOR_SIZE       (1024*4)
#define UPDATE_EXT_FLASH_BLOCK_NUM         (0)
#define UPDATE_EXT_FLASH_BLOCK_NUM16       (16)


//升级包在片外flash缓存时使用的地址信息
#define UPDATE_FLASH_BUFF_BEGIN_ADDR   (1024*64*24)//1.5M-2M      
#define UPDATE_FLASH_BUFF_END_ADDR     (1024*64*32-1)
#define UPDATE_FLASH_BUFF_SIZE         (1024*64*8)//512k
#define UPDATE_FLASH_BUFF_BEGIN_BLOCK  (UPDATE_FLASH_BUFF_BEGIN_ADDR / Flash_BLOCKBYTE_LENGTH)

//bootloader地址信息--片内
#define UPDATE_BOOTLOADER_ADDR_BEGIN   (0x08000000)//Bootloader起始地址
#define UPDATE_BOOTLOADER_ADDR_END     (0x0800BFFF)//bootloader结束地址，共64KB，占4个扇区0，1，2，3
#define UPDATE_BOOTLOADER_SECTOR_BEGIN CTL_SECTOR_NUMBER_0 //Bootloader起始sector

//应用程序地址信息--片内
#define UPDATE_APP_ADDR_BEGIN   (0x08010000)//应用程序起始地址
#define UPDATE_APP_ADDR_END     (0x0807FFFF)//应用程序结束地址，共448kB，占4个扇区4，5，6，7
#define UPDATE_APP_SECTOR_BEGIN  CTL_SECTOR_NUMBER_4 //应用程序起始sector

#define APP_ADD_BEGIN_OFFEST      (0x08000000)

//安全证书地址信息--放在w25q128中
#define UPDATE_CERT_ADDR_BEGIN   (1024*4*2)//0block 2sector(4k) 包头放在1sector
#define UPDATE_CERT_ADDR_END     (1024*4*3-1)
#define UPDATE_CERT_SECTOR_BEGIN (UPDATE_CERT_ADDR_BEGIN / UPDATE_EXT_FLASH_SECTOR_SIZE)//安全加密芯片证书

//密钥地址信息--放在w25q128中
#define UPDATE_KEY_ADDR_BEGIN   (1024*4*4)//0block 4sector(4k) 包头放在3sector
#define UPDATE_KEY_ADDR_END     (1024*4*5-1)
#define UPDATE_KEY_SECTOR_BEGIN (UPDATE_KEY_ADDR_BEGIN / UPDATE_EXT_FLASH_SECTOR_SIZE)//安全加密芯片密钥

//配置文件地址信息--放在w25q128中
#define UPDATE_CFG_FILE_ADDR_BEGIN   (1024*4*6)//0block 6sector(4k) 包头放在5sector
#define UPDATE_CFG_FILE_ADDR_END     (1024*4*7-1)
#define UPDATE_CFG_FILE_SECTOR_BEGIN (UPDATE_CFG_FILE_ADDR_BEGIN / UPDATE_EXT_FLASH_SECTOR_SIZE)//配置文件

//IP配置文件地址信息--放在w25q128中
#define UPDATE_CFG_IP_ADDR_BEGIN   (1024*64*16+1024*4*1)//16block 1sector(4k) 包头放在 block16 0sector
#define UPDATE_CFG_IP_ADDR_END     (1024*64*16+1024*4*2-1)
#define UPDATE_CFG_IP_SECTOR_BEGIN ((UPDATE_CFG_IP_ADDR_BEGIN - Flash_BLOCKBYTE_LENGTH*16)/ UPDATE_EXT_FLASH_SECTOR_SIZE)//配置文件

//南网台帐信息文件地址信息--放在w25q128中
#define UPDATE_CFG_NW_INFO_ADDR_BEGIN    (1024*64*16+1024*4*3)//16block 2sector(8k) 包头放在 block16 3sector 4sector
#define UPDATE_CFG_NW_INFO_ADDR_END      (1024*64*16+1024*4*5-1)
#define UPDATE_CFG_NW_INFO_SECTOR_BEGIN  ((UPDATE_CFG_NW_INFO_ADDR_BEGIN - Flash_BLOCKBYTE_LENGTH*16)/ UPDATE_EXT_FLASH_SECTOR_SIZE)//配置文件



////应用程序包头存储地址信息，在应用程序前4K保存--片内
//#define APP_PKG_HEAD_BEGIN         0x0800C000//(APP_ADDR_BEGIN - 4096)
//#define APP_PKG_HEAD_END           0x0800FFFF//(APP_ADDR_BEGIN-1)
//#define APP_PKG_HEAD_SECTOR_BEGIN   CTL_SECTOR_NUMBER_3//3  //头存储的sector(APP_PKG_HEAD_BEGIN/ON_CHIP_FLASH_SECTOR_SIZE)
//#define APP_PGK_HEAD               ((hy_release_file_head*)APP_PKG_HEAD_BEGIN)

//应用程序包头存储地址信息，在应用程序前2个sector保存--片内
#define UPDATE_APP_PKG_HEAD_BEGIN          0x0800C000
#define UPDATE_APP_PKG_HEAD_END            0x0800FFFF
#define UPDATE_APP_PKG_HEAD_SECTOR_BEGIN   CTL_SECTOR_NUMBER_3//头存储的sector
#define UPDATE_APP_PKG_HEAD                ((UpdateFileHead*)UPDATE_APP_PKG_HEAD_BEGIN)

//安全证书包头存储地址信息，在芯片安全证书前1个sector保存--放在w25q128中
#define UPDATE_CERT_HEAD_BEGIN          (UPDATE_CERT_ADDR_BEGIN - UPDATE_EXT_FLASH_SECTOR_SIZE)
#define UPDATE_CERT_HEAD_END            (UPDATE_CERT_ADDR_BEGIN-1)
#define UPDATE_CERT_HEAD_SECTOR_BEGIN   (UPDATE_CERT_HEAD_BEGIN/UPDATE_EXT_FLASH_SECTOR_SIZE)//头存储的sector

//密钥包头存储地址信息，在密钥前1个sector保存--放在w25q128中
#define UPDATE_KEY_HEAD_BEGIN          (UPDATE_KEY_ADDR_BEGIN - UPDATE_EXT_FLASH_SECTOR_SIZE)
#define UPDATE_KEY_HEAD_END            (UPDATE_KEY_ADDR_BEGIN-1)
#define UPDATE_KEY_HEAD_SECTOR_BEGIN   (UPDATE_KEY_HEAD_BEGIN/UPDATE_EXT_FLASH_SECTOR_SIZE)//头存储的sector

//配置文件包头存储地址信息，在配置文件前1个sector保存--放在w25q128中
#define UPDATE_CFG_FILE_HEAD_BEGIN          (UPDATE_CFG_FILE_ADDR_BEGIN - UPDATE_EXT_FLASH_SECTOR_SIZE)
#define UPDATE_CFG_FILE_HEAD_END            (UPDATE_CFG_FILE_ADDR_BEGIN-1)
#define UPDATE_CFG_FILE_HEAD_SECTOR_BEGIN   (UPDATE_CFG_FILE_HEAD_BEGIN/UPDATE_EXT_FLASH_SECTOR_SIZE)//头存储的sector

//IP配置文件包头存储地址信息，在配置文件前1个sector保存--放在w25q128中
#define UPDATE_CFG_IP_HEAD_BEGIN          (UPDATE_CFG_IP_ADDR_BEGIN - UPDATE_EXT_FLASH_SECTOR_SIZE)
#define UPDATE_CFG_IP_HEAD_END            (UPDATE_CFG_IP_ADDR_BEGIN-1)
#define UPDATE_CFG_IP_HEAD_SECTOR_BEGIN   ((UPDATE_CFG_IP_HEAD_BEGIN - Flash_BLOCKBYTE_LENGTH*16)/UPDATE_EXT_FLASH_SECTOR_SIZE)//头存储的sector

//南网信息文件包头存储地址信息，在配置文件前1个sector保存--放在w25q128中
#define UPDATE_CFG_NW_INFO_HEAD_BEGIN          (UPDATE_CFG_NW_INFO_ADDR_BEGIN - UPDATE_EXT_FLASH_SECTOR_SIZE)
#define UPDATE_CFG_NW_INFO_HEAD_END            (UPDATE_CFG_NW_INFO_ADDR_BEGIN-1)
#define UPDATE_CFG_NW_INFO_HEAD_SECTOR_BEGIN   ((UPDATE_CFG_NW_INFO_HEAD_BEGIN - Flash_BLOCKBYTE_LENGTH*16)/UPDATE_EXT_FLASH_SECTOR_SIZE)//头存储的sector


#define UPDATE_RELEASE_FILE_FLAG (*((u_int32_t *)"HYPK"))

//升级程序进行的状态
#define UPDATE_STATE_DEAD 0 //初始状态，尚未连接到升级端
#define UPDATE_STATE_IDEL 1 //空闲状态，系统平时的状态
#define UPDATE_STATE_UPGRADE_DATA_TRANS 2 //等待维护程序发送升级数据状态


#define flash_buff_crc16(len) (_flash_buff_crc16(UPDATE_FLASH_BUFF_BEGIN_ADDR, len));


///升级数据包循环缓冲区结构体
typedef struct _UpdateRecvFifoBuff_
{
   unsigned short int data_len;//数据长度
   unsigned char data_buff[UPDATE_BUFF_SIZE];//保存数据包
}UpdateRecvFifoBuff;

///升级帧结构体
typedef struct _UpdateFrame_
{
        unsigned short int flag;         // 2byte 帧起始标志，必须为5AA5
        unsigned short int data_len;     // 2byte 报文数据长度
        unsigned char id[DEVICE_ID_LEN];     //设备ID
        unsigned char frame_type;            //帧类型,是接收数据还是发送数据
        unsigned char pack_type;             //报文类型，该帧的功能，表示该帧具体指那一方面的内容
        unsigned char data[2];
}UpdateFrame;

///升级请求，包含文件头，供设备分析准备；但是在其后的数据文件发送中，文件头会与内容一起被再次发送
typedef struct _UpdateRequest_ 
{
        u_int32_t total_len;  //升级包总长度
        u_int16_t frame_len;  //升级包发送每次最大长度
        u_int16_t frame_count; //升级包发送分片个数
        UpdateFileHead file_head; //文件头，包含升级程序的描述信息
}UpdateRequest;

//补包请求，device->servr，如果 count == 0，表示不需要补包，升级成功
typedef struct _UpdateRetransTable_
{
        u_int16_t count;    //补包个数
        u_int16_t index[1]; //序号表
}UpdateRetransTable;

//升级文件数据，完整的升级文件数据分片发送
typedef struct _UpdateData_
{
        u_int16_t index;    //桢序号
        u_int16_t data_len; //本帧数据长度，写入偏移量为
        u_int8_t  data[1];  //数据
}UpdateData;


RAM_FUNC void OnChip_Flash_init(void);
RAM_FUNC u_int8_t OnChip_Flash_erase_sector(u_int16_t sectorNo);
RAM_FUNC u_int8_t OnChip_Flash_write_in_sector(u_int16_t sectNo,u_int16_t offset,u_int16_t cnt,u_int8_t buf[]);
RAM_FUNC u_int8_t OnChip_Flash_write(u_int32_t addr,u_int16_t cnt, u_int8_t buf[]);
RAM_FUNC u_int32_t OnChip_Flash_cmd_launch(void);
RAM_FUNC u_int8_t OnChip_Flash_read_in_sector(u_int16_t sectNo,u_int16_t offset,u_int16_t cnt,u_int8_t*bBuf);





#pragma pack(pop)

void init_update_module();

#endif
