diff --git a/openrtx/include/core/state.h b/openrtx/include/core/state.h index 7767b552..0671d871 100644 --- a/openrtx/include/core/state.h +++ b/openrtx/include/core/state.h @@ -61,9 +61,13 @@ typedef struct bool restore_eflash; char m17_dest[10]; bool txDisable; + uint8_t step_index; } state_t; +extern uint32_t freq_steps[]; +extern size_t n_freq_steps; + enum TunerMode { VFO = 0, diff --git a/openrtx/include/ui/EnglishStrings.h b/openrtx/include/ui/EnglishStrings.h index 18a67c35..bf76d8b4 100644 --- a/openrtx/include/ui/EnglishStrings.h +++ b/openrtx/include/ui/EnglishStrings.h @@ -91,6 +91,7 @@ const stringsTable_t englishStrings = .pressAnyButton = "press any button.", .accessibility = "Accessibility", .usedHeap = "Used heap", - .broadcast = "ALL" + .broadcast = "ALL", + .radioSettings = "Radio Settings" }; #endif // ENGLISHSTRINGS_H diff --git a/openrtx/include/ui/ui_default.h b/openrtx/include/ui/ui_default.h index f85b5824..8030adf4 100644 --- a/openrtx/include/ui/ui_default.h +++ b/openrtx/include/ui/ui_default.h @@ -60,6 +60,7 @@ enum uiScreen SETTINGS_TIMEDATE_SET, SETTINGS_DISPLAY, SETTINGS_GPS, + SETTINGS_RADIO, SETTINGS_M17, SETTINGS_VOICE, SETTINGS_RESET2DEFAULTS, @@ -96,6 +97,7 @@ enum settingsItems #ifdef GPS_PRESENT S_GPS, #endif + S_RADIO, S_M17, S_VOICE, S_RESET2DEFAULTS, @@ -133,6 +135,13 @@ enum settingsVoicePromptItems VP_PHONETIC, }; +enum settingsRadioItems +{ + R_OFFSET, + R_DIRECTION, + R_STEP, +}; + enum settingsM17Items { M17_CALLSIGN = 0, @@ -229,6 +238,7 @@ extern const char *menu_items[]; extern const char *settings_items[]; extern const char *display_items[]; extern const char *settings_gps_items[]; +extern const char *settings_radio_items[]; extern const char *settings_m17_items[]; extern const char * settings_voice_items[]; @@ -239,6 +249,7 @@ extern const uint8_t menu_num; extern const uint8_t settings_num; extern const uint8_t display_num; extern const uint8_t settings_gps_num; +extern const uint8_t settings_radio_num; extern const uint8_t settings_m17_num; extern const uint8_t settings_voice_num; extern const uint8_t backup_restore_num; diff --git a/openrtx/include/ui/ui_strings.h b/openrtx/include/ui/ui_strings.h index 11fc99e7..a9d06ce6 100644 --- a/openrtx/include/ui/ui_strings.h +++ b/openrtx/include/ui/ui_strings.h @@ -96,6 +96,7 @@ typedef struct const char* accessibility; const char* usedHeap; const char* broadcast; + const char* radioSettings; } stringsTable_t; diff --git a/openrtx/src/core/state.c b/openrtx/src/core/state.c index 99e90af0..025cd921 100644 --- a/openrtx/src/core/state.c +++ b/openrtx/src/core/state.c @@ -34,6 +34,10 @@ state_t state; pthread_mutex_t state_mutex; long long int lastUpdate = 0; +// Commonly used frequency steps, expressed in Hz +uint32_t freq_steps[] = { 1000, 5000, 6250, 10000, 12500, 15000, 20000, 25000, 50000, 100000 }; +size_t n_freq_steps = sizeof(freq_steps) / sizeof(freq_steps[0]); + void state_init() { pthread_mutex_init(&state_mutex, NULL); @@ -72,6 +76,7 @@ void state_init() state.rtxStatus = RTX_OFF; state.emergency = false; state.txDisable = false; + state.step_index = 4; // Default frequency step 12.5kHz // Force brightness field to be in range 0 - 100 if(state.settings.brightness > 100) diff --git a/openrtx/src/ui/default/ui.c b/openrtx/src/ui/default/ui.c index 5a819e3c..a5b3207c 100644 --- a/openrtx/src/ui/default/ui.c +++ b/openrtx/src/ui/default/ui.c @@ -113,6 +113,7 @@ extern void _ui_drawSettingsDisplay(ui_state_t* ui_state); extern void _ui_drawSettingsM17(ui_state_t* ui_state); extern void _ui_drawSettingsVoicePrompts(ui_state_t* ui_state); extern void _ui_drawSettingsReset2Defaults(ui_state_t* ui_state); +extern void _ui_drawSettingsRadio(ui_state_t* ui_state); extern bool _ui_drawMacroMenu(ui_state_t* ui_state); extern void _ui_reset_menu_anouncement_tracking(); @@ -138,6 +139,7 @@ const char *settings_items[] = #ifdef GPS_PRESENT "GPS", #endif + "Radio", "M17", "Accessibility", "Default Settings" @@ -163,6 +165,13 @@ const char *settings_gps_items[] = }; #endif +const char *settings_radio_items[] = +{ + "Offset", + "Direction", + "Step", +}; + const char * settings_m17_items[] = { "Callsign", @@ -246,6 +255,7 @@ const uint8_t display_num = sizeof(display_items)/sizeof(display_items[0]); #ifdef GPS_PRESENT const uint8_t settings_gps_num = sizeof(settings_gps_items)/sizeof(settings_gps_items[0]); #endif +const uint8_t settings_radio_num = sizeof(settings_radio_items)/sizeof(settings_radio_items[0]); const uint8_t settings_m17_num = sizeof(settings_m17_items)/sizeof(settings_m17_items[0]); const uint8_t settings_voice_num = sizeof(settings_voice_items)/sizeof(settings_voice_items[0]); const uint8_t backup_restore_num = sizeof(backup_restore_items)/sizeof(backup_restore_items[0]); @@ -1429,11 +1439,11 @@ void ui_updateFSM(bool *sync_rtx) else if(msg.keys & KEY_UP || msg.keys & KNOB_RIGHT) { // Increment TX and RX frequency of 12.5KHz - if(_ui_freq_check_limits(state.channel.rx_frequency + 12500) && - _ui_freq_check_limits(state.channel.tx_frequency + 12500)) + if(_ui_freq_check_limits(state.channel.rx_frequency + freq_steps[state.step_index]) && + _ui_freq_check_limits(state.channel.tx_frequency + freq_steps[state.step_index])) { - state.channel.rx_frequency += 12500; - state.channel.tx_frequency += 12500; + state.channel.rx_frequency += freq_steps[state.step_index]; + state.channel.tx_frequency += freq_steps[state.step_index]; *sync_rtx = true; vp_announceFrequencies(state.channel.rx_frequency, state.channel.tx_frequency, @@ -1443,11 +1453,11 @@ void ui_updateFSM(bool *sync_rtx) else if(msg.keys & KEY_DOWN || msg.keys & KNOB_LEFT) { // Decrement TX and RX frequency of 12.5KHz - if(_ui_freq_check_limits(state.channel.rx_frequency - 12500) && - _ui_freq_check_limits(state.channel.tx_frequency - 12500)) + if(_ui_freq_check_limits(state.channel.rx_frequency - freq_steps[state.step_index]) && + _ui_freq_check_limits(state.channel.tx_frequency - freq_steps[state.step_index])) { - state.channel.rx_frequency -= 12500; - state.channel.tx_frequency -= 12500; + state.channel.rx_frequency -= freq_steps[state.step_index]; + state.channel.tx_frequency -= freq_steps[state.step_index]; *sync_rtx = true; vp_announceFrequencies(state.channel.rx_frequency, state.channel.tx_frequency, @@ -1803,6 +1813,9 @@ void ui_updateFSM(bool *sync_rtx) state.ui_screen = SETTINGS_GPS; break; #endif + case S_RADIO: + state.ui_screen = SETTINGS_RADIO; + break; case S_M17: state.ui_screen = SETTINGS_M17; break; @@ -2023,6 +2036,42 @@ void ui_updateFSM(bool *sync_rtx) _ui_menuBack(MENU_SETTINGS); break; #endif + // Radio Settings + case SETTINGS_RADIO: + if(msg.keys & KEY_LEFT || msg.keys & KEY_RIGHT || + (ui_state.edit_mode && + (msg.keys & KEY_DOWN || msg.keys & KNOB_LEFT || + msg.keys & KEY_UP || msg.keys & KNOB_RIGHT))) + { + switch(ui_state.menu_selected) + { + case R_OFFSET: + break; + case R_DIRECTION: + // Invert frequency offset direction + if (state.channel.tx_frequency >= state.channel.rx_frequency) + state.channel.tx_frequency -= 2 * ((int32_t)state.channel.tx_frequency - (int32_t)state.channel.rx_frequency); + else // Switch to positive offset + state.channel.tx_frequency -= 2 * ((int32_t)state.channel.tx_frequency - (int32_t)state.channel.rx_frequency); + break; + case R_STEP: + // Cycle over the available frequency steps + state.step_index++; + state.step_index %= n_freq_steps; + break; + default: + state.ui_screen = SETTINGS_GPS; + } + } + else if(msg.keys & KEY_UP || msg.keys & KNOB_LEFT) + _ui_menuUp(settings_radio_num); + else if(msg.keys & KEY_DOWN || msg.keys & KNOB_RIGHT) + _ui_menuDown(settings_radio_num); + else if(msg.keys & KEY_ENTER) + ui_state.edit_mode = !ui_state.edit_mode; + else if(msg.keys & KEY_ESC) + _ui_menuBack(MENU_SETTINGS); + break; // M17 Settings case SETTINGS_M17: if(ui_state.edit_mode) @@ -2344,6 +2393,10 @@ bool ui_updateGUI() case SETTINGS_RESET2DEFAULTS: _ui_drawSettingsReset2Defaults(&ui_state); break; + // Screen to set frequency offset and step + case SETTINGS_RADIO: + _ui_drawSettingsRadio(&ui_state); + break; // Low battery screen case LOW_BAT: _ui_drawLowBatteryScreen(); diff --git a/openrtx/src/ui/default/ui_menu.c b/openrtx/src/ui/default/ui_menu.c index b4b27172..da228dd7 100644 --- a/openrtx/src/ui/default/ui_menu.c +++ b/openrtx/src/ui/default/ui_menu.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -336,6 +337,44 @@ int _ui_getSettingsGPSValueName(char *buf, uint8_t max_len, uint8_t index) } #endif +int _ui_getRadioEntryName(char *buf, uint8_t max_len, uint8_t index) +{ + if(index >= settings_radio_num) return -1; + snprintf(buf, max_len, "%s", settings_radio_items[index]); + return 0; +} + +int _ui_getRadioValueName(char *buf, uint8_t max_len, uint8_t index) +{ + if(index >= settings_radio_num) + return -1; + + int32_t offset = 0; + switch(index) + { + case R_OFFSET: + offset = abs((int32_t)last_state.channel.tx_frequency - + (int32_t)last_state.channel.rx_frequency); + snprintf(buf, max_len, "%gMHz", (float) offset / 1000000.0f); + break; + + case R_DIRECTION: + buf[0] = (last_state.channel.tx_frequency >= last_state.channel.rx_frequency) ? '+' : '-'; + buf[1] = '\0'; + break; + + case R_STEP: + // Print in kHz if it is smaller than 1MHz + if (freq_steps[last_state.step_index] < 1000000) + snprintf(buf, max_len, "%gkHz", (float) freq_steps[last_state.step_index] / 1000.0f); + else + snprintf(buf, max_len, "%gMHz", (float) freq_steps[last_state.step_index] / 1000000.0f); + break; + } + + return 0; +} + int _ui_getM17EntryName(char *buf, uint8_t max_len, uint8_t index) { if(index >= settings_m17_num) return -1; @@ -896,6 +935,17 @@ void _ui_drawSettingsReset2Defaults(ui_state_t* ui_state) drawcnt++; } +void _ui_drawSettingsRadio(ui_state_t* ui_state) +{ + gfx_clearScreen(); + // Print "Radio Settings" on top bar + gfx_print(layout.top_pos, layout.top_font, TEXT_ALIGN_CENTER, + color_white, currentLanguage->radioSettings); + // Print radio settings entries + _ui_drawMenuListValue(ui_state, ui_state->menu_selected, _ui_getRadioEntryName, + _ui_getRadioValueName); +} + void _ui_drawMacroTop() { gfx_print(layout.top_pos, layout.top_font, TEXT_ALIGN_CENTER,