#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 *)®_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 *)®_value = scale_value / scale; } else { reg_value = round(scale_value / scale); } return MenuPack_RegisterValueWrite(&stcRegInfo, (void *)®_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 *)®_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; }