/*
*********************************************************************************************************
*                                       IAR Development Kits
*                                              on the
*
*                                    M451
*
* Filename      : flash_config.h
* Version       : V1.00
* Programmer(s) : Qian Xianghong
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                             INCLUDE FILES
*********************************************************************************************************
*/
#include "includes.h"

// Flash存储规划如下：
// 252~255K: 配置数据（2K+2K，双份存储）

// 每个配置块划分为4组配置
#define CONFIG_DC_SIZE			(DATA_BUFF_SIZE)

// 配置分块大小（每个分区划为4个块，循环覆盖写入）
#define CONFIG_BLOCK_SIZE		(CONFIG_DC_SIZE * 4)

// 配置分区大小：主分区=镜像分区=可擦除页大小
#define CONFIG_PARTITION_SIZE	(CONFIG_BLOCK_SIZE * 4)

// 分区号: 0~1, 分块号: 0~3，分组号: 0~3
#define CONFIG_PARTITION(partition)	(partition)
#define CONFIG_BLOCK(block)			(block)
#define CONFIG_DC(DC)				((DC) - 1)

// 读写Flash的临时缓冲
static rd_buff_t rdBuff;

// 读写Flash的缓冲
uint8_t Config_rwBuf[CONFIG_BLOCK_SIZE] = {0};	// 扩展内存

static uint32_t Flash_ErasePartition(uint8_t partition)
{
    uint8_t i, loop = CONFIG_PARTITION_SIZE / FLASH_ERASE_SIZE;
    uint32_t u32StartAddr = FLASH_CONFIG_BASE
                            + CONFIG_PARTITION(partition) * CONFIG_PARTITION_SIZE;

    for(i = 0; i < loop; i++)
        Flash_ErasePage(u32StartAddr + i * FLASH_ERASE_SIZE);

    return TRUE;
}

static uint32_t Flash_ReadDC(uint8_t partition, uint8_t block, uint8_t DC, rd_buff_t *dataBuff)
{
    uint32_t u32StartAddr = FLASH_CONFIG_BASE
                            + CONFIG_PARTITION(partition) * CONFIG_PARTITION_SIZE
                            + CONFIG_BLOCK(block) * CONFIG_BLOCK_SIZE
                            + CONFIG_DC(DC) * CONFIG_DC_SIZE;

    Flash_BufferRead(u32StartAddr, dataBuff->buff, CONFIG_DATA_LEN(DC));
    return TRUE;
}

static uint32_t Flash_ReadBlock(uint8_t partition, uint8_t block, uint32_t forTest)
{
    // 采集板存储配置区1、2、3的数据
    if(CONFIG_BOARD_SELF == CONFIG_BOARD_SAMPLE || CONFIG_BOARD_SELF == CONFIG_BOARD_SINGLE)
    {
        if(!Flash_ReadDC(partition, block, CAN_DC_BOTTLE_CONFIG, &rdBuff) || !Config_CheckValid(&rdBuff, CAN_DC_BOTTLE_CONFIG))
            return FALSE;
        if(forTest)
            return TRUE;
        dcBuff.configBottle = rdBuff.configBottle;

        if(!Flash_ReadDC(partition, block, CAN_DC_SENSOR_CONFIG, &rdBuff) || !Config_CheckValid(&rdBuff, CAN_DC_SENSOR_CONFIG))
            return FALSE;
        dcBuff.configSensor = rdBuff.configSensor;

        if(!Flash_ReadDC(partition, block, CAN_DC_DATA_CONFIG, &rdBuff) || !Config_CheckValid(&rdBuff, CAN_DC_DATA_CONFIG))
            return FALSE;
        dcBuff.configData = rdBuff.configData;
    }

    // 电源板存储配置区4的数据
    if(CONFIG_BOARD_SELF == CONFIG_BOARD_POWER || CONFIG_BOARD_SELF == CONFIG_BOARD_SINGLE)
    {
        if(!Flash_ReadDC(partition, block, CAN_DC_DISPLAY_CONFIG, &rdBuff) || !Config_CheckValid(&rdBuff, CAN_DC_DISPLAY_CONFIG))
            return FALSE;
        if(CONFIG_BOARD_SELF == CONFIG_BOARD_POWER)
        {
            if(forTest)
                return TRUE;
        }
        dcBuff.configDisplay = rdBuff.configDisplay;
    }

    return TRUE;
}

static uint32_t Flash_ReadConfig(uint8_t partition, uint32_t forTest, uint8_t *blockNo)
{
    uint8_t block;

    for(block = 0; block < 4; block++)
    {
        if(Flash_ReadBlock(partition, block, forTest))
        {
            *blockNo = block;
            return TRUE;
        }
    }

    return FALSE;
}

static uint32_t Flash_WriteConfig(uint8_t partition)
{
    uint8_t block = 0;
    uint8_t i;
    uint32_t u32StartAddr;

    // 读取现有配置数据的块号
    if(!Flash_ReadConfig(partition, TRUE, &block))
        block = 3;

    for(i = 0; i < 4; i++)
    {
        // 确定循环写入的块号
        block = (block + 1) % 4;

        if(!Flash_ErasePartition(partition))
            return FALSE;

        memset(Config_rwBuf, 0xFF, CONFIG_BLOCK_SIZE);

        // 采集板存储配置区1、2、3的数据
        if(CONFIG_BOARD_SELF == CONFIG_BOARD_SAMPLE || CONFIG_BOARD_SELF == CONFIG_BOARD_SINGLE)
        {
            rdBuff.configBottle = dcBuff.configBottle;
            memmove(Config_rwBuf + CONFIG_DC(CAN_DC_BOTTLE_CONFIG) * CONFIG_DC_SIZE, rdBuff.buff, CONFIG_DATA_LEN(CAN_DC_BOTTLE_CONFIG));

            rdBuff.configSensor = dcBuff.configSensor;
            memmove(Config_rwBuf + CONFIG_DC(CAN_DC_SENSOR_CONFIG) * CONFIG_DC_SIZE, rdBuff.buff, CONFIG_DATA_LEN(CAN_DC_SENSOR_CONFIG));

            rdBuff.configData = dcBuff.configData;
            memmove(Config_rwBuf + CONFIG_DC(CAN_DC_DATA_CONFIG) * CONFIG_DC_SIZE, rdBuff.buff, CONFIG_DATA_LEN(CAN_DC_DATA_CONFIG));
        }

        // 电源板存储配置区4的数据
        if(CONFIG_BOARD_SELF == CONFIG_BOARD_POWER || CONFIG_BOARD_SELF == CONFIG_BOARD_SINGLE)
        {
            rdBuff.configDisplay = dcBuff.configDisplay;
            memmove(Config_rwBuf + CONFIG_DC(CAN_DC_DISPLAY_CONFIG) * CONFIG_DC_SIZE, rdBuff.buff, CONFIG_DATA_LEN(CAN_DC_DISPLAY_CONFIG));
        }

        u32StartAddr = FLASH_CONFIG_BASE
                       + CONFIG_PARTITION(partition) * CONFIG_PARTITION_SIZE
                       + CONFIG_BLOCK(block) * CONFIG_BLOCK_SIZE;

        Flash_BufferWrite(u32StartAddr, Config_rwBuf, CONFIG_BLOCK_SIZE);
        return TRUE;
    }
    return FALSE;
}

uint32_t Config_LoadConfig()
{
    uint8_t block;

    if(Flash_ReadConfig(0, FALSE, &block))
        return TRUE;
    return Flash_ReadConfig(1, FALSE, &block);
}

uint32_t Config_SaveConfig()
{
    uint32_t ret = 1, ret1 = 1;

    Config_ForceValid((rd_buff_t *) &dcBuff.configBottle, CAN_DC_BOTTLE_CONFIG);
    Config_ForceValid((rd_buff_t *) &dcBuff.configSensor, CAN_DC_SENSOR_CONFIG);
    Config_ForceValid((rd_buff_t *) &dcBuff.configData, CAN_DC_DATA_CONFIG);
    Config_ForceValid((rd_buff_t *) &dcBuff.configDisplay, CAN_DC_DISPLAY_CONFIG);

    // 贴片厂测试软件关闭
    ret = Flash_WriteConfig(0);
    ret1= Flash_WriteConfig(1);

    return ret || ret1;
}

void Config_Init()
{
}

void Config_Open()
{
    uint16_t i;
    extern const uint16_t LSrc_DensityExt[];

    // 分配扩展内存
//	Config_rwBuf = SRAM_Alloc(CONFIG_BLOCK_SIZE);

    delay_ms(20);

    // 设置默认参数（默认参数由另一个程序写入，本程序只读出来用）
    // 贴片厂测试软件打开
    Config_setBottleDefParam(&dcBuff);
    Config_setSensorDefParam(&dcBuff);
    Config_setDataDefParam(&dcBuff);
    Config_setDisplayDefParam(&dcBuff);

    // 读取保存的配置
    // 贴片厂测试软件关闭
    Config_LoadConfig();

    // 修改普莱克斯和林德的维护平台地址
    if(dcBuff.configBottle.serverVer == 3 || dcBuff.configBottle.serverVer == 4)
    {
        strcpy(dcBuff.configData.upgServer, dcBuff.configData.server);
    }

    // 液位计：修正默认参数
    if(dcBuff.configDisplay.op_PRODUCT_CLASS != PRODUCT_CLASS_LEVEL)
    {
        dcBuff.configDisplay.op_PRODUCT_CLASS = PRODUCT_CLASS_LEVEL;
        if(!dcBuff.configDisplay.op_DOL_VER)
        {
            dcBuff.configSensor.sensorPress.lowRange = 0;			// 0MPa
            dcBuff.configSensor.sensorPress.highRange = 4000;       // 4MPa
            dcBuff.configSensor.sensorPress.zeroValue = 683;	 	// 理论值：0.5v / 3.0v
            dcBuff.configSensor.sensorPress.fullValue = 3823; 		// 理论值：2.8v / 3.0v
        }
        else
        {
            dcBuff.configSensor.sensorPress.lowRange = 0;			// 0MPa
            dcBuff.configSensor.sensorPress.highRange = 5000;       // 5MPa
            dcBuff.configSensor.sensorPress.zeroValue = 710;		// 理论值：4mA * 130Ω / 3.0v
            dcBuff.configSensor.sensorPress.fullValue = 3550;		// 理论值：20mA * 130Ω / 3.0v
        }
        dcBuff.configBottle.warnPress = 300;					// 压力报警点
        dcBuff.configDisplay.L_Unit = UNIT_MMH2O;					// 显示单位
        // 保存
        Config_SaveConfig();
    }

    // 新增介质密度
    for(i = 0; i < sizeof(dcBuff.configBottle.densityExt) / sizeof(uint16_t); i++)
    {
        if(dcBuff.configBottle.densityExt[i] == 0)
            dcBuff.configBottle.densityExt[i] = LSrc_DensityExt[i];
    }

    // 新增温度报警参数
    if(dcBuff.configBottle.serverVer != 3 && dcBuff.configBottle.warnTemprH == 0 && dcBuff.configBottle.warnTempr == 0)
    {
        dcBuff.configBottle.warnTemprH = -300;
        dcBuff.configBottle.warnTempr = -300;
    }

    // 填充采集板系统信息
    if(CONFIG_BOARD_SELF == CONFIG_BOARD_SAMPLE || CONFIG_BOARD_SELF == CONFIG_BOARD_SINGLE)
        Config_fillSampleInfo(&dcBuff);

    // 填充电源板系统信息
    if(CONFIG_BOARD_SELF == CONFIG_BOARD_POWER || CONFIG_BOARD_SELF == CONFIG_BOARD_SINGLE)
        Config_fillPowerInfo(&dcBuff);

    // 填充显示板系统信息
    if(CONFIG_BOARD_SELF == CONFIG_BOARD_DISPLAY || CONFIG_BOARD_SELF == CONFIG_BOARD_SINGLE)
        Config_fillDisplayInfo(&dcBuff);

    // 填充蓝牙板系统信息
    if(CONFIG_BOARD_SELF == CONFIG_BOARD_BLUETOOTH || CONFIG_BOARD_SELF == CONFIG_BOARD_SINGLE)
        Config_fillBluetoothInfo(&dcBuff);

    // 显示版本及配置信息
    printf("\n****\tPSN: 20%02d%02d%02d%02d%03d ****\n", dcBuff.configBottle.PSN[0], dcBuff.configBottle.PSN[1],
           dcBuff.configBottle.PSN[2], dcBuff.configBottle.PSN[3],
           (dcBuff.configBottle.PSN[4] << 8) | dcBuff.configBottle.PSN[5]);

//	printf("\n****\thardVer.minor: %d ***\n", dcBuff.powerInfo.hardVer.minor);
//	printf("\n****\tsoftVer.minor: %d ***\n", dcBuff.powerInfo.softVer.minor);

    printf("\n****\tHardVer: %d, SoftVer: %d, protcolVer: %d, SoftDate: 20%02d-%02d-%02d ***\n",
           dcBuff.powerInfo.hardVer.minor, dcBuff.powerInfo.softVer.minor, dcBuff.powerInfo.protocolVer.minor,
           dcBuff.powerInfo.softDate.year, dcBuff.powerInfo.softDate.month, dcBuff.powerInfo.softDate.day);

//	dcBuff.configDisplay.op_DISP_MMWC_ONLY=1;
//	dcBuff.configDisplay.op_LEVEL_SENSOR_ONLY=0;

    if(dcBuff.configDisplay.op_DISP_MMWC_ONLY)
        printf("\n\t*** op_DISP_MMWC_ONLY = 1 ***\n");
    if(dcBuff.configDisplay.op_DOL_VER)
        printf("\n\t*** op_DOL_VER = 1 ***\n");
    if(dcBuff.configDisplay.op_BOX_VER)
        printf("\n\t*** op_BOX_VER = 1 ***\n");
    if(dcBuff.configDisplay.op_CELL_LOCATION)
        printf("\n\t*** op_CELL_LOCATION = 1 ***\n");
    if(dcBuff.configDisplay.op_LEVEL_SENSOR_ONLY)
        printf("\n\t*** op_LEVEL_SENSOR_ONLY = 1 ***\n");
    if(!dcBuff.configDisplay.op_LEVEL_SENSOR_ONLY)
    {
        if(!dcBuff.configDisplay.op_USE_PT100_SENSOR)
            printf("\n\t*** op_USE_PT100_SENSOR = 0 ***\n");
        if(dcBuff.configDisplay.op_USE_PT100_SENSOR && dcBuff.configDisplay.op_PT100_MULTI != 10)
            printf("\n\t*** op_PT100_MULTI = %d ***\n", dcBuff.configDisplay.op_PT100_MULTI);
        if(!dcBuff.configDisplay.op_PT100_3LINE)
            printf("\n\t*** op_PT100_3LINE = 0 ***\n");
        if(!dcBuff.configDisplay.op_DIFF_RESIST)
            printf("\n\t*** op_DIFF_RESIST = 0 ***\n");
    }
//	if(dcBuff.configDisplay.op_SEND_GPS_DATA)
//		printf("\n\t*** op_SEND_GPS_DATA = 1 ***\n");
//	if(dcBuff.configDisplay.op_USE_CAPACITY_SENSOR)
//		printf("\n\t*** op_USE_CAPACITY_SENSOR = 1 ***\n");
//	if(dcBuff.configDisplay.op_LOCAL_DISP)
//		printf("\n\t*** op_LOCAL_DISP = 1 ***\n");
//	if(dcBuff.configDisplay.op_ANTI_OVERFILL)
//		printf("\n\t*** op_ANTI_OVERFILL = 1 ***\n");
//	if(dcBuff.configDisplay.op_ALARM_OUTPUT)
//		printf("\n\t*** op_ALARM_OUTPUT = 1 ***\n");
//	if(dcBuff.configDisplay.op_LOW_ALARM_OUTPUT)
//		printf("\n\t*** op_LOW_ALARM_OUTPUT = 1 ***\n");
//	if(dcBuff.configDisplay.op_PRESS_ALARM_OUTPUT)
//		printf("\n\t*** op_PRESS_ALARM_OUTPUT = 1 ***\n");
//	if(dcBuff.configDisplay.op_LOW_PRESS_ALARM_OUTPUT)
//		printf("\n\t*** op_LOW_PRESS_ALARM_OUTPUT = 1 ***\n");
//	if(dcBuff.configDisplay.op_DIFF_420MA)
//		printf("\n\t*** op_DIFF_420MA = 1 ***\n");
//	if(dcBuff.configDisplay.op_PRESS_420MA)
//		printf("\n\t*** op_PRESS_420MA = 1 ***\n");
//	if(dcBuff.configDisplay.op_2ND_420MA_OUT_LEVEL)
//		printf("\n\t*** op_2ND_420MA_OUT_LEVEL = 1 ***\n");
//	if(dcBuff.configDisplay.op_USE_R0SEMOUNT)
//		printf("\n\t*** op_USE_R0SEMOUNT = 1 ***\n");
//	if(dcBuff.configDisplay.op_USE_SOLAR)
//		printf("\n\t*** op_USE_SOLAR = 1 ***\n");
//	if(dcBuff.configDisplay.op_USE_O2_LEAK)
//		printf("\n\t*** op_USE_O2_LEAK = 1 ***\n");
//	if(dcBuff.configDisplay.op_LEAK_ALARM_OUTPUT)
//		printf("\n\t*** op_LEAK_ALARM_OUTPUT = 1 ***\n");
//	if(dcBuff.configDisplay.op_USE_DOL_TTL)
//		printf("\n\t*** op_USE_DOL_TTL = 1 ***\n");
//	if(dcBuff.configDisplay.op_USE_HEIGHT_LEVEL)
//		printf("\n\t*** op_USE_HEIGHT_LEVEL = 1 ***\n");
//	if(dcBuff.configDisplay.op_USE_PCT_LEVEL)
//		printf("\n\t*** op_USE_PCT_LEVEL = 1 ***\n");
//	if(dcBuff.configBottle.dispMode != DISP_MODE_ALL)
//		printf("\n\t*** dispMode = %d ***\n", dcBuff.configBottle.dispMode);

//	if(dcBuff.configDisplay.op_SERVER_PROTOCOL == SERVER_PROTOCOL_MQTT)
//		printf("\n*** op_SERVER_PROTOCOL:\tMQTT ***\n");
//	else if(dcBuff.configDisplay.op_SERVER_PROTOCOL == SERVER_PROTOCOL_HTTPS)
//		printf("\n*** op_SERVER_PROTOCOL:\tHTTPS ***\n");
//	else if(dcBuff.configDisplay.op_SERVER_PROTOCOL == SERVER_PROTOCOL_HTTP)
//		printf("\n*** op_SERVER_PROTOCOL:\tHTTP ***\n");
//	else if(dcBuff.configDisplay.op_SERVER_PROTOCOL == SERVER_PROTOCOL_TRAIN)
//		printf("\n*** op_SERVER_PROTOCOL:\tTRAIN ***\n");
//	else if(dcBuff.configDisplay.op_SERVER_PROTOCOL == SERVER_PROTOCOL_AOYANG)
//		printf("\n*** op_SERVER_PROTOCOL:\tAOYANG ***\n");
//	else if(dcBuff.configDisplay.op_SERVER_PROTOCOL == SERVER_PROTOCOL_FURUI)
//		printf("\n*** op_SERVER_PROTOCOL:\tFURUI ***\n");
//	else
//		printf("\n*** op_SERVER_PROTOCOL:\tTCP ***\n");
//	printf("\n*** Server:\t%s:%d ***\n",
//		dcBuff.configDisplay.op_SERVER_PROTOCOL == SERVER_PROTOCOL_MQTT ?
//		SERVER_URLs[dcBuff.configDisplay.op_SERVER_INDEX] : dcBuff.configData.server,
//		dcBuff.configData.port);
//	if(dcBuff.configDisplay.op_SERVER_PROTOCOL == SERVER_PROTOCOL_TCP && dcBuff.configDisplay.op_UNIDIR_COMM)
//		printf("\n\t*** op_UNIDIR_COMM = 1 ***\n");

    printf("\n*** Sample:\t%ds ***\n", dcBuff.configData.intervalSample);
    printf("\n*** Send:\t%ds ***\n", dcBuff.configData.intervalTrans);

    printf("\n*** fullPct:\t%d*0.01kpa ***\n", dcBuff.configBottle.fullPct);
    printf("\n*** emptyPct:\t%d*0.01kpa ***\n", dcBuff.configBottle.emptyPct);

    printf("\n*** warnPressH:\t%d*1kpa ***\n", dcBuff.configBottle.warnPressH);
    printf("\n*** warnPress:\t%d*1kpa ***\n", dcBuff.configBottle.warnPress);

    printf("\n*** warnTemprH:\t%d*1c ***\n", dcBuff.configBottle.warnTemprH);
    printf("\n*** warnTempr:\t%d*1c ***\n", dcBuff.configBottle.warnTempr);

}
