#ifndef MEMU_H__
#define MEMU_H__
#define MENU_PLATFORM_16BIT 0U
#define MENU_PLATFORM_32BIT 1U
#define MENU_PLATFORM_SELECT MENU_PLATFORM_32BIT
#if (MENU_PLATFORM_SELECT == MENU_PLATFORM_16BIT)
typedef unsigned char Menu_uint8_t;
typedef unsigned int Menu_uint16_t;
typedef unsigned long Menu_uint32_t;
#define MENU_INT_SIZE 2U
#define MENU_ENUM_SIZE 2U
#elif (MENU_PLATFORM_SELECT == MENU_PLATFORM_32BIT)
typedef unsigned char Menu_uint8_t;
typedef unsigned short Menu_uint16_t;
typedef unsigned int Menu_uint32_t;
#define MENU_INT_SIZE 4U
#define MENU_ENUM_SIZE 4U
#else
#error platform select error!!!
#endif
/*--------------------------Please do not modify the above content--------------------------------*/
/*--------------------------Please do not modify the above content--------------------------------*/
/*--------------------------Please do not modify the above content--------------------------------*/
/*
使用注意事项:
1、当光标在某个分枝时,不可以把该分枝最顶层菜单界面的选项都设置成条件取消的状态。
	都取消了,光标往哪跳!!!
2、考虑上述问题,建议那些一个分枝就一个菜单项的那种,不要设置条件取消。
	不需要的时候不跳转到那个分枝就好。
3、所有函数请在主循环内调用,不要在中断内调用。
*/
/*所有菜单项的枚举
即使某些菜单项在显示上相同,但因隶属不同菜单界面,所以要用不同枚举区分
*/
typedef enum
{
	//MENU_ITEM_ENTRANCE_FIX = 0U, /*入口固定项*/
	MENU_ITEM_ECU_TRIP,
	MENU_ITEM_ECU_RANGE,
	MENU_ITEM_ECU_INS_FUEL,
	MENU_ITEM_ECU_AVER_FUEL,
	MENU_ITEM_ECU_AVER_SPEED,
	MENU_ITEM_ECU_MAINTAIN,
	MENU_ITEM_ECU_TPMS,

	MENU_ITEM_SET_Backlight,
	MENU_ITEM_SET_Sound,
	MENU_ITEM_SET_TimeHour,
	MENU_ITEM_SET_TimeMin,
	MENU_ITEM_MAX,
} Menu_Item_en_t;
/*所有菜单界面的枚举*/
typedef enum
{
	//MENU_INTF_ENTRANCE = 0U, /*入口*/
	MENU_INTF_ECU, 
	MENU_INTF_SET,
	MENU_INTERFACE_MAX,
} Menu_Interface_en_t;
/*所有菜单分支*/
typedef enum
{
	//MENU_BRANCH_ANIMATION = 0U, /*开机动画*/
	MENU_BRANCH_ECU = 0,
	MENU_BRANCH_SET,
	MENU_BRANCH_MAX,
} Menu_Branch_en_t;
/*需要记忆的深度*/
#define MENU_CURSOR_MEMORY_DEPTH 0UL
/*--------------------------Do not modify the following--------------------------------*/
/*--------------------------Do not modify the following--------------------------------*/
/*--------------------------Do not modify the following--------------------------------*/
#define MENU_RAM_DATA_LEN ((2UL * MENU_INT_SIZE + 4UL * MENU_ENUM_SIZE) + \
						   (MENU_ENUM_SIZE * MENU_BRANCH_MAX) +           \
						   (MENU_ENUM_SIZE * MENU_INTERFACE_MAX) +        \
						   (MENU_INT_SIZE * 2UL * MENU_ITEM_MAX) +        \
						   (MENU_ENUM_SIZE * MENU_CURSOR_MEMORY_DEPTH))
/*-------------------------配置字说明---------------
预留位必须填0,其他位根据需要自行选择。
0x0001位:是否可循环,顶端底端循环衔接与否 1:可循环,0:不可循环
0x0002位:预留
0x0004位:预留
0x0008位:预留
0x0010位:预留
0x0020位:预留
0x0040位:预留
0x0080位:预留
0x0100位:预留
0x0200位:预留
0x0400位:预留
0x0800位:预留
0x1000位:预留
0x2000位:预留
0x4000位:预留
0x8000位:预留
--------------------------------------------*/
/*----菜单支持的按键类型-----------*/
typedef enum
{
	MENU_KEY_NONE = 0U,
	/*6个按键的短按动作*/
	MENU_KEY_UP_SHORT,
	MENU_KEY_DOWN_SHORT,
	MENU_KEY_LEFT_SHORT,
	MENU_KEY_RIGHT_SHORT,
	MENU_KEY_CANCEL_SHORT,
	MENU_KEY_CONFIRM_SHORT,
	/*仅针对菜单光标的特殊触发动作*/
	MENU_KEY_TIMEOUT, /*超时动作触发*/
	/*6个按键的长按动作*/
	MENU_KEY_UP_LONG,
	MENU_KEY_DOWN_LONG,
	MENU_KEY_LEFT_LONG,
	MENU_KEY_RIGHT_LONG,
	MENU_KEY_CANCEL_LONG,
	MENU_KEY_CONFIRM_LONG,
	/*6个按键的超长按动作*/
	MENU_KEY_UP_SUPER_LONG,
	MENU_KEY_DOWN_SUPER_LONG,
	MENU_KEY_LEFT_SUPER_LONG,
	MENU_KEY_RIGHT_SUPER_LONG,
	MENU_KEY_CANCEL_SUPER_LONG,
	MENU_KEY_CONFIRM_SUPER_LONG,
	/*针对具体功能的特殊操作按键*/
	MENU_KEY_FUNCTION_1_SHORT,
	MENU_KEY_FUNCTION_1_LONG,
	MENU_KEY_FUNCTION_1_SUPER_LONG,
	MENU_KEY_FUNCTION_2_SHORT,
	MENU_KEY_FUNCTION_2_LONG,
	MENU_KEY_FUNCTION_2_SUPER_LONG,
	MENU_KEY_MAX,
} Menu_Key_en_t;
/*------菜单操作方向-------------------------------------------
--------默认纵向时,上下按键实现菜单项切换,左右按键实现翻页功能-----------
--------横向时,左右按键实现菜单项切换,上下按键实现翻页功能--------------
-------------------------------*/
typedef enum
{
	MENU_DIRECTION_LONGITUDINAL = 0U, /*纵向*/
	MENU_DIRECTION_TRANSVERSE,		  /*横向*/
	MENU_DIRECTION_MAX,
} Menu_Direction_en_t;
/*------菜单跳转类型选择,菜单界面发生变化时,确定进入,按键返回,超时返回等-----------*/
typedef enum
{
	/*跳转到首个位置*/
	MENU_JUMP_FIRST = 0U,
	/*跳转到末尾位置*/
	MENU_JUMP_END,
	/*跳转到已选择的菜单项上,如果有多个,选择位置靠前的*/
	MENU_JUMP_SELECT,
	/*跳转到上一次光标位置*/
	MENU_JUMP_LAST_POSITION,
	MENU_JUMP_MAX,
} Menu_Jump_Type_en_t;
/*当发生分枝切换时,对目标分枝光标的处理方式*/
typedef enum
{
	/*切换光标到分枝的首个位置上*/
	MENU_CHANGE_FIRST = 0U,
	/*切换光标到之前离开时的位置上,也就是记忆位置,从那来回哪去。*/
	MENU_CHANGE_HOLD,
	/*切换光标到记忆位置的上一个菜单层级*/
	MENU_CHANGE_PREVIOUS,
	MENU_CHANGE_MAX,
} Menu_Change_Type_en_t;
/*
错误检查结果
*/
typedef enum
{
	MENU_ERROR_NONE = 0U,
	MENU_ERROR_1, /*菜单项所隶属的菜单界面信息错误*/
	MENU_ERROR_2, /*菜单项所隶属的菜单分支信息错误*/
	MENU_ERROR_3, /*屏幕上每列可显示的行数需要小于等于菜单界面的总数 */
	MENU_ERROR_4,
	MENU_ERROR_5,  /*确认、返回、超时三个触发动作的跳转方式错误 */
	MENU_ERROR_6,  /*界面内所有菜单项是按照顺序填写的,*/
	MENU_ERROR_7,  /*同一个菜单界面内所填总数数值是一致的*/
	MENU_ERROR_8,  /*同一个菜单界面内所有菜单项的上级菜单项也是一致的。*/
	MENU_ERROR_9,  /*同一个菜单界面内每列可显示的行数也是一致的。*/
	MENU_ERROR_10, /*菜单界面内每个菜单项对应的总数与实际填写的菜单项项数量需要对应*/
	MENU_ERROR_11, /*菜单界面枚举数量和实际填写的菜单界面数量能对应上*/
	MENU_ERROR_12, /*分枝内菜单项序号不连续*/
	MENU_ERROR_13, /*分枝内菜单项总数不一致*/
	MENU_ERROR_14, /*分枝内菜单项的总数与实际填写的数量不对应*/
	MENU_ERROR_15, /*菜单分枝枚举数量和实际填写的菜单分枝数量不对应*/
	MENU_ERROR_16, /*菜单项所填方向信息错误*/
	MENU_ERROR_17, /*不可以向上无限循环。enMenuBelongItem填写错误*/
	MENU_ERROR_18,
	MENU_ERROR_19, /*菜单界内的菜单项必须连续,不可分散排列。*/
	MENU_ERROR_20, /*菜单分枝内所有的菜单项必须连续排列。不可分散排列。*/
	MENU_ERROR_21, /*确认按键跳级或者多个菜单界面的上级菜单项共用了一个*/
	MENU_ERROR_22, /*确认按键不可以跨分枝跳转*/
	MENU_ERROR_23, /*同一分枝内不可以出现与主分枝无连接的其他菜单项*/
	MENU_ERROR_24,
	MENU_ERROR_25,
	/*多对一。多个菜单项上按下确认后都跳到同一个菜单界面上。
	在能确保多对一中,“多”代表的所有菜单项存在条件永远成立时,可忽略本条。
	*/
	MENU_WARNING_1,
	MENU_ERROR_MAX,
} Menu_Error_en_t;
/*菜单属性表错误相关*/
typedef struct
{
	/*错误类型*/
	Menu_Error_en_t enMenuErrorType;
	/*菜单项或者其所在界面或者其所在分枝出现错误*/
	Menu_Item_en_t enMenuErrorItem;
} Menu_Error_Information_en_t;
/*菜单初始化类型*/
typedef struct
{
	/*菜单项长度,不可为0*/
	Menu_Item_en_t enMenuItemLen;
	/*菜单界面长度,不可为0*/
	Menu_Interface_en_t enMenuInterfaceLen;
	/*菜单分枝长度,不可为0*/
	Menu_Branch_en_t enMenuBranchLen;
	/*菜单配置信息*/
	unsigned int uintMenuConfig;
	/*需要记忆的深度
	当不需要记忆光标位置时可设置为0
	当仅需要记忆上次光标位置时设置为1,
	当仅需要记忆上次和上上次时设置成2,
	当仅需要记忆上次、上上次和上上上次时设置成3,
	以此类推
	*/
	unsigned int uintMenuCursorMemoryDepth;
} Menu_Init_st_t;
typedef void (*Logic_Operation)(Menu_Key_en_t enKeyType);
/*每个菜单项的固定属性*/
typedef struct
{
	/*定位在哪个分枝上*/
	Menu_Branch_en_t enMenuLocateBranch;
	/*定位在哪个菜单界面内*/
	Menu_Interface_en_t enMenuLocateInterface;
	/*归属哪个菜单项,上级菜单项。
	一般可以理解为在哪个菜单项上按确认按键进入的*/
	Menu_Item_en_t enMenuBelongItem;
	/*该菜单项所在界面的位置,一定顺序填写,从0开始*/
	unsigned int uintMenuPositionInInterface;
	/*该菜单项所在界面的所有项数*/
	unsigned int uintMenuItemTotalInInterface;
	/*屏幕内可显示的,每一列最多有几个横向行,*/
	unsigned int uintMenuTransverseNum;
	/*该菜单项所在分支的位置,一定顺序填写,从0开始。0表示首个位置*/
	unsigned int uintMenuPositionInBranch;
	/*该菜单项所在分支的所有项数*/
	unsigned int uintMenuItemTotalInBranch;
	/*菜单方向*/
	Menu_Direction_en_t enMenuDirection;
	/*本菜单项都支持哪些触发动作。
	待开发,暂定填0xFF即可*/
	unsigned int uintMenuKeyBit;
	/*下一级菜单界面,也就是按下确认按键后需要跳转到的界面,
	如果没有下级菜单时填0xFFFF,不要填本身序号*/
	Menu_Interface_en_t enMenuNextInterface;
	/*按下确认按键,进入新菜单界面时,光标跳转类型*/
	Menu_Jump_Type_en_t enMenuNextJumpPostion;
	/*上一级菜单界面,也就是按下返回按键后需要跳转到的界面,
	如果没有上级菜单时填0xFFFF,不要填本身序号*/
	Menu_Interface_en_t enMenuPreviousInterface;
	/*按下返回按键,返回菜单界面时,光标跳转类型*/
	Menu_Jump_Type_en_t enMenuPreviousJumpPostion;
	/*按键超时时需要返回到的菜单界面,
	如果不需要返回(返回到自身)时填0xFFFF不要填本身序号*/
	Menu_Interface_en_t enMenuTimeoutInterface;
	/*超时返回界面中光标跳转的类型*/
	Menu_Jump_Type_en_t enMenuTimeoutJumpPostion;
	/*----------------------------------------------------------*/
	/*   具体功能逻辑的回调函数,按键操作类型,上下左右确认返回    */
	Logic_Operation pfnLogicOperationCallBack;
} Menu_Item_Attribute_st_t;
/*--------------------------------------------------------------------------------------------*/
extern const Menu_Item_Attribute_st_t stMenuItemAttribute[MENU_ITEM_MAX];
/*------------------------------------------------------------------------------------*/
/*
调试开发阶段使用,检测所填属性表是否有错误.
返回值是MENU_ERROR_NONE时,才可调用后续其他函数。
注意每次修改属性表,都调用一下该函数,确定属性表填写无误。
已经确认属性表无误之后可屏蔽该函数。
enItemMAX:最大菜单项数,也就是MENU_ITEM_MAX
enInterfaceMAX:最大菜单界面数,也就是MENU_INTERFACE_MAX
enBranchMAX:最大菜单分枝数,也就是MENU_BRANCH_MAX
*/
extern Menu_Error_Information_en_t Menu_Attribute_Error_Check(Menu_uint8_t *pu8MenuRamData, const Menu_Item_Attribute_st_t *pstMenuAttribute, Menu_Init_st_t *pstMenuInit);
/*
首次上电调用一次即可,不必重复调用。
初始化默认所有菜单项有效,且没有被选中。
u32MenuItemLen:最大菜单项数,也就是MENU_ITEM_MAX
u32MenuInterfaceLen:最大菜单界面数,也就是MENU_INTERFACE_MAX
u32MenuBranchLen:最大菜单分枝数,也就是MENU_BRANCH_MAX
u32MenuConfig:配置字,根据实际需要填写。
*/
extern void Menu_Init(Menu_uint8_t *pu8MenuRamData, const Menu_Item_Attribute_st_t *pstMenuAttribute, Menu_Init_st_t *pstMenuInit);
/*
每次休眠后唤醒时调用一次。
*/
extern void Menu_Wake_Up_Init(Menu_uint8_t *pu8MenuRamData, const Menu_Item_Attribute_st_t *pstMenuAttribute, Menu_Init_st_t *pstMenuInit);
/*
菜单光标动作具体执行函数。
传入按键动作
主循环内调用!主循环内调用!主循环内调用!*/
extern void Menu_Cursor_Process(Menu_Key_en_t enMenuKey);
/*菜单逻辑回调函数的调用
具体菜单功能在此处调用执行*/
extern void Menu_Logic_Process(Menu_Key_en_t enMenuKey);
/*分枝切换
enMenuBranch:目标分枝
enMenuChangePostion:目标位置的类型
返回:实际切换到的菜单项
主循环内调用!主循环内调用!主循环内调用!
*/
extern Menu_Item_en_t Menu_Change_Branch(Menu_Branch_en_t enMenuBranch, Menu_Change_Type_en_t enMenuChangeType);
/*分枝切换
enMenuBranch:目标分枝
enMenuItemDes:目标选项
返回:实际切换到的菜单项
主循环内调用!主循环内调用!主循环内调用!
*/
extern Menu_Item_en_t Menu_Change_Branch_To_Item(Menu_Branch_en_t enMenuBranch, Menu_Item_en_t enMenuItemDes);
/*获取当前光标位置*/
extern Menu_Item_en_t Menu_Get_Current_Cursor_Information(void);
/*获取光标记忆位置
输入0获得光标记忆的上个位置
输入1获得光标记忆的上上个位置
输入2获得光标记忆的上上上个位置
注意不要超过设置的深度信息*/
extern Menu_Item_en_t Menu_Get_Memory_Cursor_Information(unsigned int uintCursorMemoryIndex);
/*获取某个菜单界面内记忆的光标位置*/
extern Menu_Item_en_t Menu_Get_Cursor_In_Interface(Menu_Interface_en_t enMenuInterface);
/*获取某个分枝内记忆的光标位置*/
extern Menu_Item_en_t Menu_Get_Cursor_In_Branch(Menu_Branch_en_t enMenuBranch);
/*
某个菜单项存在条件的设置
0:不成立,菜单项不显示
1:成立,需要显示菜单项
主循环内调用!主循环内调用!主循环内调用!
*/
extern void Menu_Item_Exist_Condition_Set(Menu_Item_en_t enMenuItem, Menu_uint8_t u8ExistOrNot);
/*------获取某个菜单项的成立条件。0:不成立,1:成立-------*/
extern Menu_uint8_t Menu_Item_Exist_Condition_Get(Menu_Item_en_t enMenuItem);
/*
设置某个菜单项是否被选中
0:未选中,没有勾选
1:选中,被勾选了
*/
extern void Menu_Item_Select_Set(Menu_Item_en_t enMenuItem, Menu_uint8_t u8SelectOrNot);
/*
获取某个菜单项是否被选中
0:未选中,没有勾选
1:选中,被勾选了
*/
extern Menu_uint8_t Menu_Item_Select_Get(Menu_Item_en_t enMenuItem);
/*获取某个菜单项所属的界面*/
/*stMenuItemAttribute[某个菜单项].enMenuLocateInterface;*/
/*获取某个菜单项所属的分枝*/
/*stMenuItemAttribute[某个菜单项].enMenuLocateBranch;*/
/*-----------------------------------------------------------------------------------*/
extern Menu_uint8_t u8MenuRamData[MENU_RAM_DATA_LEN];
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
void Menu_Hide_Service(void);
void Menu_User_Init(PoMa_Reset_en_t PowerType);
#endif