/** ##########################################################################
**     Filename  :
**     Project   :
**     Module    :
**     Processor :
**     Version   : 1.0
**     Compiler  :
**     Date/Time :
**     Abstract  :
**     Contents  :
**     Note      :
**
**     (c) Copyright dmdz Co.,Ltd
**  --------------------------------------------------------------------------
**               R E V I S I O N   H I S T O R Y
**  --------------------------------------------------------------------------
**  Date       Ver   Author             Description

**  -20230602-  --V1.0--  --mingyea---  --修改--

** #########################################################################*/

/*---------------------------------------------------------------------------
- I N C L U D E   F I L E S
----------------------------------------------------------------------------*/
#include "eeprom_state_machine.h"
#include "common_cfg.h"
#include "common_memory.h"
#include "error.h"
#include "gpio.h"
//#include "key_app_cfg.h"
#include "system_voltage_manage.h"
#include "eeprom.h"
#include "wdog.h"

#ifdef NVM_EEPROM_EXT_EN

/*---------------------------------------------------------------------------
- D E F I N E S / M A C R O S
----------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------
- T Y P E   D E F I N I T I O N S
----------------------------------------------------------------------------*/



/*---------------------------------------------------------------------------
- S T A T I C   V A R I A B L E S
----------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------
* G L O B A L   V A R I A B L E S
----------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------
- C O N S T A N T S
----------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------
- F U N C T I O N   P R O T O T Y P E
----------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------
|Prototype			:
|Called by			:
|Preconditions		:
|Input parameters	: area_id: Var片区
|Output parameters	:
|Return value		:
|Description		:  片区0初始化
----------------------------------------------------------------------------*/
void eeprom_area_init(u8 area_id)
{
	u8 l_flag_read_all = 0u;
	assert_param(area_id<EEPROM_AREA_TOTAL);
	eeprom_drv_init(area_id);
	if(g_eeprom_ext[area_id].first_reset_flag != EEPROM_FLAG_NOT_FIRST_RESET)
	{
		common_memory_clear((u8*)&g_eeprom_ext[area_id],sizeof(g_eeprom_ext[area_id]));
		g_eeprom_ext[area_id].first_reset_flag = EEPROM_FLAG_NOT_FIRST_RESET;
		g_eeprom_ext[area_id].state = EFLASH_STATE_READ;
		g_eeprom_ext[area_id].trans_page_count = 0u;
		g_eeprom_ext[area_id].erase_state = EFLASH_PAGE_ERASE_STATE_WAIT_LAST_OPERATION;
		g_eeprom_ext[area_id].transfer_state = EFLASH_PAGE_TRANSFER_STATE_WRITE_NEW_DATA;
		#ifdef EEPROM_EXT_DEBUG_EN
		g_eeprom_ext_test[area_id].test_count[36]++;
		#endif
		l_flag_read_all =1u;
		//临时
		//common_memory_clear((u8*)&g_ram_for_eeprom_data,sizeof(g_ram_for_eeprom_data));
	}
	else
	{
		if(g_eeprom_ext[area_id].state== EFLASH_STATE_READ)
		{
			g_eeprom_ext[area_id].page_count=0u;
			l_flag_read_all =1u;
			//
		}
	}
	#ifdef EEPROM_OPTIMIZE_SEARCH_FAST
	eeprom_get_current_page_addr(area_id,&g_eeprom_ext[area_id].current_page,&g_eeprom_ext[area_id].current_end_addr);
	#endif
	g_eeprom_ext[area_id].page_addr_cur_total = 0u;
	if(l_flag_read_all ==1u)
	{
		#ifdef EEPROM_EXT_STATE_MACHILE_ENABLE
		//if(area_id == EEPROM_AREA_ID_APP)
		//{
			//eeprom_read_all_data_to_ram_seq(area_id);
		//}
		#else
		//读取所有到RAM----如果是第一次，就必读
		eeprom_read_all_data_to_ram_seq(area_id);
		#endif
	}
}


/*---------------------------------------------------------------------------
|Prototype			:
|Called by			:
|Preconditions		:
|Input parameters	: area_id: Var片区
|Output parameters	:
|Return value		:
|Description		:  内部实现的状态机
----------------------------------------------------------------------------*/
void eeprom_state_machine_task(u8 area_id)
{
	u16 i;
	u16 l_status = EFLASH_STATUS_SUCCESS;
	u16 virt_addr;
	u32 data;
	//static u16 data_index = 0;
	static u16 l_timeout = 0;
	u16 l_valid_page = EFLASH_PAGE0;
	//u8 l_buf[4];
	u8 l_count;
	switch (g_eeprom_ext[area_id].state)
	{
		case EFLASH_STATE_READ:

			l_count=0u;
			//EEPROM_EXT_TEST_ON();
			do
			{
				i=g_eeprom_ext[area_id].page_count;
				//讀取數據
				#ifdef EEPROM_EXT_DEBUG_IO_EN
				EEPROM_EXT_TEST_ON(area_id);
				#endif
				g_eeprom_ext[area_id].cmd_eeprom_result =eeprom_read_one_element(area_id,g_eeprom_ext[area_id].page_count,&g_logic_page_read_data[area_id]);
				#ifdef EEPROM_EXT_DEBUG_IO_EN
				EEPROM_EXT_TEST_OFF(area_id);
				#endif
				if(g_eeprom_ext[area_id].cmd_eeprom_result == EFLASH_READ_OK)
				{
					#ifdef EEPROM_EXT_DEBUG_EN
					g_eeprom_ext_test[area_id].test_count[37]++;
					#endif
				}
				else
				{
					#ifdef EEPROM_EXT_DEBUG_EN
					g_eeprom_ext_test[area_id].test_count[38]++;
					#endif
				}
				//復制到ram
				#if 0
				g_ram_for_eeprom[4u*i] = (g_logic_page_read_data>>24)&0xffu;
				g_ram_for_eeprom[4u*i+1u] = (g_logic_page_read_data>>16)&0xffu;
				g_ram_for_eeprom[4u*i+2u] = (g_logic_page_read_data>>8)&0xffu;
				g_ram_for_eeprom[4u*i+3u] = (g_logic_page_read_data)&0xffu;
				#else
				common_memory_copys((u8*)&g_ram_for_eeprom[area_id][4u*i],(u8*)&g_logic_page_read_data[area_id],EEPROM_READ_U32_NUM);
				#endif
				l_count++;
				#ifdef EEPROM_EXT_DEBUG_EN
				g_eeprom_ext_test[area_id].test_count[39]++;
				#endif
				g_eeprom_ext[area_id].page_count++;
				if(g_eeprom_ext[area_id].page_count>=EEPROM_AREAx_ADDR_TOTAL_U32(area_id))  //所有都读取完全
				{
					//EEPROM_EXT_TEST_OFF();
					g_eeprom_ext[area_id].page_count=0u;
					g_eeprom_ext[area_id].state = EFLASH_STATE_IDLE;
					#ifdef EEPROM_OPTIMIZE_SEARCH_FAST
					eeprom_get_current_page_addr(area_id,&g_eeprom_ext[area_id].current_page,&g_eeprom_ext[area_id].current_end_addr);
					#endif
					#ifdef EEPROM_EXT_DEBUG_EN
					g_eeprom_ext_test[area_id].test_count[40]++;
					#endif
					break;
				}
			}while(l_count<EEPROM_READ_U32_NUM);  //这个宏，在这里，应该重新命名，并定义
			//EEPROM_EXT_TEST_OFF();
		break;
		case EFLASH_STATE_IDLE:
			//do
			//{
				if(g_eeprom_ext[area_id].page_count>=EEPROM_AREAx_ADDR_TOTAL_U32(area_id))
				{
					g_eeprom_ext[area_id].page_count=0u;
					//
					g_eeprom_ext[area_id].result = EFLASH_RESULT_ONCE_OK;

					#ifdef EEPROM_EXT_DEBUG_EN
					g_eeprom_ext_test[area_id].test_count[41]++;
					#endif
					#ifdef EEPROM_OPTIMIZE_SEARCH_FAST
					eeprom_get_current_page_addr(area_id,&g_eeprom_ext[area_id].current_page,&g_eeprom_ext[area_id].current_end_addr);
					#endif
				}

				i=g_eeprom_ext[area_id].page_count;
				g_eeprom_ext[area_id].cmd_eeprom_result =eeprom_read_one_element(area_id,g_eeprom_ext[area_id].page_count,&g_logic_page_read_data[area_id]);
				if(g_eeprom_ext[area_id].cmd_eeprom_result == EFLASH_READ_OK)
				{
					#ifdef EEPROM_EXT_DEBUG_EN
					g_eeprom_ext_test[area_id].test_count[42]++;
					#endif
				}
				else
				{
					#ifdef EEPROM_EXT_DEBUG_EN
					g_eeprom_ext_test[area_id].test_count[43]++;
					#endif
				}
				//EEPROM_EXT_TEST_OFF();
				#if 1
				//if(0 == l_status) //己存在
				{
					#if 0
					g_logic_page_read_u8data[0] = (g_logic_page_read_data>>24)&0xffu;
					g_logic_page_read_u8data[1] = (g_logic_page_read_data>>16)&0xffu;
					g_logic_page_read_u8data[2] = (g_logic_page_read_data>>8)&0xffu;
					g_logic_page_read_u8data[3] = (g_logic_page_read_data>>0)&0xffu;
					#else
					common_memory_copys((u8*)&g_logic_page_read_u8data[area_id][0],(u8*)&g_logic_page_read_data[area_id],EEPROM_READ_U32_NUM);
					#endif
					if( (g_ram_for_eeprom[area_id][4*i] == g_logic_page_read_u8data[area_id][0] )
							&& (g_ram_for_eeprom[area_id][4*i+1] == g_logic_page_read_u8data[area_id][1] )
							&& (g_ram_for_eeprom[area_id][4*i+2] == g_logic_page_read_u8data[area_id][2] )
							&& (g_ram_for_eeprom[area_id][4*i+3] == g_logic_page_read_u8data[area_id][3] )
							)
					{
						//全部相同
						#ifdef EEPROM_EXT_DEBUG_EN
						g_eeprom_ext_test[area_id].test_count[44]++;
						#endif
					}
					else
					{
						//有不同--还得判断
						#if 0
						g_logic_page_write_data= ((u32)g_ram_for_eeprom[4*i]<<24)
											| ((u32)g_ram_for_eeprom[4*i+1]<<16)
											| ((u32)g_ram_for_eeprom[4*i+2]<<8)
											| ((u32)g_ram_for_eeprom[4*i+3]);
						#else
						common_memory_copys((u8*)&g_logic_page_write_data[area_id],(u8*)&g_ram_for_eeprom[area_id][4u*i],EEPROM_READ_U32_NUM);
						#endif
						g_eeprom_ext[area_id].page_cur_id = i;
						#ifdef EEPROM_EXT_DEBUG_IO_EN
						EEPROM_EXT_TEST_ON(area_id);
						#endif
						g_eeprom_ext[area_id].state = EFLASH_STATE_UPDATE;
						#ifdef EEPROM_EXT_DEBUG_IO_EN
						EEPROM_EXT_TEST_OFF(area_id);
						#endif
						#ifdef EEPROM_EXT_DEBUG_EN
						g_eeprom_ext_test[area_id].test_count[45]++;
						#endif
					}

				}
				#if 0
				else  //不存在
				{
					g_logic_page_data= ((u32)g_ram_for_eeprom[4*i]<<24)
										| ((u32)g_ram_for_eeprom[4*i+1]<<16)
										| ((u32)g_ram_for_eeprom[4*i+2]<<8)
										| ((u32)g_ram_for_eeprom[4*i+3]);
					g_eeprom_ext.page_cur_id = i;
					EEPROM_EXT_TEST_ON();
					g_eeprom_ext.state = EFLASH_STATE_UPDATE;
					EEPROM_EXT_TEST_OFF();
				}
				#endif
				#ifdef EEPROM_EXT_DEBUG_EN
				g_eeprom_ext_test[area_id].test_count[46]++;
				#endif
				g_eeprom_ext[area_id].page_count++;
				//break;
			//}while(1);
				#endif
			break;
		case EFLASH_STATE_UPDATE:
				virt_addr = g_eeprom_ext[area_id].page_cur_id;
				data = g_logic_page_write_data[area_id];
				/* Get valid Page for write operation */
				l_valid_page = eeprom_find_valid_page(area_id,EFLASH_WRITE_IN_VALID_PAGE);

				/* Check if there is no valid page */
				/* 扇区损坏，要格式化E2 需要很长时间，请关闭开门狗 */
				if (l_valid_page == EFLASH_NO_VALID_PAGE)
				{
					#ifdef EEPROM_EXT_DEBUG_IO_EN
					EEPROM_EXT_TEST1_ON(area_id);
					#endif
					eeprom_format(area_id);
					#ifdef EEPROM_EXT_DEBUG_IO_EN
					EEPROM_EXT_TEST1_OFF(area_id);
					#endif
					g_eeprom_ext[area_id].state = EFLASH_STATE_IDLE;
					#ifdef EEPROM_OPTIMIZE_SEARCH_FAST
					eeprom_get_current_page_addr(area_id,&g_eeprom_ext[area_id].current_page,&g_eeprom_ext[area_id].current_end_addr);
					#endif
					#ifdef EEPROM_EXT_DEBUG_EN
					g_eeprom_ext_test[area_id].test_count[47]++;
					#endif
					break;
				}
				#ifdef EEPROM_EXT_DEBUG_IO_EN
				//EEPROM_EXT_TEST1_ON(area_id);
				#endif
				l_status =  eeprom_verify_page_ful_write_one_ele(area_id,l_valid_page, virt_addr, data);
				#ifdef EEPROM_EXT_DEBUG_IO_EN
				//EEPROM_EXT_TEST1_OFF(area_id);
				#endif
				if(l_status == EFLASH_STATUS_PPADRER_ERROR)
				{
					#ifdef EEPROM_EXT_DEBUG_IO_EN
					EEPROM_EXT_TEST1_ON(area_id);
					#endif
					eeprom_format(area_id);
					#ifdef EEPROM_EXT_DEBUG_IO_EN
					EEPROM_EXT_TEST1_OFF(area_id);
					#endif
					g_eeprom_ext[area_id].state = EFLASH_STATE_IDLE;
					#ifdef EEPROM_OPTIMIZE_SEARCH_FAST
					eeprom_get_current_page_addr(area_id,&g_eeprom_ext[area_id].current_page,&g_eeprom_ext[area_id].current_end_addr);
					#endif
					#ifdef EEPROM_EXT_DEBUG_EN
					g_eeprom_ext_test[area_id].test_count[48]++;
					#endif
					break;
				}
				if(l_status == EFLASH_PAGE_FULL)
				{
					l_timeout = 0;
					#ifdef EEPROM_EXT_NOT_TRANS_MORE_WHEN_FULL
					if( g_eeprom_ext[area_id].page_addr_cur_total >= (g_eeprom_user_info[area_id].mass_page_addr_total_u32) )
					{
						#ifdef EEPROM_EXT_DEBUG_EN
						g_eeprom_ext_test[area_id].test_count[49]++;
						#endif
						g_eeprom_ext[area_id].state = EFLASH_STATE_IDLE;
						g_eeprom_ext[area_id].result = EFLASH_RESULT_ONCE_OK;
						#ifdef EEPROM_OPTIMIZE_SEARCH_FAST
						eeprom_get_current_page_addr(area_id,&g_eeprom_ext[area_id].current_page,&g_eeprom_ext[area_id].current_end_addr);
						#endif
					}
					else
					#endif
					{
						g_eeprom_ext[area_id].state = EFLASH_STATE_PAGE_TRANSFER;
						g_eeprom_ext[area_id].transfer_state = EFLASH_PAGE_TRANSFER_STATE_WRITE_NEW_DATA;
					}
					#ifdef EEPROM_EXT_DEBUG_EN
					g_eeprom_ext_test[area_id].test_count[50]++;
					#endif
				}
				else
				{
					#ifdef EEPROM_OPTIMIZE_SEARCH_FAST
					eeprom_get_current_page_addr(area_id,&g_eeprom_ext[area_id].current_page,&g_eeprom_ext[area_id].current_end_addr);
					#endif
					g_eeprom_ext[area_id].state = EFLASH_STATE_IDLE;
					#ifdef EEPROM_EXT_DEBUG_EN
					g_eeprom_ext_test[area_id].test_count[51]++;
					#endif
				}
				#ifdef EEPROM_EXT_DEBUG_EN
				g_eeprom_ext_test[area_id].test_count[52]++;
				#endif
			break;
		case EFLASH_STATE_PAGE_TRANSFER:
				virt_addr = g_eeprom_ext[area_id].page_cur_id;
				data = g_logic_page_write_data[area_id];
				l_status = eeprom_page_transfer(area_id,virt_addr, data);
				if(l_status == EFLASH_STATUS_SUCCESS)
				{
					g_eeprom_ext[area_id].state = EFLASH_STATE_IDLE;
					#ifdef EEPROM_EXT_DEBUG_EN
					g_eeprom_ext_test[area_id].test_count[53]++;
					#endif
				}
				if(l_status == EFLASH_STATUS_PPADRER_ERROR)
				{
					#ifdef EEPROM_EXT_DEBUG_IO_EN
					EEPROM_EXT_TEST1_ON(area_id);
					#endif
					eeprom_format(area_id);
					#ifdef EEPROM_EXT_DEBUG_IO_EN
					EEPROM_EXT_TEST1_OFF(area_id);
					#endif
					g_eeprom_ext[area_id].state = EFLASH_STATE_IDLE;
					#ifdef EEPROM_EXT_DEBUG_EN
					g_eeprom_ext_test[area_id].test_count[54]++;
					#endif
				}
				l_timeout ++;
				if( (l_timeout >= EEPROM_EXT_TIMEOUT) || (l_status != EFLASH_STATUS_BUSY && l_status != EFLASH_STATUS_SUCCESS))
				{
					//EFLASH_SetCtrlReg1(0x0);
					//EFLASH_LockCtrl(); //TEMP_CLOSE 这些不知道怎么修改
					g_eeprom_ext[area_id].state = EFLASH_STATE_IDLE;
					g_eeprom_ext[area_id].result = EFLASH_RESULT_ONCE_OK;
					#ifdef EEPROM_EXT_DEBUG_EN
					g_eeprom_ext_test[area_id].test_count[55]++;
					#endif
				}
				#ifdef EEPROM_EXT_DEBUG_EN
				g_eeprom_ext_test[area_id].test_count[56]++;
				#endif
				#ifdef EEPROM_OPTIMIZE_SEARCH_FAST
				if(g_eeprom_ext[area_id].state==EFLASH_STATE_IDLE)
				{
					eeprom_get_current_page_addr(area_id,&g_eeprom_ext[area_id].current_page,&g_eeprom_ext[area_id].current_end_addr);
				}
				#endif
			break;
		default:
			g_eeprom_ext[area_id].state = EFLASH_STATE_IDLE;
			#ifdef EEPROM_EXT_DEBUG_EN
			g_eeprom_ext_test[area_id].test_count[57]++;
			#endif
			break;
	}
}

/*---------------------------------------------------------------------------
|Prototype			:
|Called by			:
|Preconditions		:
|Input parameters	: area_id: Var片区
|Output parameters	:
|Return value		:
|Description		:  重新启动--一个循环
----------------------------------------------------------------------------*/
void eeprom_state_machine_area_resatrt(u8 area_id)
{
	assert_param(area_id<EEPROM_AREA_TOTAL);
	if(area_id == EEPROM_AREA_ID_0)
	{
		g_eeprom_ext[area_id].page_count=0u;
		g_eeprom_ext[area_id].result = EFLASH_RESULT_INIT;
	}
	else
	{
		#if EEPROM_AREA_TOTAL >1u
		g_eeprom_ext[EEPROM_AREA_ID_1].page_count=0u;
		g_eeprom_ext[EEPROM_AREA_ID_1].result = EFLASH_RESULT_INIT;
		#endif
	}
}

/*---------------------------------------------------------------------------
|Prototype			:
|Called by			:
|Preconditions		:
|Input parameters	:
|Output parameters	:
|Return value		:
|Description		:  重新启动--一个循环
----------------------------------------------------------------------------*/
void eeprom_state_machine_resatrt(void)
{
	u8 i;
	for(i=0u;i<EEPROM_AREA_TOTAL;i++)
	{
		g_eeprom_ext[i].page_count=0u;
		g_eeprom_ext[i].result = EFLASH_RESULT_INIT;
	}
}

/*---------------------------------------------------------------------------
|Prototype			:
|Called by			:
|Preconditions		:
|Input parameters	:
|Output parameters	:
|Return value		:
|Description		:  读取一个循环是否结束
----------------------------------------------------------------------------*/
u8 eeprom_state_machine_area_get_result(u8 area_id)
{
	u8 l_result = EFLASH_RESULT_INIT;
	assert_param(area_id<EEPROM_AREA_TOTAL);
	if(area_id == EEPROM_AREA_ID_0)
	{
		l_result = g_eeprom_ext[area_id].result;
	}
	else
	{
		#if EEPROM_AREA_TOTAL >1u
		l_result = g_eeprom_ext[area_id].result;
		#endif
	}
	return l_result;
}

/*---------------------------------------------------------------------------
|Prototype			:
|Called by			:
|Preconditions		:
|Input parameters	:
|Output parameters	:
|Return value		:
|Description		:  读取一个循环是否结束
----------------------------------------------------------------------------*/
u8 eeprom_state_machine_area_get_all_result_ok(void)
{
	u8 l_result = EFLASH_RESULT_ONCE_OK;
	//u8 l_total = EEPROM_AREA_TOTAL;
	u8 i;
	u8 l_power_grade = system_voltage_manage_mode_get(FUNC_SYSTEM_VOLTAGE_MANAGE_ID);

	if(l_power_grade == SYSTEM_VOLTAGE_MODE_LOW)
	{
		return l_result;
	}

	for(i=0u;i<EEPROM_AREA_TOTAL;i++)
	{
		l_result = g_eeprom_ext[i].result;
		if(l_result == EFLASH_RESULT_INIT)
		{
			break;
		}
	}
	return l_result;
}

/*---------------------------------------------------------------------------
|Prototype			:
|Called by			:
|Preconditions		:
|Input parameters	:
|Output parameters	:
|Return value		:
|Description		:  读取是否就绪--主要是己完成
----------------------------------------------------------------------------*/
u8 eeprom_state_machine_area_get_all_ready(void)
{
	u8 l_result = EFLASH_STATE_IDLE;
	u8 i;

	for(i=0u;i<EEPROM_AREA_TOTAL;i++)
	{
		l_result = g_eeprom_ext[i].state;
		if(l_result == EFLASH_STATE_READ)
		{
			break;
		}
	}
	return l_result;
}



/*---------------------------------------------------------------------------
|Prototype			:
|Called by			:
|Preconditions		:
|Input parameters	:
|Output parameters	:
|Return value		:
|Description		:  片区0初始化
----------------------------------------------------------------------------*/
void eeprom_ext_clear_flag(void)
{
	u8 i;
	for(i=0u;i<EEPROM_AREA_TOTAL;i++)
	{
		g_eeprom_ext[i].first_reset_flag = EEPROM_FLAG_FIRST_RESET_CLEAR;
	}
}



#endif


