

#include "onechip_include_header.h"

// 用户数据存储地址——选择Flash末尾区域，避免覆盖程序代码
// STM32F103RE Flash: 0x08000000 ~ 0x0807FFFF (512KB)
#define CFG_PARAM_START_ADDR  0x0807F800   // 最后1页(2KB)起始地址


#define onechip_name  "Onechip602"
#define onechip_pswd  "onechip1003"
#define default_SN  "2603001"


/**
 * @brief 从指定Flash地址读取32位数据
 */
uint32_t Flash_ReadWord(uint32_t address)
{
    return *(__IO uint32_t*)address;
}

/**
 * @brief 从指定Flash地址读取16位数据
 */
uint16_t Flash_ReadHalfWord(uint32_t address)
{
    return *(__IO uint16_t*)address;
}

/**
 * @brief 向Flash写入16位数据（半字）
 * @param address 目标地址（必须为偶数，2字节对齐）
 * @param data    要写入的数据（16位）
 * @retval HAL_OK 成功，否则失败
 */
HAL_StatusTypeDef Flash_WriteHalfWord(uint32_t address, uint16_t data)
{
    HAL_StatusTypeDef status = HAL_ERROR;
    
    // 1. 解锁Flash
    HAL_FLASH_Unlock();
    
    // 2. 写入半字数据
    status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, address, data);
    
    // 3. 锁定Flash
    HAL_FLASH_Lock();
    
    return status;
}

/**
 * @brief 向Flash写入32位数据（字）
 * @param address 目标地址（必须为4字节对齐）
 * @param data    要写入的数据（32位）
 */
HAL_StatusTypeDef Flash_WriteWord(uint32_t address, uint32_t data)
{
    HAL_StatusTypeDef status = HAL_ERROR;
    
    HAL_FLASH_Unlock();
    status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data);
    HAL_FLASH_Lock();
    
    return status;
}

/**
 * @brief 擦除指定Flash页
 * @param page_address 页起始地址（必须是页边界对齐）
 */
HAL_StatusTypeDef Flash_ErasePage(uint32_t page_address)
{
    HAL_StatusTypeDef status = HAL_ERROR;
    FLASH_EraseInitTypeDef EraseInitStruct;
    uint32_t PageError = 0;
    
    // 计算页号
    // uint32_t page_num = (page_address - FLASH_BASE) / FLASH_PAGE_SIZE;
    
    HAL_FLASH_Unlock();
    
    EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.PageAddress = page_address;
    EraseInitStruct.NbPages = 1;
    
    status = HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
    
    HAL_FLASH_Lock();
    
    return status;
}

/**
 * @brief 向Flash写入多个半字数据（自动处理擦除）
 * @param start_addr 起始地址
 * @param pBuffer    数据缓冲区
 * @param NumToWrite 要写入的半字数量
 */
void Flash_WriteBuffer(uint32_t start_addr, uint8_t *pBuffer, uint32_t NumToWrite)
{
    // 1. 擦除目标页
    uint32_t page_start = start_addr - (start_addr % FLASH_PAGE_SIZE);
    Flash_ErasePage(page_start);
    
    // 2. 依次写入每个半字
    for (uint32_t i = 0; i < NumToWrite; i=i+4) {
        Flash_WriteWord(start_addr + i * 4, pBuffer[i]);
    }
}


/********************************************************************
*                         checksum_calc()
*
*描述：接收数据checksum计算
*参数：pdata：要计算的数据
*     len：要计算的数据长度
*返回：checksum值
*其他：无
*--------------------------------------------------------------------
*记录：
********************************************************************/
uint32_t checksum_calc(uint8_t *pdata, uint8_t len)
{
	uint8_t *tmp     = pdata;
	uint8_t checksum = 0;

	for(uint8_t i = 0; i < len; i++)
	{
		checksum += tmp[i];
	}

	return checksum;
}

/********************************************************************
*                         checksum_calc()
*
*描述：接收数据checksum计算
*参数：pdata：要计算的数据
*     len：要计算的数据长度
*返回：checksum值
*其他：无
*--------------------------------------------------------------------
*记录：
********************************************************************/
uint32_t checksum_calc1(uint8_t *wdata, int len)
{
	uint32_t checksum = 0;

	for(int i = 0; i < len; i++)
	{
		checksum += wdata[i];
	}

	return checksum;
}

/********************************************************************
*                         cfg_load_default_param()
*
*描述：加载默认参数
*参数：无
*返回：无
*其他：无
*--------------------------------------------------------------------
*记录：
********************************************************************/
void cfg_load_default_param(void)
{
	sysinf.presetTempVal = 72;
	sysinf.presetTempTime = 5;
	sysinf.setTempVal    = 68;
	sysinf.holdTemp = 65.5;
	sysinf.tempOffset = 2.5f;
	sysinf.preHeatTime = 1;
	sysinf.readyTemp = 65.5;
	sysinf.adjtemp = -0.5;
	sysinf.log_level = 0;
	sysinf.skip_CheckOrRun = 0;
	sysinf.timeinner = 6000;
	sysinf.swingtime = 100;
	sysinf.swingspeed = 60;	
	sysinf.swingtimeRight = 40;
	sysinf.swingtimePause = 100;
	sysinf.runLoopTime = 600;
	sysinf.runLoopSpeed = 80;
	strcpy(sysinf.wifiname, onechip_name);
	strcpy(sysinf.password, onechip_pswd);
	memset(sysinf.SN, 0 ,sizeof(sysinf.SN));
	strcpy(sysinf.SN, default_SN);
}

/********************************************************************
*                         cfg_param_verify()
*
*描述：配置参数校验
*参数：无
*返回：0/1：校验不通过/通过
*其他：无
*--------------------------------------------------------------------
*记录：
********************************************************************/
uint8_t cfg_param_verify(void)
{
	
    unsigned char pramlen = sizeof(oneChipSysdef) - offsetof(oneChipSysdef, lysis_offset);

	if((uint32_t)checksum_calc((uint8_t *)CFG_PARAM_START_ADDR, (pramlen-4)) != *(uint32_t *)(CFG_PARAM_START_ADDR + (pramlen-4)))
	{
		return 0;
	}
	else
	{
		if(memcmp((uint8_t *)&sysinf.lysis_offset, (uint8_t *)CFG_PARAM_START_ADDR, pramlen) == 0)
		{
			return 1;
		}
		else
		{
			return 0;
		}
	}
}

/********************************************************************
*                         cfg_save_cfg_param()
*
*描述：保存配置参数
*参数：无
*返回：0/1：保存失败/成功
*其他：无
*--------------------------------------------------------------------
*记录：
********************************************************************/
uint8_t cfg_save_cfg_param(void)
{
    unsigned char pramlen = sizeof(oneChipSysdef) - offsetof(oneChipSysdef, lysis_offset);

	sysinf.checksum = (uint32_t)checksum_calc((uint8_t *)&sysinf.lysis_offset, (pramlen-4));
    Flash_WriteBuffer(CFG_PARAM_START_ADDR, (uint8_t *)&sysinf.lysis_offset, pramlen);
	return cfg_param_verify();
}

/********************************************************************
*                         cfg_param_init()
*
*描述：配置参数初始化
*参数：无
*返回：0/1：初始化失败/成功
*其他：无
*--------------------------------------------------------------------
*记录：
********************************************************************/
uint8_t cfg_param_init(void)
{
	uint8_t rlt = 0;

 	unsigned char pramlen = sizeof(oneChipSysdef) - offsetof(oneChipSysdef, lysis_offset);

	if((uint32_t)checksum_calc((uint8_t *)CFG_PARAM_START_ADDR, (pramlen-4)) != *(uint32_t *)(CFG_PARAM_START_ADDR + (pramlen-4)))
	{
		return 0;
	}
	else
	{
		cfg_load_default_param();
		rlt = cfg_save_cfg_param();
		Van_Device_Printf(VAN_LOG_CRITICAL, "读取参数出错，加载默认参数\r\n");
	}

	return rlt;
}
