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

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

// Flash存储规划如下：
// 0~7K: boot-loader，解压程序，由LDROM调入内存执行
// 8~11K: 配置数据（2K+2K，双份存储）
// 12~15K：保留
// 16~255K: 保留（以后可能用于存放16点阵的字库，现为了烧录方便，是放在程序里面）
// 256~511K：升级包
// 512K~8M: 保留（以后可能用于存放GPRS采集数据，现放在铁电里面）

// 每个配置块划分为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 / SFLASH_ERASE_SIZE;
    uint32_t u32StartAddr = SFLASH_CONFIG_BASE
				+ CONFIG_PARTITION(partition) * CONFIG_PARTITION_SIZE;

	for(i = 0; i < loop; i++)
	{
		SFlash_WriteEN();
		SFlash_PageErase(u32StartAddr + i * SFLASH_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 = SFLASH_CONFIG_BASE
				+ CONFIG_PARTITION(partition) * CONFIG_PARTITION_SIZE
				+ CONFIG_BLOCK(block) * CONFIG_BLOCK_SIZE
				+ CONFIG_DC(DC) * CONFIG_DC_SIZE;

	SFlash_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 = SFLASH_CONFIG_BASE
				+ CONFIG_PARTITION(partition) * CONFIG_PARTITION_SIZE
				+ CONFIG_BLOCK(block) * CONFIG_BLOCK_SIZE;

		if(SFlash_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_Open()
{	
	// 分配扩展内存
//	Config_rwBuf = SRAM_Alloc(CONFIG_BLOCK_SIZE);
	
	delay_ms(20);
	SFlash_UnlockBPR();
	


	// 读取保存的配置
	// 贴片厂测试软件关闭
	Config_LoadConfig();
	
//	apex// 测试代码
//	dcBuff.configBottle.PSN[0] = 25;	// PSN: 2025092980002
//	dcBuff.configBottle.PSN[1] = 9;
//	dcBuff.configBottle.PSN[2] = 29;
//	dcBuff.configBottle.PSN[3] = 80;
//	dcBuff.configBottle.PSN[4] = 0;
//	dcBuff.configBottle.PSN[5] = 2;
if(0== dcBuff.configBottle.offlineSeconds)
{
		// 设置默认参数（默认参数由另一个程序写入，本程序只读出来用）
	// 贴片厂测试软件打开
	Config_setBottleDefParam(&dcBuff);
	Config_setSensorDefParam(&dcBuff);
	Config_setDataDefParam(&dcBuff);
	Config_setDisplayDefParam(&dcBuff);
}

	Config_SaveConfig();
//	dcBuff.configData.intervalTrans = 120;
	
	// 填充采集板系统信息
	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****\tProductVer: %d ***\n", dcBuff.powerInfo.hardVer.minor);
	printf("\n****\tHardVer: %d, SoftVer: %d, protcolVer: %d, SoftDate: 20%02d-%02d-%02d ***\n",
		dcBuff.powerInfo.hardVer.major, dcBuff.powerInfo.softVer.minor, dcBuff.powerInfo.protocolVer.minor,
		dcBuff.powerInfo.softDate.year, dcBuff.powerInfo.softDate.month, dcBuff.powerInfo.softDate.day);
}
