#include "drv_rtc.h"

#include "bsp_fdb.h"


#include "db_config.h"
#include "comm_manager.h"
#include "eeprom_manager.h"

#include "kit_data.h"
#include <os_cfg.h>

typedef struct
{
    bool     is_circuit_on;
    uint16_t power_off_tick;
    uint32_t task_timeout_time[OS_MAX_TASKS];
    uint8_t  hardfault_buf[64];
}UninitData;
UninitData uninit_data __attribute__((section (".UNINIT_RAM"),zero_init));
FDB_STATIC_INIT(fdb_item, kFdbData_End, (128 * 1024), 0x08060000, 0x080C0000);

/************************************************modbus cfg*****************************************************/
typedef struct
{
    uint16_t task_num;
    ModbusHead *head;
}ModelItem;

ModelItem model_item[kModbusIdx_End + 1];

void bms_analyse_model_data(void)
{
    uint32_t i, len, num, addr = 0;
    uint8_t  *model_buf = (uint8_t *)bsp_fdb_get_data_addr(&fdb_item, kFdbData_ModbusCfg);

    if(model_buf != NULL)
    {
        len = READ_LT_INT16U(model_buf, addr);
        if(kit_check_crc16(model_buf, len) == 0)
        {
            for(i = 0; i < kModbusIdx_End + 1; i++)
            {
                num = READ_LT_INT16U(model_buf, addr);
                if((num != 0) 
                && (num != 0xFFFF))
                {
                    model_item[i].head = (ModbusHead *)&model_buf[addr];
                }
                else
                {
                    num = 0;
                }
                model_item[i].task_num = num;
                addr += num * 8;
            }
        }
    }
}

uint16_t bms_read_modbus_model(uint8_t *buf)
{
    uint16_t len = 0;
    uint32_t addr = 0;
    uint8_t  *model_buf = (uint8_t *)bsp_fdb_get_data_addr(&fdb_item, kFdbData_ModbusCfg);

    if(model_buf != NULL)
    {
        len = READ_LT_INT16U(model_buf, addr);
        if((len != 0xFFFF) && (kit_check_crc16(model_buf, len) == 0))
        {
            kit_copy_buf(buf, model_buf, len);
        }
        else
        {
            len = 0;
        }
    }

    return len;
}

bool bms_write_modbus_model(uint8_t *buf, uint16_t len)
{
    bool res = true;
    uint8_t  *model_buf = (uint8_t *)bsp_fdb_get_data_addr(&fdb_item, kFdbData_ModbusCfg);
    uint16_t cur_len = (model_buf != NULL) ? READ_LT_INT16U_BY_CONST_POS(model_buf, 0) : 0;
    
    if((cur_len != len) || (kit_is_buf_same(model_buf, buf, len) != true))
    {
        res = bsp_fdb_write_data(&fdb_item, kFdbData_ModbusCfg, buf, len);
    }
    
    return res;
}

uint16_t bms_get_modbus_model_task_num(uint8_t mb_idx)
{
    uint16_t num = 0;
    
    if(mb_idx < kModbusIdx_End + 1)
    {
        num = model_item[mb_idx].task_num;
    }
    
    return num;
}

ModbusHead *bms_get_modbus_model_head_addr(uint8_t mb_idx, uint16_t task_idx)
{
    ModbusHead *head = NULL;
    
    if(mb_idx < kModbusIdx_End)
    {
        head = &model_item[mb_idx].head[task_idx];
    }
    
    return head;
}


/************************************************HardFault*****************************************************/
bool bms_write_hardfault_data(uint8_t *buf, uint16_t len)
{
    bool res = true;
    if((buf != NULL) && (len == 64))
    {
        bms_soft_reset_save(kSoftReset_HardFault, buf, len);
        kit_copy_buf(uninit_data.hardfault_buf, buf, len);
        if(bsp_fdb_get_data_addr(&fdb_item, kFdbData_TaskTimeout) == NULL)
        {
            res = bsp_fdb_write_data(&fdb_item, kFdbData_HardFault, buf, len);
        }
    }
    return res;
}

uint16_t bms_read_hardfault_data(uint8_t *buf, uint16_t len)
{
    uint16_t res = true;
    if(buf != NULL)
    {
        res = bsp_fdb_read_data(&fdb_item, kFdbData_HardFault, buf);
    }
    return res;
}

/************************************************Task Timeout*****************************************************/

void bms_write_task_timeout_data(uint32_t task_id)
{
    if(task_id < OS_MAX_TASKS)
    {
        uninit_data.task_timeout_time[task_id] = drv_rtc_get_tick();
        if(bsp_fdb_get_data_addr(&fdb_item, kFdbData_TaskTimeout) == NULL)
        {
            bsp_fdb_write_data(&fdb_item, kFdbData_TaskTimeout, (uint8_t *)uninit_data.task_timeout_time, OS_MAX_TASKS * 4);
        }
    }
}

uint16_t bms_read_task_timeout_data(uint8_t *buf, uint16_t len)
{
    uint16_t res = true;
    if(buf != NULL)
    {
        res = bsp_fdb_read_data(&fdb_item, kFdbData_TaskTimeout, buf);
    }
    return res;
}

#include "bsp_queue.h"
#include "eeprom_manager.h"
extern EEpromItem eeprom_item;
#define BCU_MODBUS_CFG_CNT      (27U)//(25u)--Ôö¼ÓT2¸ßµÍÎÂ
#define BCU_MODBUS_CFG_LEN      (500 * 2)
#define BCU_MODBUS_CFG_START_ADDR 58
//QUEUE_STATIC_INIT_CCM(modbus_cfg, 22 * 3, 4);

QUEUE_STATIC_INIT(modbus_cfg, BCU_MODBUS_CFG_CNT * 6, 4);

uint32_t hmi_fill_modbus_cfg(uint8_t *buf)
{
    uint32_t i, tmp, cnt, addr = 0;
    //for(i = 0; i < BCU_MODBUS_CFG_CNT * 3; i++) -jason
    for(i = 0; i < 77; i++)
    {
        if(i < 75)
        {
            cnt = i * 5;
            WRITE_BT_INT16U(buf, addr, eeprom_item.data_buf[kEep_DisLTVoltHTAlarm1 + cnt]);
		    WRITE_BT_INT16U(buf, addr, eeprom_item.data_buf[kEep_DisLTVoltHTAlarm1 + cnt + 1]);
            WRITE_BT_INT16U(buf, addr, eeprom_item.data_buf[kEep_DisLTVoltHTAlarm1 + cnt + 2]);
		    WRITE_BT_INT16U(buf, addr, eeprom_item.data_buf[kEep_DisLTVoltHTAlarm1 + cnt + 3]);
            tmp = (eeprom_item.data_buf[kEep_DisLTVoltHTAlarm1 + cnt + 4] >> 8) & 0x00FF;
		    WRITE_BT_INT16U(buf, addr, tmp);
		
            tmp = eeprom_item.data_buf[kEep_DisLTVoltHTAlarm1 + cnt + 4] & 0x00FF;
            WRITE_BT_INT16U(buf, addr, tmp);
        }
        else
        {
            cnt = i * 5 - 75 * 5;
            WRITE_BT_INT16U(buf, addr, eeprom_item.data_buf[kEep_HT2TempAlarm1Alarm1 + cnt]);
		    WRITE_BT_INT16U(buf, addr, eeprom_item.data_buf[kEep_HT2TempAlarm1Alarm1 + cnt + 1]);
            WRITE_BT_INT16U(buf, addr, eeprom_item.data_buf[kEep_HT2TempAlarm1Alarm1 + cnt + 2]);
		    WRITE_BT_INT16U(buf, addr, eeprom_item.data_buf[kEep_HT2TempAlarm1Alarm1 + cnt + 3]);
            tmp = (eeprom_item.data_buf[kEep_HT2TempAlarm1Alarm1 + cnt + 4] >> 8) & 0x00FF;
		    WRITE_BT_INT16U(buf, addr, tmp);
		
            tmp = eeprom_item.data_buf[kEep_HT2TempAlarm1Alarm1 + cnt + 4] & 0x00FF;
            WRITE_BT_INT16U(buf, addr, tmp);            
        }

    }
    kit_set_buf(&buf[addr], BCU_MODBUS_CFG_LEN - addr, 0);
    
    return BCU_MODBUS_CFG_LEN;
}

uint16_t hmi_write_modbus_cfg(uint16_t offset_addr, uint16_t data)
{
    uint16_t tmp, cfg_idx,offset_new=0;
        
    //if(offset_addr < BCU_MODBUS_CFG_CNT * 3 * 6)
    if(offset_addr < 450)
    {
		/*
        tmp = offset_addr % 3;
        cfg_idx = (offset_addr / 3) * 5 + (tmp << 1) + BCU_MODBUS_CFG_START_ADDR;        
        tmp = (tmp == 2) ? kEepromDataType_Low : kEepromDataType_Full;
    
        tmp = bsp_eeprom_save_data(cfg_idx, data, (EepromDataType)tmp);
		*/
		
        tmp = offset_addr % 6;
		if(tmp < 4)
		{
			cfg_idx = (offset_addr / 6) * 5 + tmp + BCU_MODBUS_CFG_START_ADDR;        
			tmp = bsp_eeprom_save_data(cfg_idx, data, kEepromDataType_Full);
		}
		else if(tmp == 4)
		{
			cfg_idx = (offset_addr / 6) * 5 + 4 + BCU_MODBUS_CFG_START_ADDR;        
			tmp = bsp_eeprom_save_data(cfg_idx, data, kEepromDataType_High);
		}
		else if(tmp == 5)
		{
			cfg_idx = (offset_addr / 6) * 5 + 4 + BCU_MODBUS_CFG_START_ADDR;        
			tmp = bsp_eeprom_save_data(cfg_idx, data, kEepromDataType_Low);
		}
    }
    else
    {
        //tmp = data + 1;
        
        if(offset_addr < 462) //T2¸ßµÍÎÂ
        {
            tmp = offset_addr % 6;
            offset_new = offset_addr - 450;
            if(tmp < 4)
		    {
			    cfg_idx = (offset_new / 6) * 5 + tmp + kEep_HT2TempAlarm1Alarm1;        
			    tmp = bsp_eeprom_save_data(cfg_idx, data, kEepromDataType_Full);
		    }
		    else if(tmp == 4)
		    {
			    cfg_idx = (offset_new / 6) * 5 + 4 + kEep_HT2TempAlarm1Alarm1;        
			    tmp = bsp_eeprom_save_data(cfg_idx, data, kEepromDataType_High);
		    }
		    else if(tmp == 5)
		    {
			    cfg_idx = (offset_new / 6) * 5 + 4 + kEep_HT2TempAlarm1Alarm1;        
			    tmp = bsp_eeprom_save_data(cfg_idx, data, kEepromDataType_Low);
		    }
        }
    }
    return tmp;
}


void bms_init_fdb(void)
{
    bsp_fdb_init(&fdb_item);
    bms_analyse_model_data();
}
