diff --git a/openrtx/include/ui.h b/openrtx/include/ui.h index 705908ac..a6d7cdf3 100644 --- a/openrtx/include/ui.h +++ b/openrtx/include/ui.h @@ -158,6 +158,7 @@ typedef struct ui_state_t uint8_t input_number; uint8_t input_position; uint8_t input_set; + long long last_keypress; freq_t new_rx_frequency; freq_t new_tx_frequency; char new_rx_freq_buf[14]; @@ -168,6 +169,7 @@ typedef struct ui_state_t char new_date_buf[9]; char new_time_buf[9]; #endif + char new_callsign[10]; // Which state to return to when we exit menu uint8_t last_main_state; } diff --git a/openrtx/src/ui/ui.c b/openrtx/src/ui/ui.c index a4e767b6..4e366123 100644 --- a/openrtx/src/ui/ui.c +++ b/openrtx/src/ui/ui.c @@ -70,6 +70,7 @@ #ifdef HAS_GPS #include #endif +#include #include #include #include @@ -104,7 +105,7 @@ extern void _ui_drawSettingsTimeDate(); extern void _ui_drawSettingsTimeDateSet(ui_state_t* ui_state); #endif extern void _ui_drawSettingsDisplay(ui_state_t* ui_state); -extern void _ui_drawSettingsM17(); +extern void _ui_drawSettingsM17(ui_state_t* ui_state); extern bool _ui_drawMacroMenu(); const char *menu_items[] = @@ -170,6 +171,22 @@ const char *authors[] = "Fred IU2NRO", }; +const char *symbols_ITU_T_E161[] = +{ + " 0", + ",.?1", + "abc2ABC", + "def3DEF", + "ghi4GHI", + "jkl5JKL", + "mno6MNO", + "pqrs7PQRS", + "tuv8TUV", + "wxyz9WXYZ", + "*", + "#" +}; + // Calculate number of menu entries const uint8_t menu_num = sizeof(menu_items)/sizeof(menu_items[0]); const uint8_t settings_num = sizeof(settings_items)/sizeof(settings_items[0]); @@ -706,6 +723,37 @@ void _ui_menuBack(uint8_t prev_state) } } +void _ui_textInputKeypad(char *buf, uint8_t max_len, kbd_msg_t msg) +{ + if(ui_state.input_position >= max_len) + return; + long long now = getTick(); + // Get currently pressed number key + uint8_t num_key = input_getPressedNumber(msg); + // Get number of symbols related to currently pressed key + uint8_t num_symbols = strlen(symbols_ITU_T_E161[num_key]); + // Reset reference values on first function call + if(ui_state.input_position == 0 && ui_state.input_set == 0) + { + ui_state.input_number = num_key; + ui_state.last_keypress = now; + } + // Different key pressed, advance input position + if(ui_state.input_number != num_key || (now - ui_state.last_keypress) > kbd_long_interval) + { + ui_state.input_position += 1; + ui_state.input_set = 0; + } + // Same key pressed, advance symbol choice + else + ui_state.input_set = (ui_state.input_set + 1) % num_symbols; + // Update reference values + ui_state.input_number = num_key; + ui_state.last_keypress = now; + // After time interval, advance input position and reset symbol selection and timestamp + buf[ui_state.input_position] = symbols_ITU_T_E161[num_key][ui_state.input_set]; +} + void ui_saveState() { last_state = state; @@ -1216,8 +1264,37 @@ void ui_updateFSM(event_t event, bool *sync_rtx) #endif // M17 Settings case SETTINGS_M17: - if(msg.keys & KEY_ESC) - _ui_menuBack(MENU_SETTINGS); + if(ui_state.edit_mode) + { + if(msg.keys & KEY_ENTER) + { + // Save selected callsign and disable input mode + strcpy(state.settings.callsign, ui_state.new_callsign); + ui_state.edit_mode = false; + } + else if(msg.keys & KEY_ESC) + // Discard selected callsign and disable input mode + ui_state.edit_mode = false; + else if(input_isNumberPressed(msg)) + _ui_textInputKeypad(ui_state.new_callsign, 9, msg); + } + else + { + if(msg.keys & KEY_ENTER) + { + // Enable callsign input + ui_state.edit_mode = true; + // Reset text input variables + ui_state.input_number = 0; + ui_state.input_position = 0; + ui_state.input_set = 0; + ui_state.last_keypress = 0; + memset(&ui_state.new_callsign, 0, 9); + ui_state.new_callsign[0] = '_'; + } + else if(msg.keys & KEY_ESC) + _ui_menuBack(MENU_SETTINGS); + } break; } } @@ -1309,7 +1386,7 @@ void ui_updateGUI() #endif // M17 settings screen case SETTINGS_M17: - _ui_drawSettingsM17(); + _ui_drawSettingsM17(&ui_state); break; // Low battery screen case LOW_BAT: diff --git a/openrtx/src/ui/ui_menu.c b/openrtx/src/ui/ui_menu.c index 0baab518..b5b81ad5 100644 --- a/openrtx/src/ui/ui_menu.c +++ b/openrtx/src/ui/ui_menu.c @@ -513,7 +513,7 @@ void _ui_drawSettingsTimeDateSet(ui_state_t* ui_state) } #endif -void _ui_drawSettingsM17() +void _ui_drawSettingsM17(ui_state_t* ui_state) { gfx_clearScreen(); // Print "M17 Settings" on top bar @@ -522,10 +522,25 @@ void _ui_drawSettingsM17() gfx_printLine(1, 4, layout.top_h, SCREEN_HEIGHT - layout.bottom_h, layout.horizontal_pad, layout.menu_font, TEXT_ALIGN_LEFT, color_white, "Callsign:"); - // Print M17 current callsign - gfx_printLine(1, 1, layout.top_h, SCREEN_HEIGHT - layout.bottom_h, - layout.horizontal_pad, layout.input_font, - TEXT_ALIGN_CENTER, color_white, last_state.settings.callsign); + if(ui_state->edit_mode) + { + uint16_t rect_width = SCREEN_WIDTH - (layout.horizontal_pad * 2); + uint16_t rect_height = (SCREEN_HEIGHT - (layout.top_h + layout.bottom_h))/2; + point_t rect_origin = {(SCREEN_WIDTH - rect_width) / 2, + (SCREEN_HEIGHT - rect_height) / 2}; + gfx_drawRect(rect_origin, rect_width, rect_height, color_white, false); + // Print M17 callsign being typed + gfx_printLine(1, 1, layout.top_h, SCREEN_HEIGHT - layout.bottom_h, + layout.horizontal_pad, layout.input_font, + TEXT_ALIGN_CENTER, color_white, ui_state->new_callsign); + } + else + { + // Print M17 current callsign + gfx_printLine(1, 1, layout.top_h, SCREEN_HEIGHT - layout.bottom_h, + layout.horizontal_pad, layout.input_font, + TEXT_ALIGN_CENTER, color_white, last_state.settings.callsign); + } } bool _ui_drawMacroMenu() {