Files
stm32f4_rtt_5.2.0/Menu/src/menu_pack.c
2025-06-19 21:57:12 +08:00

2042 lines
61 KiB
C

#include "math.h"
#include "menu_pack.h"
#include "menu_pack_port.h"
#include "string.h"
#include "ctype.h"
#include "stdio.h"
#define MAX_PACK_LAYER 8
#define MENU_PACK_ALIAS_ITEM_SORT 1 //排序后的队列, 可通过二分查找别名索引
#ifndef ADJUST_HIGHER_BIT
#define ADJUST_HIGHER_BIT 0
#endif
TMenuPackLevel MenuPack_Layer[MAX_PACK_LAYER];
int16_t MenuPack_LayerIndex = -1;
bool MenuPack_ModifyActive = false;
void MenuPack_AdjustModifyBuf(char *buf, int sel_bit, int key);
typedef enum EModbusAddrType
{
MODBUS_ADDR_TYPE_HODE_REGISTER_ADDR = 0,
MODBUS_ADDR_TYPE_BIT_ADDR = 1,
MODBUS_ADDR_TYPE_INPUT_BIT_ADDR = 2,
MODBUS_ADDR_TYPE_INPUT_REGISTER_ADDR = 3,
MODBUS_ADDR_TYPE_HODE_REGISTER_ADDR2 = 4,
} EModbusAddrType;
#define MODBUS_REG_COUNT_PER_TYPE 100000
typedef enum EMinMaxAdjust
{
ADJUST_MIN = 0,
ADJUST_MAX,
} EMinMaxAdjust;
static bool MenuPack_ModifyPassword(int modify_row, int modify_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info);
static int MenuPack_SearchAliasValueIndexMenuItem(const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info, uint16_t alias_value);
static bool MenuPack_ModifyIpAddr(int modify_row, int modify_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info);
static bool MenuPack_ModifySystemDate(int modify_row, int modify_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info);
static bool MenuPack_ModifySystemTime(int modify_row, int modify_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info);
static void MenuPack_AdjustModifyBufLimit(char *buf, const char *format, int sel_bit, EMinMaxAdjust adjust, int key);
static const char *MenuPack_GetStringScale(const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info);
static const char *MenuPack_GetStringFormat(const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info);
static const struct TMenuItemInfo *MenuPack_GetItem(const TMenuPackFileInfo *pinfo, TMenuPackLevel *pmenu_level);
static int MenuPack_ModifyStringBuf(int modify_row, int modify_col, char *buf, int key, int *psel_bit);
//RT_WEAK
bool MenuPack_CheckVisible(const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info)
{
return true;
}
//RT_WEAK
void MenuPack_ModifyBufCallBack(char *buf)
{
}
//RT_WEAK
int COMM_ReadRegisters(uint16_t *resp, uint16_t reg_addr, uint16_t range)
{
for (int i = 0; i < range; i++)
{
*((uint16_t *)resp + i) = 0;
}
return range;
}
//RT_WEAK
bool COMM_WriteRegisters(uint16_t *recv, uint16_t reg_addr, uint16_t range)
{
return false;
}
//RT_WEAK
int COMM_ReadBitRegisters(uint8_t *pbuf, uint16_t reg_addr, uint16_t range)
{
for (int i = 0; i < range; i++)
{
*((uint8_t *)pbuf + i) = 0;
}
return range;
}
//RT_WEAK
bool COMM_WriteBitRegisters(uint8_t *recv, uint16_t reg_addr, uint16_t range)
{
return false;
}
//RT_WEAK
void MenuPack_BrotherMenuEnterCallBack(const TMenuPackFileInfo *pinfo, int brother_menu_index, int key)
{
return;
}
//RT_WEAK
bool MenuPack_RegisterValueWrite(TCommRegisterInfo *pstcCommReg, void *pbuf)
{
uint64_t new_reg_value = 0;
uint64_t origin_reg_value = 0;
uint16_t *preg_write;
int reg_count = pstcCommReg->reg_count;
int reg_addr = pstcCommReg->reg_addr;
if (reg_count == 0)
{
return false;
}
EModbusAddrType addr_type = (EModbusAddrType)(reg_addr / MODBUS_REG_COUNT_PER_TYPE);
reg_addr = reg_addr % MODBUS_REG_COUNT_PER_TYPE;
if (addr_type == MODBUS_ADDR_TYPE_INPUT_BIT_ADDR || addr_type == MODBUS_ADDR_TYPE_BIT_ADDR)
{
return COMM_WriteBitRegisters((uint8_t *)pbuf, reg_addr, reg_count);
}
else
{
int bit = pstcCommReg->bit;
int bit_reg_count = reg_count;
if (bit >= 0)
{
int bit_reg_count = pstcCommReg->reg_count;
reg_addr = pstcCommReg->reg_addr + bit / 16;
bit = bit % 16;
reg_count = (bit + bit_reg_count) / 16;
if ((bit + bit_reg_count) % 16 > 0)
{
reg_count += 1;
}
}
else
{
reg_count = pstcCommReg->reg_count;
}
reg_count = min(reg_count, 4);
if (COMM_ReadRegisters((uint16_t *)&origin_reg_value, reg_addr, reg_count) != reg_count)
{
return false;
}
preg_write = (uint16_t *)pbuf;
if (bit >= 0)
{
uint32_t value_mask = (0xFFFFFFFF >> (32 - bit_reg_count)) << pstcCommReg->bit;
uint32_t new_value = *(uint16_t *)pbuf;
if (reg_count > 0)
{
new_value |= (*((uint16_t *)pbuf + 1) << 16);
}
new_reg_value = (origin_reg_value & ~value_mask) | ((new_value << pstcCommReg->bit) & value_mask);
preg_write = (uint16_t *)&new_reg_value;
}
return COMM_WriteRegisters((uint16_t *)preg_write, reg_addr, reg_count);
}
}
//RT_WEAK
int MenuPack_RegisterValueRead(TCommRegisterInfo *pstcCommReg, void *pbuf, int max_buf_items)
{
int read_reg_count = 0;
int reg_addr = pstcCommReg->reg_addr;
int reg_count = pstcCommReg->reg_count;
if (reg_count == 0)
{
return 0;
}
EModbusAddrType addr_type = (EModbusAddrType)(reg_addr / MODBUS_REG_COUNT_PER_TYPE);
reg_addr = reg_addr % MODBUS_REG_COUNT_PER_TYPE;
if (addr_type == MODBUS_ADDR_TYPE_INPUT_BIT_ADDR || addr_type == MODBUS_ADDR_TYPE_BIT_ADDR)
{
read_reg_count = COMM_ReadBitRegisters((uint8_t *)pbuf, reg_addr, reg_count);
}
else
{
int bit = pstcCommReg->bit;
int bit_reg_count = reg_count;
if (bit >= 0)
{
reg_addr = pstcCommReg->reg_addr + bit / 16;
bit = bit % 16;
reg_count = (bit + bit_reg_count) / 16;
if ((bit + bit_reg_count) % 16 > 0)
{
reg_count += 1;
}
}
read_reg_count = COMM_ReadRegisters((uint16_t *)pbuf, reg_addr, reg_count);
if (bit >= 0)
{
uint16_t *pvalue = (uint16_t *)pbuf;
uint32_t value = pvalue[0];
if (reg_count > 1)
{
value |= (pvalue[1] << 16);
}
uint32_t bit_read_value = (value >> bit) & (0xFFFFFFFF >> (32 - bit_reg_count));
*(uint16_t *)pbuf = bit_read_value & 0xFFFF;
if (reg_count > 1)
{
pvalue[1] = (bit_read_value >> 16) & 0xFFFF;
}
}
}
return read_reg_count;
}
//RT_WEAK
void MenuPack_ProcessFunc(EMenuPackCommand cmd, const struct TMenuItemInfo *pmenu_info, int key)
{
}
//RT_WEAK
void MenuPack_DisplayFlush(void)
{
}
//RT_WEAK
void MenuPack_Clear(void)
{
}
//RT_WEAK
void MenuPack_CommReinit(void)
{
}
//RT_WEAK
void MenuPack_DisplayModifyString(int modify_row, int modify_col, const char *str, int sel_bit)
{
}
//RT_WEAK
bool MenuPack_ActionItemModify(int modify_row, int modify_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info)
{
return true;
}
//RT_WEAK
void MenuPack_BeforeDisplayMenu(const TMenuPackFileInfo *pinfo, const char *pstr_action, int menu_index)
{
}
//RT_WEAK
void MenuPack_AfterDisplayMenu(const TMenuPackFileInfo *pinfo, const char *pstr_action, int menu_index)
{
}
//RT_WEAK
void MenuPack_MenuItemDisplay(const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info, int disp_line)
{
}
//RT_WEAK
void MenuPack_MenuActionProcess(const TMenuPackFileInfo *pinfo, const char *pstr_menu, int menu_index, int *pkey)
{
}
//RT_WEAK
const char *MenuPack_GetDisplayUnit(const char *punit, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info)
{
return punit;
}
//RT_WEAK
bool MenuPack_InputPassword(const TMenuPackFileInfo *pinfo, uint16_t *pvalue_password)
{
if (pvalue_password)
{
*pvalue_password = DEFAULT_ENGINEER_PASSWORD;
}
return true;
}
//RT_WEAK
bool MenuPack_CheckPasswordSuccess(const TMenuPackFileInfo *pinfo)
{
return true;
}
//RT_WEAK
void MenuPack_DisplayDefaultAction(int disp_row,
int disp_col,
const TMenuPackFileInfo *pinfo,
const struct TMenuItemInfo *pmenu_info,
const char *pstr_action)
{
MenuPack_DisplayStringPosSelect(disp_row, disp_col, DEFAULT_EMPTY_STRING);
MenuPack_DisplayStringPos(disp_row, disp_col, DEFAULT_EMPTY_STRING);
}
static int menu_pack_search_next_digit_bit(char *pbuf, int cur_bit)
{
int len = strlen(pbuf);
int new_bit = cur_bit + 1;
while (new_bit < len)
{
if (isdigit(pbuf[new_bit]))
{
return new_bit;
}
new_bit++;
}
return cur_bit;
}
static int menu_pack_search_next_digit_bit_after_dot(char *pbuf, int cur_bit)
{
while (*pbuf != '.' && *pbuf != '\0')
{
pbuf++;
cur_bit++;
}
return menu_pack_search_next_digit_bit(pbuf, cur_bit);
}
static double MenuPack_GetScaleValue(double scale, const char *pformat, uint32_t reg_value, int reg_count)
{
double scale_value;
if (strstr(pformat, "+") != NULL)
{
if (reg_count == 1)
{
scale_value = scale * (int16_t)reg_value;
}
else
{
scale_value = scale * (int32_t)reg_value;
}
}
else
{
if (reg_count == 1)
{
scale_value = scale * (uint16_t)reg_value;
}
else
{
scale_value = scale * (uint32_t)reg_value;
}
}
return scale_value;
}
int MenuPack_ModifyNormal(int modify_row, int modify_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info, int reg_off)
{
const char *pscale = MenuPack_GetStringScale(pinfo, pmenu_info);
const char *pformat = MenuPack_GetStringFormat(pinfo, pmenu_info);
const char *preg_addr_key_str = MenuPack_GetStringFromOffset(pinfo, pmenu_info->comm_str_offset);
TCommRegisterInfo stcRegInfo = MenuPack_UpdateCommInfo(preg_addr_key_str);
stcRegInfo.reg_addr += reg_off;
if (stcRegInfo.reg_count == 0)
{
return false;
}
uint16_t buf_value[2] = {0};
double scale = 1.0;
double scale_value;
char buf[40];
char max_adjust_format[40];
char min_adjust_format[40];
const char *pmax_adjust_format = NULL;
const char *pmin_adjust_format = NULL;
int min_str_len, max_str_len, value_str_len;
int32_t reg_value = 0;
bool is_float = stcRegInfo.is_float;
bool is_big_endian = stcRegInfo.is_big_endian;
MenuPack_RegisterValueRead(&stcRegInfo, buf_value, ARRAY_SIZE(buf_value));
if (is_big_endian)
{
reg_value = (buf_value[0] << 16) | buf_value[1];
}
else
{
reg_value = (buf_value[1] << 16) | buf_value[0];
}
if (strcmp(pscale, DEFAULT_EMPTY_STRING) != 0)
{
scale = atof(pscale);
}
if (is_float)
{
scale_value = (*(float *)&reg_value) * scale;
}
else
{
scale_value = MenuPack_GetScaleValue(scale, pformat, reg_value, stcRegInfo.reg_count);
}
value_str_len = snprintf(buf, sizeof(buf), pformat, scale_value);
const char *punit = NULL;
if (pmenu_info->info.normal.unit_index > 0 && pmenu_info->info.normal.unit_index < pinfo->pastcUnitPack->unit_count)
{
uint16_t unit_str_offset = pinfo->pastcUnitPack->uint_string_off[pmenu_info->info.normal.unit_index];
punit = MenuPack_GetStringFromOffset(pinfo, unit_str_offset);
punit = MenuPack_GetDisplayUnit(punit, pinfo, pmenu_info);
}
if (punit)
{
snprintf(buf + value_str_len, sizeof(buf) - value_str_len, " %s", punit);
}
if (pmenu_info->info.normal.limit_index > 0 && pmenu_info->info.normal.limit_index < pinfo->pastcLimitPack->limit_count)
{
struct TValueLimitItem *plimit_item = &pinfo->pastcLimitPack->items[pmenu_info->info.normal.limit_index];
if (plimit_item->max_string_off > 0)
{
const char *pstr_max = MenuPack_GetStringFromOffset(pinfo, plimit_item->max_string_off);
if (strstr(pstr_max, "#") == NULL)
{
float fmax_value = atof(pstr_max);
max_str_len = snprintf(max_adjust_format, sizeof(max_adjust_format), pformat, fmax_value);
if (max_str_len == value_str_len)
{
pmax_adjust_format = max_adjust_format;
}
}
else
{
max_str_len = strlen(pstr_max);
if (max_str_len == value_str_len)
{
pmax_adjust_format = pstr_max;
}
}
}
if (plimit_item->min_string_off > 0)
{
const char *pstr_min = MenuPack_GetStringFromOffset(pinfo, plimit_item->min_string_off);
if (strstr(pstr_min, "#") == NULL)
{
float fmin_value = atof(pstr_min);
min_str_len = snprintf(min_adjust_format, sizeof(min_adjust_format), pformat, fmin_value);
if (min_str_len == value_str_len)
{
pmin_adjust_format = min_adjust_format;
}
}
else
{
min_str_len = strlen(pstr_min);
if (min_str_len == value_str_len)
{
pmin_adjust_format = pstr_min;
}
}
}
}
int ret = MenuPack_ModifyDefault(modify_row, modify_col, buf, pmax_adjust_format, pmin_adjust_format);
if (ret)
{
scale_value = atof(buf);
if (is_float)
{
*(uint32_t *)&reg_value = scale_value / scale;
}
else
{
reg_value = round(scale_value / scale);
}
return MenuPack_RegisterValueWrite(&stcRegInfo, (void *)&reg_value);
}
return false;
}
int MenuPack_ModifyAlias(int modify_row, int modify_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info, int reg_addr_off)
{
int key = 0;
int alias_index = 0;
int32_t alias_value = 0;
const char *preg_addr_key_str = MenuPack_GetStringFromOffset(pinfo, pmenu_info->comm_str_offset);
TCommRegisterInfo stcRegInfo = MenuPack_UpdateCommInfo(preg_addr_key_str);
stcRegInfo.reg_addr += reg_addr_off;
MenuPack_RegisterValueRead(&stcRegInfo, (void *)&alias_value, sizeof(alias_value) / sizeof(uint16_t));
int alias_value_index = MenuPack_SearchAliasValueIndexMenuItem(pinfo, pmenu_info, alias_value);
if (alias_value_index < 0)
{
alias_value_index = 0;
//return alias_value;
}
alias_index = pmenu_info->info.alias.alias_index;
int start_index = pinfo->pastcAliasPack->items[alias_index].start_index;
int item_count = pinfo->pastcAliasPack->items[alias_index].alias_item_nums;
struct TAliasTable2Item *pitem2;
do
{
if (alias_value_index >= item_count)
{
alias_value_index = 0;
}
if (alias_value_index < 0)
{
alias_value_index = item_count - 1;
}
pitem2 = &pinfo->pastcAliasPack2->items[start_index + alias_value_index];
const char *palias_name = MenuPack_GetStringFromOffset(pinfo, pitem2->alias_string_off);
MenuPack_DisplayStringPos(modify_row, modify_col, DEFAULT_EMPTY_STRING);
MenuPack_DisplayStringPosSelect(modify_row, modify_col, palias_name);
MenuPack_DisplayFlush();
key = MenuPack_WaitKey(RT_TICK_PER_SECOND / 5);
switch (key)
{
case MENU_PACK_KEY_DOWN:
alias_value_index--;
break;
case MENU_PACK_KEY_UP:
case MENU_PACK_KEY_RESET_OR_UP:
alias_value_index++;
break;
case MENU_PACK_KEY_RIGHT:
case MENU_PACK_KEY_ENTER:
case MENU_PACK_KEY_ENTER_OR_RIGHT:
key = MENU_PACK_KEY_ENTER;
break;
default:
break;
}
} while (key != MENU_PACK_KEY_ENTER && key != MENU_PACK_KEY_ESCAPE);
if (key == MENU_PACK_KEY_ENTER)
{
if (alias_value != pitem2->value)
{
alias_value = pitem2->value;
return MenuPack_RegisterValueWrite(&stcRegInfo, (void *)&alias_value);
}
}
return false;
}
static int MenuPack_ModifyStringBuf(int modify_row, int modify_col, char *buf, int key, int *psel_bit)
{
int len;
int sel_bit;
len = strlen(buf);
sel_bit = *psel_bit;
switch (key)
{
case MENU_PACK_KEY_UP:
case MENU_PACK_KEY_RESET_OR_UP:
if (sel_bit == 0)
{
if (buf[sel_bit] == '+')
{
buf[sel_bit] = '-';
}
else if (buf[sel_bit] == '-')
{
buf[sel_bit] = '+';
}
}
MenuPack_AdjustModifyBuf(buf, sel_bit, 1);
break;
case MENU_PACK_KEY_DOWN:
if (sel_bit == 0)
{
if (buf[sel_bit] == '+')
{
buf[sel_bit] = '-';
}
else if (buf[sel_bit] == '-')
{
buf[sel_bit] = '+';
}
}
MenuPack_AdjustModifyBuf(buf, sel_bit, -1);
break;
case MENU_PACK_KEY_0:
case MENU_PACK_KEY_1:
case MENU_PACK_KEY_2:
case MENU_PACK_KEY_3:
case MENU_PACK_KEY_4:
case MENU_PACK_KEY_5:
case MENU_PACK_KEY_6:
case MENU_PACK_KEY_7:
case MENU_PACK_KEY_8:
case MENU_PACK_KEY_9:
buf[sel_bit] = key;
sel_bit = menu_pack_search_next_digit_bit(buf, sel_bit);
break;
case MENU_PACK_KEY_DOT:
sel_bit = menu_pack_search_next_digit_bit_after_dot(buf, sel_bit);
break;
case MENU_PACK_KEY_RIGHT:
case MENU_PACK_KEY_ENTER_OR_RIGHT:
while (sel_bit < len)
{
sel_bit++;
if (isdigit(buf[sel_bit]))
{
break;
}
}
if (key == MENU_PACK_KEY_RIGHT)
{
if (sel_bit == len)
{
sel_bit = len - 1;
}
}
if (sel_bit == len)
{
key = MENU_PACK_KEY_ENTER;
}
break;
case MENU_PACK_KEY_END:
key = MENU_PACK_KEY_ENTER;
break;
case MENU_PACK_KEY_LEFT:
while (sel_bit > 0)
{
sel_bit--;
if (isdigit(buf[sel_bit]))
{
break;
}
}
break;
}
*psel_bit = sel_bit;
return key;
}
const char *MenuPack_GetStringFromOffset(const TMenuPackFileInfo *pinfo, uint16_t offset)
{
if (offset < pinfo->pastcStringPack->table_string_size)
{
return (const char *)&pinfo->pastcStringPack->table_string[offset];
}
return DEFAULT_EMPTY_STRING;
}
static const char *MenuPack_GetStringScale(const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info)
{
uint16_t offset = 0;
if (pmenu_info->info.common.type == MENU_ITEM_NORMAL)
{
uint16_t scale_format_index = pmenu_info->info.normal.scale_format_index;
if (scale_format_index < pinfo->pastcFormatPack->scale_format_count)
{
offset = pinfo->pastcFormatPack->items[scale_format_index].scale_string_off;
}
}
return MenuPack_GetStringFromOffset(pinfo, offset);
}
static const char *MenuPack_GetStringFormat(const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info)
{
uint16_t offset = 0;
if (pmenu_info->info.common.type == MENU_ITEM_NORMAL)
{
uint16_t scale_format_index = pmenu_info->info.normal.scale_format_index;
if (scale_format_index < pinfo->pastcFormatPack->scale_format_count)
{
offset = pinfo->pastcFormatPack->items[scale_format_index].format_string_off;
}
}
return MenuPack_GetStringFromOffset(pinfo, offset);
}
#if MENU_PACK_ALIAS_ITEM_SORT > 0
int MenuPack_SearchAliasValueIndex(const TMenuPackFileInfo *pinfo, int alias_index, uint16_t alias_value)
{
if (alias_index < pinfo->pastcAliasPack->table_count)
{
struct TAliasTableItem *pitem = &pinfo->pastcAliasPack->items[alias_index];
struct TAliasTable2Item *pitem_mid;
if (pitem->start_index < pinfo->pastcAliasPack2->table_count && pitem->start_index + pitem->alias_item_nums <= pinfo->pastcAliasPack2->table_count)
{
int left = 0;
int right = pitem->alias_item_nums - 1;
int mid;
while (left <= right)
{
mid = (left + right) / 2;
pitem_mid = &pinfo->pastcAliasPack2->items[pitem->start_index + mid];
if (pitem_mid->value < alias_value)
{
left = mid + 1;
}
else if (pitem_mid->value > alias_value)
{
right = mid - 1;
}
else
{
break;
}
}
if (left > right)
{
return -1;
}
return mid;
}
}
return -1;
}
#else
int MenuPack_SearchAliasValueIndex(const TMenuPackFileInfo *pinfo, int alias_index, uint16_t alias_value)
{
if (alias_index < pinfo->pastcAliasPack->table_count)
{
struct TAliasTableItem *pitem = &pinfo->pastcAliasPack->items[alias_index];
if (pitem->start_index < pinfo->pastcAliasPack2->table_count && pitem->start_index + pitem->alias_item_nums <= pinfo->pastcAliasPack2->table_count)
{
for (int i = 0; i < pitem->alias_item_nums; i++)
{
struct TAliasTable2Item *pitem2 = &pinfo->pastcAliasPack2->items[pitem->start_index + i];
if (pitem2->value == alias_value)
{
return i;
}
}
}
}
return -1;
}
#endif
static int MenuPack_SearchAliasValueIndexMenuItem(const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info, uint16_t alias_value)
{
if (pmenu_info->info.common.type == MENU_ITEM_ALIAS)
{
uint16_t alias_index = pmenu_info->info.alias.alias_index;
return MenuPack_SearchAliasValueIndex(pinfo, alias_index, alias_value);
}
return -1;
}
int MenuPack_SearchMenuIndex(const TMenuPackFileInfo *pinfo, const char *pstr_menu_name)
{
struct TMenuDescriptionInfo *pdesc;
struct TMenuDescriptionItem *pdesc_item;
int i;
const char *pstr_menu;
pdesc = pinfo->pastcMenuDescriptionInfo;
for (i = 0; i < pdesc->item_count; i++)
{
pdesc_item = &pdesc->items[i];
pstr_menu = MenuPack_GetStringFromOffset(pinfo, pdesc_item->menu_name_str_offset);
if (strcmp(pstr_menu, pstr_menu_name) == 0)
{
//menu name string match
return i;
}
}
return -1;
}
int MenuPack_SearchAliasIndex(const TMenuPackFileInfo *pinfo, const char *alias_name)
{
int alias_index;
const char *pstr;
pstr = MenuPack_GetStringFromOffset(pinfo, 0);
for (alias_index = 0; alias_index < pinfo->pastcAliasPack->table_count; alias_index++)
{
pstr = pstr + strlen(pstr) + 1; //first string is empty sring
if (strcmp(pstr, alias_name) == 0)
{
return alias_index;;
}
}
return -1;
}
const char *MenuPack_GetStringAlias(const TMenuPackFileInfo *pinfo, int alias_index, int16_t alias_value)
{
uint16_t offset = 0;
static char buf[12];
int alias_value_index = MenuPack_SearchAliasValueIndex(pinfo, alias_index, alias_value);
const char *pstr_alias;
if (alias_value_index >= 0)
{
struct TAliasTableItem *pitem = &pinfo->pastcAliasPack->items[alias_index];
struct TAliasTable2Item *pitem2 = &pinfo->pastcAliasPack2->items[pitem->start_index + alias_value_index];
offset = pitem2->alias_string_off;
}
pstr_alias = MenuPack_GetStringFromOffset(pinfo, offset);
if (pstr_alias == NULL || strcmp(pstr_alias, DEFAULT_EMPTY_STRING) == 0)
{
snprintf(buf, sizeof(buf), "(%d)", alias_value);
pstr_alias = buf;
}
return pstr_alias;
}
const char *MenuPack_MenuItemGetStringAlias(const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info, int16_t alias_value)
{
uint16_t alias_index = pmenu_info->info.alias.alias_index;
return MenuPack_GetStringAlias(pinfo, alias_index, alias_value);
}
#define ROUND_VALUE_INCREASE(value, inc, max_value) \
value += inc; \
if (value >= max_value) \
{ \
value = value - max_value; \
}
#define ROUND_VALUE_DECREASE(value, inc, max_value) \
value -= inc; \
if (value < 0) \
{ \
value = max_value - 1; \
}
static void MenuPack_UpdateIpBuffer(char *buf, int buf_size, uint32_t ip_addr)
{
snprintf(buf, buf_size, "%03d.%03d.%03d.%03d", (ip_addr & 0xFF), (ip_addr >> 8) & 0xFF, (ip_addr >> 16) & 0xFF, (ip_addr >> 24) & 0xFF);
}
static void MenuPack_UpdateDateBuffer(char *buf, int buf_size, uint16_t year_mon_day[3])
{
int year = year_mon_day[0];
int month = year_mon_day[1];
int day = year_mon_day[2];
snprintf(buf, buf_size, "%04d-%02d-%02d", year, month, day);
}
static void MenuPack_UpdateTimeBuffer(char *buf, int buf_size, uint16_t hour_min_sec[3])
{
int hour = hour_min_sec[0];
int minute = hour_min_sec[1];
int second = hour_min_sec[2];
snprintf((char *)buf, buf_size, "%02d:%02d:%02d", hour, minute, second);
}
bool MenuPack_ModifyDefault(int modify_row, int modify_col, char *buf, const char *max_format, const char *min_format)
{
int sel_bit = 0;
int key = 0;
int bit_adjust = 0;
do
{
key = MenuPack_WaitKey(RT_TICK_PER_SECOND / 5);
key = MenuPack_ModifyStringBuf(modify_row, modify_col, buf, key, &sel_bit);
if (max_format)
{
MenuPack_AdjustModifyBufLimit(buf, max_format, sel_bit, ADJUST_MAX, key);
}
if (min_format)
{
MenuPack_AdjustModifyBufLimit(buf, min_format, sel_bit, ADJUST_MIN, key);
}
MenuPack_DisplayModifyString(modify_row, modify_col, buf, sel_bit);
MenuPack_ModifyBufCallBack(buf);
MenuPack_DisplayFlush();
} while (key != MENU_PACK_KEY_ENTER && key != MENU_PACK_KEY_ESCAPE);
if (key == MENU_PACK_KEY_ENTER)
{
return true;
}
return false;
}
static void MenuPack_DisplayIpAddr(int disp_row, int disp_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info)
{
char buf[40];
const char *preg_addr_key_str = MenuPack_GetStringFromOffset(pinfo, pmenu_info->comm_str_offset);
uint32_t value = 0;
TCommRegisterInfo stcRegInfo = MenuPack_UpdateCommInfo(preg_addr_key_str);
MenuPack_RegisterValueRead(&stcRegInfo, (void *)&value, sizeof(value) / sizeof(uint16_t));
MenuPack_UpdateIpBuffer(buf, sizeof(buf), value);
MenuPack_DisplayStringPos(disp_row, disp_col, buf);
}
static void MenuPack_DisplayPassword(int disp_row, int disp_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info)
{
MenuPack_DisplayStringPos(disp_row, disp_col, "****");
}
static int MenuPack_GetDigitBufferStartBit(const char *buf, int sel_bit)
{
int len = strlen(buf);
int start_bit = sel_bit;
char c, c1;
if (start_bit >= len)
{
start_bit = len - 1;
}
while (start_bit > 0)
{
c = buf[start_bit];
c1 = buf[start_bit - 1];
if (isdigit(c) && (isdigit(c1) || c1 == '.'))
{
start_bit--;
if (c1 == '.')
{
start_bit--;
}
}
else
{
break;
}
}
return start_bit;
}
static int MenuPack_GetDigitBufferEndBit(const char *buf, int sel_bit)
{
int len = strlen(buf);
int end_bit = sel_bit;
char c, c1;
if (end_bit >= len)
{
end_bit = len - 1;
}
while (end_bit < len)
{
c = buf[end_bit];
c1 = buf[end_bit + 1];
if (isdigit(c) && (isdigit(c1) || c1 == '.'))
{
end_bit++;
if (c1 == '.')
{
end_bit++;
}
}
else
{
break;
}
}
return end_bit;
}
static float MenuPack_GetBufferValue(const char *buf, int sel_bit)
{
int start_bit = MenuPack_GetDigitBufferStartBit(buf, sel_bit);
return atof(buf + start_bit);
}
void MenuPack_AdjustModifyBuf(char *buf, int sel_bit, int bit_adjust)
{
int adjust_higher_bit = 0;
if (sel_bit >= 0)
{
if (isdigit(buf[sel_bit]))
{
buf[sel_bit] += bit_adjust;
if (buf[sel_bit] > '9')
{
buf[sel_bit] = '0';
adjust_higher_bit = 1;
}
if (buf[sel_bit] < '0')
{
buf[sel_bit] = '9';
adjust_higher_bit = 1;
}
}
if (buf[sel_bit] == '.' || buf[sel_bit] == '<')
{
adjust_higher_bit = 1;
}
#if ADJUST_HIGHER_BIT > 0
if (adjust_higher_bit)
{
MenuPack_AdjustModifyBuf(buf, sel_bit - 1, bit_adjust);
}
#endif
}
}
static void MenuPack_AdjustModifyBufLimit(char *buf, const char *format, int sel_bit, EMinMaxAdjust mode, int key)
{
char buf2[40] = {0};
int i;
strncpy(buf2, buf, sizeof(buf2));
for (i = 0; i < sizeof(buf2); i++)
{
if (format[i] == '\0')
{
break;
}
else if (buf2[i] == '.' && format[i] != '.')
{
buf2[i] = ' ';
}
else if (buf2[i] == ' ' && format[i] == '<')
{
buf2[i] = '<';
}
}
float limit_value = MenuPack_GetBufferValue(format, sel_bit);
float cur_value = MenuPack_GetBufferValue(buf2, sel_bit);
int start_bit = MenuPack_GetDigitBufferStartBit(buf2, sel_bit);
int end_bit = MenuPack_GetDigitBufferEndBit(buf2, sel_bit);
if ((mode == ADJUST_MAX && cur_value > limit_value) || (mode == ADJUST_MIN && cur_value < limit_value))
{
for (i = start_bit; i <= end_bit; i++)
{
if (isdigit(format[i]))
{
buf2[i] = format[i];
}
}
}
for (i = 0; i < sizeof(buf2); i++)
{
if (buf[i] == '\0')
{
break;
}
else if (buf[i] != '.')
{
buf[i] = buf2[i];
}
}
}
static bool MenuPack_ModifyPassword(int modify_row, int modify_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info)
{
MenuPack_InputPassword(pinfo, NULL);
MenuPack_DispMenu(pinfo);
if (MenuPack_CheckPasswordSuccess(pinfo))
{
return MenuPack_ModifyNormal(modify_row, modify_col, pinfo, pmenu_info, 0);
}
return true;
}
static bool MenuPack_ModifyIpAddr(int disp_row, int disp_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info)
{
unsigned value;
char buf[40];
int a, b, c, d;
const char *max_adjust_format = "255#255#255#255";
const char *preg_addr_key_str = MenuPack_GetStringFromOffset(pinfo, pmenu_info->comm_str_offset);
TCommRegisterInfo stcRegInfo = MenuPack_UpdateCommInfo(preg_addr_key_str);
value = 0;
MenuPack_RegisterValueRead(&stcRegInfo, (void *)&value, sizeof(value) / sizeof(uint16_t));
MenuPack_UpdateIpBuffer(buf, sizeof(buf), value);
bool is_success = MenuPack_ModifyDefault(disp_row, disp_col, buf, max_adjust_format, NULL);
if (!is_success)
{
return false;
}
a = (value & 0xFF);
b = (value >> 8) & 0xFF;
c = (value >> 16) & 0xFF;
d = (value >> 24) & 0xFF;
sscanf(buf, "%03d.%03d.%03d.%03d", &a, &b, &c, &d);
value = a | (b << 8) | (c << 16) | (d << 24);
return MenuPack_RegisterValueWrite(&stcRegInfo, (void *)&value);
}
static void MenuPack_DisplaySystemDate(int disp_row, int disp_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info)
{
char buf[40];
uint16_t year_mon_day_buf[3] = {0};
const char *preg_addr_key_str = MenuPack_GetStringFromOffset(pinfo, pmenu_info->comm_str_offset);
TCommRegisterInfo stcRegInfo = MenuPack_UpdateCommInfo(preg_addr_key_str);
MenuPack_RegisterValueRead(&stcRegInfo, (void *)year_mon_day_buf, ARRAY_SIZE(year_mon_day_buf));
MenuPack_UpdateDateBuffer(buf, sizeof(buf), year_mon_day_buf);
MenuPack_DisplayStringPos(disp_row, disp_col, buf);
}
static bool MenuPack_ModifySystemDate(int modify_row, int modify_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info)
{
char buf[40];
int year = 0, mon = 0, day = 0;
const char *max_adjust_format = "9999#12#31";
const char *min_adjust_format = "1970#01#01";
uint16_t year_mon_day_buf[3] = {0};
const char *preg_addr_key_str = MenuPack_GetStringFromOffset(pinfo, pmenu_info->comm_str_offset);
TCommRegisterInfo stcRegInfo = MenuPack_UpdateCommInfo(preg_addr_key_str);
MenuPack_RegisterValueRead(&stcRegInfo, (void *)year_mon_day_buf, ARRAY_SIZE(year_mon_day_buf));
MenuPack_UpdateDateBuffer(buf, sizeof(buf), year_mon_day_buf);
bool is_success = MenuPack_ModifyDefault(modify_row, modify_col, buf, max_adjust_format, min_adjust_format);
if (!is_success)
{
return false;
}
sscanf(buf, "%04d-%02d-%02d", &year, &mon, &day);
year_mon_day_buf[0] = year;
year_mon_day_buf[1] = mon;
year_mon_day_buf[2] = day;
MenuPack_RegisterValueWrite(&stcRegInfo, (void *)year_mon_day_buf);
return true;
}
static void MenuPack_DisplaySystemTime(int modify_row, int modify_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info)
{
char buf[40];
uint16_t hour_min_sec[3] = {0};
const char *preg_addr_key_str = MenuPack_GetStringFromOffset(pinfo, pmenu_info->comm_str_offset);
TCommRegisterInfo stcRegInfo = MenuPack_UpdateCommInfo(preg_addr_key_str);
MenuPack_RegisterValueRead(&stcRegInfo, (void *)hour_min_sec, ARRAY_SIZE(hour_min_sec));
MenuPack_UpdateTimeBuffer(buf, sizeof(buf), hour_min_sec);
MenuPack_DisplayStringPos(modify_row, modify_col, buf);
}
static bool MenuPack_ModifySystemTime(int modify_row, int modify_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info)
{
char buf[40];
uint16_t hour_min_sec[3] = {0};
const char *preg_addr_key_str = MenuPack_GetStringFromOffset(pinfo, pmenu_info->comm_str_offset);
TCommRegisterInfo stcRegInfo = MenuPack_UpdateCommInfo(preg_addr_key_str);
MenuPack_RegisterValueRead(&stcRegInfo, (void *)hour_min_sec, ARRAY_SIZE(hour_min_sec));
MenuPack_UpdateTimeBuffer(buf, sizeof(buf), hour_min_sec);
const char *max_adjust_format = "23<59<59";
int hour = hour_min_sec[0];
int minute = hour_min_sec[1];
int second = hour_min_sec[2];
bool is_success = MenuPack_ModifyDefault(modify_row, modify_col, buf, max_adjust_format, NULL);
if (!is_success)
{
return false;
}
sscanf(buf, "%02d:%02d:%02d", &hour, &minute, &second);
hour_min_sec[0] = hour;
hour_min_sec[1] = minute;
hour_min_sec[2] = second;
MenuPack_RegisterValueWrite(&stcRegInfo, (void *)hour_min_sec);
return true;
}
const char *MenuPack_GetDisplayAliasString(const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info, int reg_addr_off)
{
const char *preg_addr_key_str = MenuPack_GetStringFromOffset(pinfo, pmenu_info->comm_str_offset);
TCommRegisterInfo stcRegInfo = MenuPack_UpdateCommInfo(preg_addr_key_str);
uint16_t alias_value = 0;
stcRegInfo.reg_addr += reg_addr_off;
MenuPack_RegisterValueRead(&stcRegInfo, (void *)&alias_value, sizeof(alias_value) / sizeof(uint16_t));
const char *palias_str = MenuPack_MenuItemGetStringAlias(pinfo, pmenu_info, alias_value);
return palias_str;
}
void MenuPack_DisplayAlias(int disp_row, int disp_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info, int reg_addr_off)
{
const char *palias_str = MenuPack_GetDisplayAliasString(pinfo, pmenu_info, reg_addr_off);
MenuPack_DisplayStringPos(disp_row, disp_col, palias_str);
}
void MenuPack_GetDisplayNormalString(const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info, int reg_addr_off, char *pbuf, int buf_size)
{
const char *pformat = MenuPack_GetStringFormat(pinfo, pmenu_info);
const char *preg_addr_key_str = MenuPack_GetStringFromOffset(pinfo, pmenu_info->comm_str_offset);
TCommRegisterInfo stcRegInfo = MenuPack_UpdateCommInfo(preg_addr_key_str);
stcRegInfo.reg_addr += reg_addr_off;
uint32_t reg_value = 0;
MenuPack_RegisterValueRead(&stcRegInfo, (void *)&reg_value, sizeof(reg_value) / sizeof(uint16_t));
const char *pscale = MenuPack_GetStringScale(pinfo, pmenu_info);
double scale = 1.0;
if (strcmp(pscale, DEFAULT_EMPTY_STRING) != 0)
{
scale = atof(pscale);
}
double scale_value = MenuPack_GetScaleValue(scale, pformat, reg_value, stcRegInfo.reg_count);
int len = snprintf(pbuf, buf_size, pformat, scale_value);
const char *punit = NULL;
if (pmenu_info->info.normal.unit_index > 0 && pmenu_info->info.normal.unit_index < pinfo->pastcUnitPack->unit_count)
{
uint16_t unit_str_offset = pinfo->pastcUnitPack->uint_string_off[pmenu_info->info.normal.unit_index];
punit = MenuPack_GetStringFromOffset(pinfo, unit_str_offset);
punit = MenuPack_GetDisplayUnit(punit, pinfo, pmenu_info);
}
if (punit)
{
snprintf(pbuf + len, buf_size - len, " %s", punit);
}
}
void MenuPack_DisplayNormal(int disp_row, int disp_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info, int reg_addr_off)
{
char buf[60];
MenuPack_GetDisplayNormalString(pinfo, pmenu_info, reg_addr_off, buf, sizeof(buf));
MenuPack_DisplayStringPos(disp_row, disp_col, buf);
}
const struct TMenuDescriptionItem *MenuPack_MenuIndexDescription(const TMenuPackFileInfo *pinfo, int menu_index)
{
if (menu_index > 0 && menu_index < pinfo->pastcMenuDescriptionInfo->item_count)
{
struct TMenuDescriptionItem *pdesc_item = &pinfo->pastcMenuDescriptionInfo->items[menu_index];
if (pdesc_item->menu_index == menu_index)
{
return pdesc_item;
}
}
return NULL;
}
const struct TMenuDescriptionItem* MenuPack_SearchMenuDescription(const TMenuPackFileInfo *pinfo)
{
int menu_index;
TMenuPackLevel *pmenu_level;
pmenu_level = MenuPack_GetActiveLevel(pinfo);
if (!pmenu_level)
{
return NULL;
}
menu_index = pmenu_level->menu_index;
return MenuPack_MenuIndexDescription(pinfo, menu_index);
}
int MenuPack_GetSelectItemIndex(const TMenuPackFileInfo *pinfo)
{
TMenuPackLevel *pmenu_level;
if (!pinfo->pstcPackHeader)
{
return 0;
}
pmenu_level = MenuPack_GetActiveLevel(pinfo);
if (!pmenu_level)
{
return 0;
}
return pmenu_level->item_select;
}
static int MenuPack_GetActiveMenuIndex(const TMenuPackFileInfo *pinfo)
{
TMenuPackLevel *pmenu_level;
int menu_index = -1;
pmenu_level = MenuPack_GetActiveLevel(pinfo);
if (pmenu_level != NULL)
{
menu_index = pmenu_level->menu_index;
}
return menu_index;
}
static int MenuPack_GetMenuItemNums(const TMenuPackFileInfo *pinfo, int menu_index)
{
if (menu_index > 0 && menu_index < pinfo->pastcMenuPack->item_count)
{
const struct TMenuPackItem *pitem = &pinfo->pastcMenuPack->items[menu_index];
return pitem->menu_items;
}
return 0;
}
void MenuPack_DisplayItem(int disp_row, int disp_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info, int reg_addr_off)
{
if (pmenu_info->info.common.type == MENU_ITEM_ALIAS)
{
MenuPack_DisplayStringPosSelect(disp_row, disp_col, DEFAULT_EMPTY_STRING);
MenuPack_DisplayAlias(disp_row, disp_col, pinfo, pmenu_info, reg_addr_off);
}
else if (pmenu_info->info.common.type == MENU_ITEM_NORMAL)
{
MenuPack_DisplayStringPosSelect(disp_row, disp_col, DEFAULT_EMPTY_STRING);
MenuPack_DisplayNormal(disp_row, disp_col, pinfo, pmenu_info, reg_addr_off);
}
}
int MenuPack_ModifyItem(int modify_row, int modify_col, const TMenuPackFileInfo *pinfo, const struct TMenuItemInfo *pmenu_info, int reg_addr_off)
{
if (pmenu_info->info.common.type == MENU_ITEM_ALIAS || pmenu_info->info.common.type == MENU_ITEM_NORMAL)
{
if (!MenuPack_CheckPasswordSuccess(pinfo))
{
MenuPack_InputPassword(pinfo, NULL);
MenuPack_DispMenu(pinfo);
}
if (MenuPack_CheckPasswordSuccess(pinfo))
{
if (pmenu_info->info.common.type == MENU_ITEM_ALIAS)
{
return MenuPack_ModifyAlias(modify_row, modify_col, pinfo, pmenu_info, reg_addr_off);
}
else
{
return MenuPack_ModifyNormal(modify_row, modify_col, pinfo, pmenu_info, reg_addr_off);
}
}
}
return false;
}
int Menu_ItemSelectRow = -1;
void MenuPack_SelectItem(const TMenuPackFileInfo *pinfo, int item_select_row)
{
Menu_ItemSelectRow = item_select_row;
MenuPack_DispMenu(pinfo);
Menu_ItemSelectRow = -1;
}
void MenuPack_ExecuteSelectItem(const TMenuPackFileInfo *pinfo)
{
MenuPack_ProcessMenu(pinfo, MENU_PACK_KEY_ENTER);
}
void MenuPack_DispMenu(const TMenuPackFileInfo *pinfo)
{
const struct TMenuItemInfo *pmenu_start = NULL;
const struct TMenuItemInfo *pmenu_end = NULL;
const struct TMenuItemInfo *pmenu_info;
const struct TMenuPackItem *pitem;
int start_index, end_index;
int disp_row;
int disp_col;
int menu_index_offset;
const char *ptitle_str;
TMenuPackLevel *pmenu_level;
int menu_index;
int action_index = 0;
const struct TMenuDescriptionItem * pdesc_item;
if (!pinfo->pstcPackHeader)
{
return;
}
const char *pstr_menu = DEFAULT_EMPTY_STRING;
for (int i = 0; i < 2; i++)
{
menu_index = MenuPack_GetActiveMenuIndex(pinfo);
pdesc_item = MenuPack_MenuIndexDescription(pinfo, menu_index);
if (pdesc_item == NULL)
{
MenuPack_EnterMainMenu(pinfo);
continue;
}
pstr_menu = MenuPack_GetStringFromOffset(pinfo, pdesc_item->menu_name_str_offset);
MenuPack_BeforeDisplayMenu(pinfo, pstr_menu, menu_index);
if (menu_index == MenuPack_GetActiveMenuIndex(pinfo))
{
break;
}
}
start_index = 0;
end_index = 0;
if ((unsigned)menu_index >= pinfo->pastcMenuPack->item_count || menu_index == 0)
{
return;
}
pitem = &pinfo->pastcMenuPack->items[menu_index];
if (pitem->menu_start_index < pinfo->pastMenuPack2->item_count &&
pitem->menu_start_index + pitem->menu_items <= pinfo->pastMenuPack2->item_count)
{
start_index = pitem->menu_start_index;
end_index = pitem->menu_start_index + pitem->menu_items;
}
pmenu_start = &pinfo->pastMenuPack2->items[start_index];
pmenu_end = &pinfo->pastMenuPack2->items[end_index];
const struct TMenuItemInfo *pmenu_info_select;
bool is_select_match;
bool is_info_visible;
pmenu_level = MenuPack_GetActiveLevel(pinfo);
retry_search:
if (pmenu_level->item_select < 0)
{
pmenu_level->item_select = pitem->menu_items - 1;
}
if (pmenu_level->item_select >= pitem->menu_items)
{
pmenu_level->item_select = 0;
pmenu_level->item_display_start = 0;
}
if (pmenu_level->item_display_start > pmenu_level->item_select)
{
pmenu_level->item_display_start = pmenu_level->item_select;
}
pmenu_info = pmenu_start + pmenu_level->item_display_start;
pmenu_info_select = pmenu_start + pmenu_level->item_select;
is_select_match = false;
disp_row = 0;
disp_col = 0;
menu_index_offset = 0;
while (pmenu_info < pmenu_end)
{
is_info_visible = MenuPack_CheckVisible(pinfo, pmenu_info);
if (is_info_visible)
{
if (Menu_ItemSelectRow >= 0 && Menu_ItemSelectRow == disp_row)
{
pmenu_level->item_select = pmenu_level->item_display_start + menu_index_offset;
Menu_ItemSelectRow = -1;
goto retry_search;
}
disp_row++;
}
menu_index_offset++;
if (pmenu_info == pmenu_info_select)
{
is_select_match = true;
if (!is_info_visible)
{
if (pmenu_level->item_select_adjust > 0)
{
ROUND_VALUE_INCREASE(pmenu_level->item_select, 1, pitem->menu_items);
}
else
{
ROUND_VALUE_DECREASE(pmenu_level->item_select, 1, pitem->menu_items);
}
goto retry_search;
}
}
if (disp_row >= pdesc_item->max_menu_item)
{
if (!is_select_match)
{
ROUND_VALUE_INCREASE(pmenu_level->item_display_start, 1, pitem->menu_items);
goto retry_search;
}
break;
}
pmenu_info++;
}
if (!is_select_match && pmenu_info < pmenu_end)
{
ROUND_VALUE_INCREASE(pmenu_level->item_display_start, 1, pitem->menu_items);
goto retry_search;
}
pmenu_info = pmenu_start + pmenu_level->item_display_start;
pmenu_info_select = pmenu_start + pmenu_level->item_select;
if (pdesc_item != NULL)
{
int prev_menu_index = pdesc_item->prev_menu_index;
int next_menu_index = pdesc_item->next_menu_index;
MenuPack_DisplayPage(pdesc_item->display_page);
ptitle_str = MenuPack_GetStringFromOffset(pinfo, pdesc_item->description_str_off);
MenuPack_DisplayTitleString(ptitle_str);
const struct TMenuDescriptionItem *pdesc_item_prev = MenuPack_MenuIndexDescription(pinfo, prev_menu_index);
if (pdesc_item_prev)
{
const char *ptitle_str_prev;
ptitle_str_prev = MenuPack_GetStringFromOffset(pinfo, pdesc_item_prev->description_str_off);
if (strcmp(ptitle_str_prev, ptitle_str) == 0)
{
MenuPack_DisplayPrevTitleString(DEFAULT_EMPTY_STRING);
}
else
{
MenuPack_DisplayPrevTitleString(ptitle_str_prev);
}
}
const struct TMenuDescriptionItem *pdesc_item_next = MenuPack_MenuIndexDescription(pinfo, next_menu_index);
if (pdesc_item_next)
{
const char *ptitle_str_next;
ptitle_str_next = MenuPack_GetStringFromOffset(pinfo, pdesc_item_next->description_str_off);
if (strcmp(ptitle_str_next, ptitle_str) == 0)
{
MenuPack_DisplayNextTitleString(DEFAULT_EMPTY_STRING);
}
else
{
MenuPack_DisplayNextTitleString(ptitle_str_next);
}
}
}
disp_row = 0;
while (pmenu_info < pmenu_end)
{
is_info_visible = MenuPack_CheckVisible(pinfo, pmenu_info);
if (is_info_visible)
{
const char *pname;
disp_col = 0;
pname = MenuPack_GetStringFromOffset(pinfo, pmenu_info->name_offset);
if (pmenu_info == pmenu_info_select)
{
pmenu_level->select_row = disp_row;
MenuPack_DisplayStringPos(disp_row, disp_col, DEFAULT_EMPTY_STRING);
MenuPack_DisplayStringPosSelect(disp_row, disp_col, pname);
}
else
{
MenuPack_DisplayStringPosSelect(disp_row, disp_col, DEFAULT_EMPTY_STRING);
MenuPack_DisplayStringPos(disp_row, disp_col, pname);
}
disp_col = 1;
action_index = pmenu_info->info.common.action_index;
if (action_index > 0 && action_index < pinfo->pastcActionPack->action_count)
{
uint16_t action_str_offset = pinfo->pastcActionPack->action_string_off[action_index];
const char *pstr_action = MenuPack_GetStringFromOffset(pinfo, action_str_offset);
if (strcmp(pstr_action, "ip") == 0)
{
MenuPack_DisplayIpAddr(disp_row, disp_col, pinfo, pmenu_info);
}
else if (strcmp(pstr_action, "date") == 0)
{
MenuPack_DisplaySystemDate(disp_row, disp_col, pinfo, pmenu_info);
}
else if (strcmp(pstr_action, "time") == 0)
{
MenuPack_DisplaySystemTime(disp_row, disp_col, pinfo, pmenu_info);
}
else if (strcmp(pstr_action, "password") == 0)
{
MenuPack_DisplayPassword(disp_row, disp_col, pinfo, pmenu_info);
}
else
{
MenuPack_DisplayDefaultAction(disp_row, disp_col, pinfo, pmenu_info, pstr_action);
}
}
else if (pmenu_info->info.common.type == MENU_ITEM_ALIAS || pmenu_info->info.common.type == MENU_ITEM_NORMAL)
{
MenuPack_DisplayItem(disp_row, disp_col, pinfo, pmenu_info, 0);
}
else if (pmenu_info->info.common.type == MENU_ITEM_SUB_MENU)
{
MenuPack_DisplayStringPosSelect(disp_row, disp_col, DEFAULT_EMPTY_STRING);
MenuPack_DisplayStringPos(disp_row, disp_col, DEFAULT_EMPTY_STRING);
MenuPack_DisplayStringPos(disp_row, disp_col + 1, "->");
}
MenuPack_MenuItemDisplay(pinfo, pmenu_info, disp_row);
disp_row++;
}
pmenu_info++;
}
while (disp_row < pdesc_item->max_menu_item)
{
disp_col = 0;
MenuPack_DisplayStringPos(disp_row, disp_col, DEFAULT_EMPTY_STRING);
MenuPack_DisplayStringPosSelect(disp_row, disp_col, DEFAULT_EMPTY_STRING);
disp_col = 1;
MenuPack_DisplayStringPos(disp_row, disp_col, DEFAULT_EMPTY_STRING);
MenuPack_DisplayStringPosSelect(disp_row, disp_col, DEFAULT_EMPTY_STRING);
MenuPack_MenuItemDisplay(pinfo, NULL, disp_row);
disp_row++;
}
MenuPack_AfterDisplayMenu(pinfo, pstr_menu, menu_index);
}
TMenuPackLevel *MenuPack_GetActiveLevel(const TMenuPackFileInfo *pinfo)
{
if ((unsigned)MenuPack_LayerIndex >= ARRAY_SIZE(MenuPack_Layer))
{
return NULL;
}
return &MenuPack_Layer[MenuPack_LayerIndex];
}
void MenuPack_EnterSubMenu(int sub_menu_index)
{
if (MenuPack_LayerIndex + 1 < MAX_PACK_LAYER)
{
MenuPack_LayerIndex++;
MenuPack_Layer[MenuPack_LayerIndex].item_select = 0;
MenuPack_Layer[MenuPack_LayerIndex].item_display_start = 0;
MenuPack_Layer[MenuPack_LayerIndex].select_row = 0;
MenuPack_Layer[MenuPack_LayerIndex].menu_index = sub_menu_index;
MenuPack_CommReinit();
}
}
void MenuPack_EnterMainMenu(const TMenuPackFileInfo *pinfo)
{
MenuPack_LayerIndex = -1;
MenuPack_EnterSubMenu(pinfo->pastcMenuPack->top_menu_index);
}
const struct TMenuItemInfo *MenuPack_GetSelectItem(const TMenuPackFileInfo *pinfo)
{
TMenuPackLevel *pmenu_level;
pmenu_level = MenuPack_GetActiveLevel(pinfo);
if (!pmenu_level)
{
return NULL;
}
return MenuPack_GetItem(pinfo, pmenu_level);
}
void MenuPack_ToUpperLayer(const TMenuPackFileInfo *pinfo, int key)
{
TMenuPackLevel *pmenu_level;
const struct TMenuItemInfo *pmenu_info = NULL;
if (MenuPack_LayerIndex >= 0)
{
MenuPack_LayerIndex--;
MenuPack_CommReinit();
pmenu_level = MenuPack_GetActiveLevel(pinfo);
if (pmenu_level)
{
pmenu_info = MenuPack_GetItem(pinfo, pmenu_level);
if (pmenu_info->info.common.type == MENU_ITEM_SUB_MENU)
{
MenuPack_ProcessFunc(MENU_PACK_AFTER_EXIT_SUB, pmenu_info, key);
}
}
}
}
void MenuPack_QuitToMainMenu(const TMenuPackFileInfo *pinfo)
{
TMenuPackLevel *pmenu_level;
do
{
MenuPack_ToUpperLayer(pinfo, 0);
pmenu_level = MenuPack_GetActiveLevel(pinfo);
} while (pmenu_level != NULL);
MenuPack_EnterMainMenu(pinfo);
}
static const struct TMenuItemInfo *MenuPack_GetItem(const TMenuPackFileInfo *pinfo, TMenuPackLevel *pmenu_level)
{
const struct TMenuItemInfo *pmenu_info = NULL;
if (pmenu_level->menu_index < pinfo->pastcMenuPack->item_count)
{
int start_index = pinfo->pastcMenuPack->items[pmenu_level->menu_index].menu_start_index;
if (start_index < pinfo->pastMenuPack2->item_count && start_index + pmenu_level->item_select < pinfo->pastMenuPack2->item_count)
{
pmenu_info = &pinfo->pastMenuPack2->items[start_index + pmenu_level->item_select];
}
}
return pmenu_info;
}
void MenuPack_ProcessMenu(const TMenuPackFileInfo *pinfo, int key)
{
const struct TMenuItemInfo *pmenu_info;
TMenuPackLevel *pmenu_level;
int action_index;
int menu_index;
const struct TMenuDescriptionItem *pdesc_item;
int menu_item_count;
bool is_password_ok;
const char *pstr_menu;
if (pinfo->pstcPackHeader == NULL)
{
return;
}
pmenu_level = MenuPack_GetActiveLevel(pinfo);
if (pmenu_level == NULL)
{
return;
}
menu_index = pmenu_level->menu_index;
pdesc_item = MenuPack_MenuIndexDescription(pinfo, menu_index);
pmenu_level = MenuPack_GetActiveLevel(pinfo);
if (pmenu_level == NULL)
{
return;
}
menu_index = pmenu_level->menu_index;
pstr_menu = MenuPack_GetStringFromOffset(pinfo, pdesc_item->menu_name_str_offset);
MenuPack_MenuActionProcess(pinfo, pstr_menu, menu_index, &key);
pmenu_info = MenuPack_GetItem(pinfo, pmenu_level);
const char *preg_addr_key_str = MenuPack_GetStringFromOffset(pinfo, pmenu_info->comm_str_offset);
MenuPack_ProcessFunc(MENU_PACK_KEY_PRESS, pmenu_info, key);
switch (key)
{
case MENU_PACK_KEY_HOME:
MenuPack_QuitToMainMenu(pinfo);
break;
case MENU_PACK_KEY_RESET_OR_UP:
case MENU_PACK_KEY_ESCAPE:
MenuPack_ToUpperLayer(pinfo, key);
break;
case MENU_PACK_KEY_ENTER_OR_RIGHT:
case MENU_PACK_KEY_ENTER:
is_password_ok = true;
if (pmenu_info->menu_property == MENU_PROP_ENGINEER)
{
uint16_t pass_word = 0;
MenuPack_InputPassword(pinfo, &pass_word);
if (pass_word != DEFAULT_ENGINEER_PASSWORD)
{
is_password_ok = false;
}
}
else if (pmenu_info->menu_property == MENU_PROP_READ_ONLY)
{
break;
}
if (is_password_ok == false)
{
break;
}
action_index = pmenu_info->info.common.action_index;
if (action_index > 0 && action_index < pinfo->pastcActionPack->action_count)
{
uint16_t action_str_offset = pinfo->pastcActionPack->action_string_off[action_index];
const char *pstr_action = MenuPack_GetStringFromOffset(pinfo, action_str_offset);
if (strcmp(pstr_action, "ip") == 0)
{
MenuPack_ModifyIpAddr(pmenu_level->select_row, 1, pinfo, pmenu_info);
}
else if (strcmp(pstr_action, "date") == 0)
{
MenuPack_ModifySystemDate(pmenu_level->select_row, 1, pinfo, pmenu_info);
}
else if (strcmp(pstr_action, "time") == 0)
{
MenuPack_ModifySystemTime(pmenu_level->select_row, 1, pinfo, pmenu_info);
}
else if (strcmp(pstr_action, "password") == 0)
{
MenuPack_ModifyPassword(pmenu_level->select_row, 1, pinfo, pmenu_info);
}
else
{
bool ret = MenuPack_ActionItemModify(pmenu_level->select_row, 1, pinfo, pmenu_info);
if (pmenu_info->info.common.type == MENU_ITEM_SUB_MENU && ret)
{
MenuPack_ProcessFunc(MENU_PACK_BEFORE_ENTER_SUB, pmenu_info, key);
MenuPack_EnterSubMenu(pmenu_info->info.sub_menu.sub_menu_index);
}
}
}
else if (pmenu_info->info.common.type == MENU_ITEM_SUB_MENU)
{
MenuPack_ProcessFunc(MENU_PACK_BEFORE_ENTER_SUB, pmenu_info, key);
MenuPack_EnterSubMenu(pmenu_info->info.sub_menu.sub_menu_index);
}
else if (pmenu_info->info.common.action_index == 0)
{
if (pmenu_info->info.common.type == MENU_ITEM_ALIAS || pmenu_info->info.common.type == MENU_ITEM_NORMAL)
{
if (!MenuPack_CheckPasswordSuccess(pinfo))
{
MenuPack_InputPassword(pinfo, NULL);
MenuPack_DispMenu(pinfo);
}
if (MenuPack_CheckPasswordSuccess(pinfo))
{
MenuPack_ModifyItem(pmenu_level->select_row, 1, pinfo, pmenu_info, 0);
}
}
}
break;
case MENU_PACK_KEY_UP:
pmenu_level->item_select_adjust = -1;
pmenu_level->item_select--;
break;
case MENU_PACK_KEY_DOWN:
pmenu_level->item_select_adjust = 1;
pmenu_level->item_select++;
break;
case MENU_PACK_KEY_PGDOWN:
pmenu_level->item_select_adjust = pdesc_item->max_menu_item;
pmenu_level->item_select += pmenu_level->item_select_adjust;
menu_item_count = MenuPack_GetMenuItemNums(pinfo, menu_index);
if (pmenu_level->item_select >= menu_item_count)
{
pmenu_level->item_select = 0;
}
pmenu_level->item_display_start = pmenu_level->item_select;
break;
case MENU_PACK_KEY_PGUP:
pmenu_level->item_select_adjust = -pdesc_item->max_menu_item;
pmenu_level->item_select -= pmenu_level->item_select_adjust;
if (pmenu_level->item_select < 0)
{
pmenu_level->item_select = 0;
}
pmenu_level->item_display_start = pmenu_level->item_select;
break;
case MENU_PACK_KEY_LEFT:
case MENU_PACK_KEY_RIGHT:
pdesc_item = MenuPack_MenuIndexDescription(pinfo, menu_index);
if (pdesc_item != NULL)
{
int prev_menu_index = pdesc_item->prev_menu_index;
int next_menu_index = pdesc_item->next_menu_index;
if (key == MENU_PACK_KEY_LEFT)
{
if (prev_menu_index > 0 && prev_menu_index != menu_index)
{
MenuPack_ToUpperLayer(pinfo, key);
MenuPack_EnterSubMenu(prev_menu_index);
MenuPack_BrotherMenuEnterCallBack(pinfo, prev_menu_index, MENU_PACK_KEY_LEFT);
}
}
else
{
if (next_menu_index > 0 && next_menu_index != menu_index)
{
MenuPack_ToUpperLayer(pinfo, key);
MenuPack_EnterSubMenu(next_menu_index);
MenuPack_BrotherMenuEnterCallBack(pinfo, next_menu_index, MENU_PACK_KEY_RIGHT);
}
}
}
break;
default:
break;
}
return;
}
TCommRegisterInfo MenuPack_UpdateCommInfo(const char *preg_addr_key_str)
{
TCommRegisterInfo result = {0};
uint32_t reg_addr = 0;
uint16_t reg_count = 1;
int8_t bit = -1;
if (strcmp(preg_addr_key_str, DEFAULT_EMPTY_STRING) == 0)
{
reg_count = 0;
}
reg_addr = atoi(preg_addr_key_str);
const char *pdot = strstr(preg_addr_key_str, ".");
if (pdot)
{
bit = atoi(pdot + 1);
}
const char *pcomma = strstr(preg_addr_key_str, "#");
if (pcomma)
{
reg_count = atoi(pcomma + 1);
}
result.reg_addr = reg_addr;
result.reg_count = reg_count;
result.bit = bit;
result.is_float = strstr(preg_addr_key_str, "#f") != NULL ? true : false;
result.is_big_endian = strstr(preg_addr_key_str, "#>") != NULL ? true : false;
return result;
}
int32_t MenuPack_SearchCommIndex(TMenuPackFileInfo *pinfo, TCommRegisterInfo *pstcCommReg)
{
int32_t comm_index = -1;
uint32_t reg_addr_limit_start;
uint32_t reg_addr_limit_end;
uint32_t reg_addr_start;
uint32_t reg_addr_end;
uint32_t reg_count;
if (pstcCommReg == NULL || pstcCommReg->reg_count == 0)
{
return comm_index;
}
for (int i = 0; i < pinfo->pastcCommPack->item_count; i++)
{
reg_addr_limit_start = pinfo->pastcCommPack->items[i].reg_start;
reg_addr_limit_end = reg_addr_limit_start + pinfo->pastcCommPack->items[i].reg_count;
reg_addr_start = pstcCommReg->reg_addr;
if (pstcCommReg->bit >= 0)
{
reg_count = (pstcCommReg->bit + pstcCommReg->reg_count + 15) / 16;
}
else
{
reg_count = pstcCommReg->reg_count;
}
reg_addr_end = reg_addr_start + reg_count;
if (reg_addr_start >= reg_addr_limit_start && reg_addr_end <= reg_addr_limit_end)
{
comm_index = i;
break;
}
}
return comm_index;
}