2020-10-30 19:13:52 +00:00
|
|
|
/***************************************************************************
|
2023-02-08 15:33:02 +00:00
|
|
|
* Copyright (C) 2020 - 2023 by Federico Amedeo Izzo IU2NUO, *
|
2022-06-29 05:47:38 +00:00
|
|
|
* Niccolò Izzo IU2KIN *
|
|
|
|
* Frederik Saraci IU2NRO *
|
|
|
|
* Silvano Seva IU2KWO *
|
2020-10-30 19:13:52 +00:00
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
|
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/> *
|
|
|
|
***************************************************************************/
|
|
|
|
|
2020-10-30 19:56:48 +00:00
|
|
|
/*
|
2020-12-11 13:40:56 +00:00
|
|
|
* The graphical user interface (GUI) works by splitting the screen in
|
2020-10-30 19:56:48 +00:00
|
|
|
* horizontal rows, with row height depending on vertical resolution.
|
2020-12-11 13:40:56 +00:00
|
|
|
*
|
2020-10-30 19:56:48 +00:00
|
|
|
* The general screen layout is composed by an upper status bar at the
|
|
|
|
* top of the screen and a lower status bar at the bottom.
|
|
|
|
* The central portion of the screen is filled by two big text/number rows
|
|
|
|
* And a small row.
|
|
|
|
*
|
|
|
|
* Below is shown the row height for two common display densities.
|
|
|
|
*
|
2020-10-31 10:18:01 +00:00
|
|
|
* 160x128 display (MD380) Recommended font size
|
2020-10-30 19:56:48 +00:00
|
|
|
* ┌─────────────────────────┐
|
2021-01-31 10:37:42 +00:00
|
|
|
* │ top_status_bar (16px) │ 8 pt (11 px) font with 2 px vertical padding
|
|
|
|
* │ top_pad (4px) │ 4 px padding
|
|
|
|
* │ Line 1 (20px) │ 8 pt (11 px) font with 4 px vertical padding
|
|
|
|
* │ Line 2 (20px) │ 8 pt (11 px) font with 4 px vertical padding
|
2020-10-30 19:56:48 +00:00
|
|
|
* │ │
|
2021-01-31 10:37:42 +00:00
|
|
|
* │ Line 3 (40px) │ 16 pt (xx px) font with 6 px vertical padding
|
|
|
|
* │ RSSI+squelch bar (20px) │ 20 px
|
|
|
|
* │ bottom_pad (4px) │ 4 px padding
|
2020-10-30 19:56:48 +00:00
|
|
|
* └─────────────────────────┘
|
|
|
|
*
|
2020-10-31 17:12:44 +00:00
|
|
|
* 128x64 display (GD-77)
|
2020-10-30 19:56:48 +00:00
|
|
|
* ┌─────────────────────────┐
|
2021-01-03 08:38:54 +00:00
|
|
|
* │ top_status_bar (11 px) │ 6 pt (9 px) font with 1 px vertical padding
|
2021-01-31 10:37:42 +00:00
|
|
|
* │ top_pad (1px) │ 1 px padding
|
2021-01-03 08:38:54 +00:00
|
|
|
* │ Line 1 (10px) │ 6 pt (9 px) font without vertical padding
|
2021-01-31 10:37:42 +00:00
|
|
|
* │ Line 2 (10px) │ 6 pt (9 px) font with 2 px vertical padding
|
|
|
|
* │ Line 3 (18px) │ 12 pt (xx px) font with 0 px vertical padding
|
|
|
|
* │ RSSI+squelch bar (11px) │ 11 px
|
|
|
|
* │ bottom_pad (1px) │ 1 px padding
|
2020-10-30 19:56:48 +00:00
|
|
|
* └─────────────────────────┘
|
2020-10-31 17:12:44 +00:00
|
|
|
*
|
|
|
|
* 128x48 display (RD-5R)
|
|
|
|
* ┌─────────────────────────┐
|
2021-01-03 08:38:54 +00:00
|
|
|
* │ top_status_bar (11 px) │ 6 pt (9 px) font with 1 px vertical padding
|
|
|
|
* ├─────────────────────────┤ 1 px line
|
2021-01-31 10:37:42 +00:00
|
|
|
* │ Line 2 (10px) │ 8 pt (11 px) font with 4 px vertical padding
|
|
|
|
* │ Line 3 (18px) │ 8 pt (11 px) font with 4 px vertical padding
|
2020-10-31 17:12:44 +00:00
|
|
|
* └─────────────────────────┘
|
2020-10-30 19:56:48 +00:00
|
|
|
*/
|
|
|
|
|
2020-10-30 19:13:52 +00:00
|
|
|
#include <stdio.h>
|
2020-11-16 08:03:03 +00:00
|
|
|
#include <stdint.h>
|
2022-09-13 12:59:08 +00:00
|
|
|
#include <math.h>
|
2022-12-08 20:53:45 +00:00
|
|
|
#include <ui/ui_default.h>
|
2021-01-29 19:35:48 +00:00
|
|
|
#include <rtx.h>
|
2020-12-24 15:24:35 +00:00
|
|
|
#include <interfaces/platform.h>
|
2022-08-04 20:22:56 +00:00
|
|
|
#include <interfaces/display.h>
|
2022-03-26 13:51:43 +00:00
|
|
|
#include <interfaces/cps_io.h>
|
2021-01-01 21:06:35 +00:00
|
|
|
#include <interfaces/nvmem.h>
|
2021-05-11 06:20:18 +00:00
|
|
|
#include <interfaces/delays.h>
|
2020-12-07 17:43:54 +00:00
|
|
|
#include <string.h>
|
2020-12-11 13:09:20 +00:00
|
|
|
#include <battery.h>
|
2021-01-01 16:31:42 +00:00
|
|
|
#include <input.h>
|
2022-09-05 15:36:07 +00:00
|
|
|
#include <utils.h>
|
2021-01-28 11:51:22 +00:00
|
|
|
#include <hwconfig.h>
|
2022-08-16 19:39:47 +00:00
|
|
|
#include <voicePromptUtils.h>
|
2022-09-11 09:38:40 +00:00
|
|
|
#include <beeps.h>
|
2020-10-31 10:18:01 +00:00
|
|
|
|
2021-01-10 08:03:07 +00:00
|
|
|
/* UI main screen functions, their implementation is in "ui_main.c" */
|
|
|
|
extern void _ui_drawMainBackground();
|
2023-09-10 04:27:36 +00:00
|
|
|
extern void _ui_drawMainTop(ui_state_t* ui_state);
|
2021-01-30 07:33:39 +00:00
|
|
|
extern void _ui_drawVFOMiddle();
|
|
|
|
extern void _ui_drawMEMMiddle();
|
2021-01-10 08:03:07 +00:00
|
|
|
extern void _ui_drawVFOBottom();
|
|
|
|
extern void _ui_drawMEMBottom();
|
2022-09-15 13:59:52 +00:00
|
|
|
extern void _ui_drawMainVFO(ui_state_t* ui_state);
|
2021-01-30 07:33:39 +00:00
|
|
|
extern void _ui_drawMainVFOInput(ui_state_t* ui_state);
|
2022-09-15 13:59:52 +00:00
|
|
|
extern void _ui_drawMainMEM(ui_state_t* ui_state);
|
2021-01-10 08:03:07 +00:00
|
|
|
/* UI menu functions, their implementation is in "ui_menu.c" */
|
2021-01-09 17:33:40 +00:00
|
|
|
extern void _ui_drawMenuTop(ui_state_t* ui_state);
|
2022-03-26 12:42:10 +00:00
|
|
|
extern void _ui_drawMenuBank(ui_state_t* ui_state);
|
2021-01-09 17:33:40 +00:00
|
|
|
extern void _ui_drawMenuChannel(ui_state_t* ui_state);
|
2021-01-24 17:53:43 +00:00
|
|
|
extern void _ui_drawMenuContacts(ui_state_t* ui_state);
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef GPS_PRESENT
|
2021-02-14 13:04:01 +00:00
|
|
|
extern void _ui_drawMenuGPS();
|
2021-02-14 16:49:23 +00:00
|
|
|
extern void _ui_drawSettingsGPS(ui_state_t* ui_state);
|
|
|
|
#endif
|
2022-05-18 11:18:12 +00:00
|
|
|
extern void _ui_drawSettingsVoicePrompts(ui_state_t* ui_state);
|
2021-01-09 17:33:40 +00:00
|
|
|
extern void _ui_drawMenuSettings(ui_state_t* ui_state);
|
2022-03-12 23:21:52 +00:00
|
|
|
extern void _ui_drawMenuBackupRestore(ui_state_t* ui_state);
|
|
|
|
extern void _ui_drawMenuBackup(ui_state_t* ui_state);
|
|
|
|
extern void _ui_drawMenuRestore(ui_state_t* ui_state);
|
2021-01-30 07:02:41 +00:00
|
|
|
extern void _ui_drawMenuInfo(ui_state_t* ui_state);
|
2021-01-30 18:58:25 +00:00
|
|
|
extern void _ui_drawMenuAbout();
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef RTC_PRESENT
|
2021-01-30 07:33:39 +00:00
|
|
|
extern void _ui_drawSettingsTimeDate();
|
|
|
|
extern void _ui_drawSettingsTimeDateSet(ui_state_t* ui_state);
|
2021-01-09 17:33:40 +00:00
|
|
|
#endif
|
2021-01-29 21:59:38 +00:00
|
|
|
extern void _ui_drawSettingsDisplay(ui_state_t* ui_state);
|
2021-05-11 06:20:18 +00:00
|
|
|
extern void _ui_drawSettingsM17(ui_state_t* ui_state);
|
2022-05-18 11:18:12 +00:00
|
|
|
extern void _ui_drawSettingsVoicePrompts(ui_state_t* ui_state);
|
2022-02-26 11:42:28 +00:00
|
|
|
extern void _ui_drawSettingsReset2Defaults(ui_state_t* ui_state);
|
2023-09-25 12:16:32 +00:00
|
|
|
extern void _ui_drawSettingsRadio(ui_state_t* ui_state);
|
2023-09-08 07:48:03 +00:00
|
|
|
extern bool _ui_drawMacroMenu(ui_state_t* ui_state);
|
2022-09-10 00:11:01 +00:00
|
|
|
extern void _ui_reset_menu_anouncement_tracking();
|
2021-01-09 17:33:40 +00:00
|
|
|
|
2021-02-13 15:14:44 +00:00
|
|
|
const char *menu_items[] =
|
2020-12-06 20:45:10 +00:00
|
|
|
{
|
2022-03-26 12:42:10 +00:00
|
|
|
"Banks",
|
2020-12-06 20:45:10 +00:00
|
|
|
"Channels",
|
|
|
|
"Contacts",
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef GPS_PRESENT
|
2020-12-06 20:45:10 +00:00
|
|
|
"GPS",
|
2021-02-14 16:49:23 +00:00
|
|
|
#endif
|
2021-01-30 07:02:41 +00:00
|
|
|
"Settings",
|
2021-01-30 10:57:00 +00:00
|
|
|
"Info",
|
|
|
|
"About"
|
2020-12-06 20:45:10 +00:00
|
|
|
};
|
|
|
|
|
2021-02-02 20:45:10 +00:00
|
|
|
const char *settings_items[] =
|
2020-12-20 09:47:07 +00:00
|
|
|
{
|
2021-02-15 21:02:09 +00:00
|
|
|
"Display",
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef RTC_PRESENT
|
2021-01-26 21:04:19 +00:00
|
|
|
"Time & Date",
|
2021-01-29 22:07:39 +00:00
|
|
|
#endif
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef GPS_PRESENT
|
2021-05-10 20:20:10 +00:00
|
|
|
"GPS",
|
2021-02-14 16:49:23 +00:00
|
|
|
#endif
|
2023-09-25 12:16:32 +00:00
|
|
|
"Radio",
|
2022-02-26 11:42:28 +00:00
|
|
|
"M17",
|
2022-08-16 19:39:47 +00:00
|
|
|
"Accessibility",
|
2022-02-26 11:42:28 +00:00
|
|
|
"Default Settings"
|
2021-02-13 15:14:44 +00:00
|
|
|
};
|
2021-01-26 21:04:19 +00:00
|
|
|
|
2021-02-02 20:45:10 +00:00
|
|
|
const char *display_items[] =
|
2021-01-26 21:04:19 +00:00
|
|
|
{
|
2023-08-07 18:36:22 +00:00
|
|
|
#ifdef SCREEN_BRIGHTNESS
|
2021-01-26 21:04:19 +00:00
|
|
|
"Brightness",
|
2023-08-07 18:36:22 +00:00
|
|
|
#endif
|
2021-02-13 15:14:44 +00:00
|
|
|
#ifdef SCREEN_CONTRAST
|
2021-12-13 22:18:01 +00:00
|
|
|
"Contrast",
|
2021-01-29 21:57:24 +00:00
|
|
|
#endif
|
2021-12-13 22:18:01 +00:00
|
|
|
"Timer"
|
2021-02-13 15:14:44 +00:00
|
|
|
};
|
|
|
|
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef GPS_PRESENT
|
2021-02-13 16:23:16 +00:00
|
|
|
const char *settings_gps_items[] =
|
|
|
|
{
|
|
|
|
"GPS Enabled",
|
|
|
|
"GPS Set Time",
|
|
|
|
"UTC Timezone"
|
|
|
|
};
|
2021-02-14 16:49:23 +00:00
|
|
|
#endif
|
2023-05-28 11:35:13 +00:00
|
|
|
|
2023-09-25 12:16:32 +00:00
|
|
|
const char *settings_radio_items[] =
|
|
|
|
{
|
2023-10-22 21:53:19 +00:00
|
|
|
"Rpt. shift",
|
2023-09-25 12:16:32 +00:00
|
|
|
"Direction",
|
|
|
|
"Step",
|
2023-10-22 23:51:29 +00:00
|
|
|
"Correction",
|
2023-09-25 12:16:32 +00:00
|
|
|
};
|
|
|
|
|
2023-05-28 11:35:13 +00:00
|
|
|
const char * settings_m17_items[] =
|
|
|
|
{
|
|
|
|
"Callsign",
|
2023-09-05 18:38:22 +00:00
|
|
|
"CAN",
|
|
|
|
"CAN RX Check"
|
2023-05-28 11:35:13 +00:00
|
|
|
};
|
|
|
|
|
2022-05-18 11:18:12 +00:00
|
|
|
const char * settings_voice_items[] =
|
|
|
|
{
|
2022-08-16 19:39:47 +00:00
|
|
|
"Voice",
|
|
|
|
"Phonetic"
|
2022-05-18 11:18:12 +00:00
|
|
|
};
|
2021-02-13 16:23:16 +00:00
|
|
|
|
2022-03-12 23:21:52 +00:00
|
|
|
const char *backup_restore_items[] =
|
|
|
|
{
|
|
|
|
"Backup",
|
|
|
|
"Restore"
|
|
|
|
};
|
|
|
|
|
2021-02-02 20:45:10 +00:00
|
|
|
const char *info_items[] =
|
2021-01-30 07:02:41 +00:00
|
|
|
{
|
2021-04-11 07:56:46 +00:00
|
|
|
"",
|
2021-01-30 07:02:41 +00:00
|
|
|
"Bat. Voltage",
|
|
|
|
"Bat. Charge",
|
|
|
|
"RSSI",
|
2022-06-16 15:16:38 +00:00
|
|
|
"Used heap",
|
2021-02-02 20:45:10 +00:00
|
|
|
"Band",
|
|
|
|
"VHF",
|
|
|
|
"UHF",
|
2023-09-07 09:44:09 +00:00
|
|
|
"Hw Version",
|
|
|
|
#ifdef PLATFORM_TTWRPLUS
|
|
|
|
"Radio",
|
|
|
|
"Radio FW",
|
|
|
|
#endif
|
2021-01-30 07:02:41 +00:00
|
|
|
};
|
2021-02-13 15:14:44 +00:00
|
|
|
|
2021-02-02 20:45:10 +00:00
|
|
|
const char *authors[] =
|
2021-01-30 10:57:00 +00:00
|
|
|
{
|
|
|
|
"Niccolo' IU2KIN",
|
|
|
|
"Silvano IU2KWO",
|
|
|
|
"Federico IU2NUO",
|
|
|
|
"Fred IU2NRO",
|
|
|
|
};
|
2021-02-13 16:23:16 +00:00
|
|
|
|
2022-08-04 20:55:42 +00:00
|
|
|
static const char *symbols_ITU_T_E161[] =
|
2021-05-11 06:20:18 +00:00
|
|
|
{
|
|
|
|
" 0",
|
|
|
|
",.?1",
|
|
|
|
"abc2ABC",
|
|
|
|
"def3DEF",
|
|
|
|
"ghi4GHI",
|
|
|
|
"jkl5JKL",
|
|
|
|
"mno6MNO",
|
|
|
|
"pqrs7PQRS",
|
|
|
|
"tuv8TUV",
|
|
|
|
"wxyz9WXYZ",
|
2021-10-09 16:35:42 +00:00
|
|
|
"-/*",
|
2021-05-11 06:20:18 +00:00
|
|
|
"#"
|
|
|
|
};
|
|
|
|
|
2022-08-04 20:55:42 +00:00
|
|
|
static const char *symbols_ITU_T_E161_callsign[] =
|
2021-07-18 13:50:08 +00:00
|
|
|
{
|
2022-06-17 08:10:23 +00:00
|
|
|
"0 ",
|
2021-07-18 13:50:08 +00:00
|
|
|
"1",
|
|
|
|
"ABC2",
|
|
|
|
"DEF3",
|
|
|
|
"GHI4",
|
|
|
|
"JKL5",
|
|
|
|
"MNO6",
|
|
|
|
"PQRS7",
|
|
|
|
"TUV8",
|
|
|
|
"WXYZ9",
|
2021-10-09 16:35:42 +00:00
|
|
|
"-/",
|
2021-07-18 13:50:08 +00:00
|
|
|
""
|
|
|
|
};
|
|
|
|
|
2021-02-13 16:23:16 +00:00
|
|
|
// Calculate number of menu entries
|
2021-01-09 09:47:18 +00:00
|
|
|
const uint8_t menu_num = sizeof(menu_items)/sizeof(menu_items[0]);
|
2020-12-28 08:31:33 +00:00
|
|
|
const uint8_t settings_num = sizeof(settings_items)/sizeof(settings_items[0]);
|
2021-01-27 20:46:36 +00:00
|
|
|
const uint8_t display_num = sizeof(display_items)/sizeof(display_items[0]);
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef GPS_PRESENT
|
2021-02-13 16:23:16 +00:00
|
|
|
const uint8_t settings_gps_num = sizeof(settings_gps_items)/sizeof(settings_gps_items[0]);
|
2021-02-14 16:49:23 +00:00
|
|
|
#endif
|
2023-09-25 12:16:32 +00:00
|
|
|
const uint8_t settings_radio_num = sizeof(settings_radio_items)/sizeof(settings_radio_items[0]);
|
2023-05-28 11:35:13 +00:00
|
|
|
const uint8_t settings_m17_num = sizeof(settings_m17_items)/sizeof(settings_m17_items[0]);
|
2022-05-18 11:18:12 +00:00
|
|
|
const uint8_t settings_voice_num = sizeof(settings_voice_items)/sizeof(settings_voice_items[0]);
|
2022-03-12 23:21:52 +00:00
|
|
|
const uint8_t backup_restore_num = sizeof(backup_restore_items)/sizeof(backup_restore_items[0]);
|
2021-01-30 07:02:41 +00:00
|
|
|
const uint8_t info_num = sizeof(info_items)/sizeof(info_items[0]);
|
2021-01-30 10:57:00 +00:00
|
|
|
const uint8_t author_num = sizeof(authors)/sizeof(authors[0]);
|
2020-12-20 09:47:07 +00:00
|
|
|
|
2020-12-20 08:07:48 +00:00
|
|
|
const color_t color_black = {0, 0, 0, 255};
|
2020-12-19 14:00:33 +00:00
|
|
|
const color_t color_grey = {60, 60, 60, 255};
|
2020-12-20 08:07:48 +00:00
|
|
|
const color_t color_white = {255, 255, 255, 255};
|
2020-12-19 14:00:33 +00:00
|
|
|
const color_t yellow_fab413 = {250, 180, 19, 255};
|
2020-12-07 17:43:54 +00:00
|
|
|
|
2020-10-31 17:12:44 +00:00
|
|
|
layout_t layout;
|
2021-01-30 07:33:39 +00:00
|
|
|
state_t last_state;
|
2023-08-08 18:20:14 +00:00
|
|
|
bool macro_latched;
|
2022-08-04 20:55:42 +00:00
|
|
|
static ui_state_t ui_state;
|
|
|
|
static bool macro_menu = false;
|
|
|
|
static bool layout_ready = false;
|
|
|
|
static bool redraw_needed = true;
|
2021-11-22 22:06:11 +00:00
|
|
|
|
2022-08-04 20:55:42 +00:00
|
|
|
static bool standby = false;
|
|
|
|
static long long last_event_tick = 0;
|
2020-12-30 18:55:51 +00:00
|
|
|
|
2022-06-29 05:47:38 +00:00
|
|
|
// UI event queue
|
2022-08-04 20:55:42 +00:00
|
|
|
static uint8_t evQueue_rdPos;
|
|
|
|
static uint8_t evQueue_wrPos;
|
|
|
|
static event_t evQueue[MAX_NUM_EVENTS];
|
2022-06-29 05:47:38 +00:00
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
|
|
|
|
static layout_t _ui_calculateLayout()
|
2020-10-31 10:18:01 +00:00
|
|
|
{
|
2021-01-03 08:38:54 +00:00
|
|
|
// Horizontal line height
|
|
|
|
const uint16_t hline_h = 1;
|
|
|
|
// Compensate for fonts printing below the start position
|
|
|
|
const uint16_t text_v_offset = 1;
|
|
|
|
|
2020-10-31 17:12:44 +00:00
|
|
|
// Calculate UI layout depending on vertical resolution
|
|
|
|
// Tytera MD380, MD-UV380
|
2020-11-16 08:03:03 +00:00
|
|
|
#if SCREEN_HEIGHT > 127
|
|
|
|
|
|
|
|
// Height and padding shown in diagram at beginning of file
|
|
|
|
const uint16_t top_h = 16;
|
2021-01-31 10:37:42 +00:00
|
|
|
const uint16_t top_pad = 4;
|
|
|
|
const uint16_t line1_h = 20;
|
|
|
|
const uint16_t line2_h = 20;
|
2023-08-31 18:37:55 +00:00
|
|
|
const uint16_t line3_h = 20;
|
|
|
|
const uint16_t line3_large_h = 40;
|
|
|
|
const uint16_t line4_h = 20;
|
2021-02-20 15:03:37 +00:00
|
|
|
const uint16_t menu_h = 16;
|
2021-05-09 09:19:02 +00:00
|
|
|
const uint16_t bottom_h = 23;
|
2021-01-31 10:37:42 +00:00
|
|
|
const uint16_t bottom_pad = top_pad;
|
2021-01-03 08:38:54 +00:00
|
|
|
const uint16_t status_v_pad = 2;
|
2021-01-31 10:37:42 +00:00
|
|
|
const uint16_t small_line_v_pad = 2;
|
|
|
|
const uint16_t big_line_v_pad = 6;
|
2020-12-06 15:16:42 +00:00
|
|
|
const uint16_t horizontal_pad = 4;
|
2020-11-16 08:03:03 +00:00
|
|
|
|
|
|
|
// Top bar font: 8 pt
|
2023-08-23 12:32:36 +00:00
|
|
|
const fontSize_t top_font = FONT_SIZE_8PT;
|
|
|
|
const symbolSize_t top_symbol_size = SYMBOLS_SIZE_8PT;
|
2021-01-31 10:37:42 +00:00
|
|
|
// Text line font: 8 pt
|
|
|
|
const fontSize_t line1_font = FONT_SIZE_8PT;
|
2023-08-31 18:37:55 +00:00
|
|
|
const symbolSize_t line1_symbol_size = SYMBOLS_SIZE_8PT;
|
2021-01-31 10:37:42 +00:00
|
|
|
const fontSize_t line2_font = FONT_SIZE_8PT;
|
2023-08-31 18:37:55 +00:00
|
|
|
const symbolSize_t line2_symbol_size = SYMBOLS_SIZE_8PT;
|
|
|
|
const fontSize_t line3_font = FONT_SIZE_8PT;
|
|
|
|
const symbolSize_t line3_symbol_size = SYMBOLS_SIZE_8PT;
|
|
|
|
const fontSize_t line4_font = FONT_SIZE_8PT;
|
|
|
|
const symbolSize_t line4_symbol_size = SYMBOLS_SIZE_8PT;
|
2021-01-31 10:37:42 +00:00
|
|
|
// Frequency line font: 16 pt
|
2023-08-31 18:37:55 +00:00
|
|
|
const fontSize_t line3_large_font = FONT_SIZE_16PT;
|
2020-11-16 08:03:03 +00:00
|
|
|
// Bottom bar font: 8 pt
|
2020-11-17 21:50:27 +00:00
|
|
|
const fontSize_t bottom_font = FONT_SIZE_8PT;
|
2021-02-02 11:54:09 +00:00
|
|
|
// TimeDate/Frequency input font
|
|
|
|
const fontSize_t input_font = FONT_SIZE_12PT;
|
2021-02-20 15:03:37 +00:00
|
|
|
// Menu font
|
|
|
|
const fontSize_t menu_font = FONT_SIZE_8PT;
|
2021-05-06 11:03:41 +00:00
|
|
|
// Mode screen frequency font: 12 pt
|
|
|
|
const fontSize_t mode_font_big = FONT_SIZE_12PT;
|
|
|
|
// Mode screen details font: 9 pt
|
|
|
|
const fontSize_t mode_font_small = FONT_SIZE_9PT;
|
2020-11-16 08:03:03 +00:00
|
|
|
|
2020-10-31 17:12:44 +00:00
|
|
|
// Radioddity GD-77
|
2020-11-16 08:03:03 +00:00
|
|
|
#elif SCREEN_HEIGHT > 63
|
|
|
|
|
|
|
|
// Height and padding shown in diagram at beginning of file
|
2021-01-03 08:38:54 +00:00
|
|
|
const uint16_t top_h = 11;
|
2021-01-31 10:37:42 +00:00
|
|
|
const uint16_t top_pad = 1;
|
2021-01-03 08:38:54 +00:00
|
|
|
const uint16_t line1_h = 10;
|
2021-01-31 10:37:42 +00:00
|
|
|
const uint16_t line2_h = 10;
|
2023-08-31 18:37:55 +00:00
|
|
|
const uint16_t line3_h = 10;
|
|
|
|
const uint16_t line3_large_h = 16;
|
|
|
|
const uint16_t line4_h = 10;
|
2021-02-20 15:03:37 +00:00
|
|
|
const uint16_t menu_h = 10;
|
2021-05-09 09:19:02 +00:00
|
|
|
const uint16_t bottom_h = 15;
|
2021-02-20 14:14:35 +00:00
|
|
|
const uint16_t bottom_pad = 0;
|
2021-01-03 08:38:54 +00:00
|
|
|
const uint16_t status_v_pad = 1;
|
2021-01-31 10:37:42 +00:00
|
|
|
const uint16_t small_line_v_pad = 1;
|
|
|
|
const uint16_t big_line_v_pad = 0;
|
2020-12-06 15:16:42 +00:00
|
|
|
const uint16_t horizontal_pad = 4;
|
2020-11-16 08:03:03 +00:00
|
|
|
|
2021-01-03 10:22:24 +00:00
|
|
|
// Top bar font: 6 pt
|
2023-08-23 12:32:36 +00:00
|
|
|
const fontSize_t top_font = FONT_SIZE_6PT;
|
|
|
|
const symbolSize_t top_symbol_size = SYMBOLS_SIZE_6PT;
|
2021-01-03 10:22:24 +00:00
|
|
|
// Middle line fonts: 5, 8, 8 pt
|
2021-01-31 10:37:42 +00:00
|
|
|
const fontSize_t line1_font = FONT_SIZE_6PT;
|
2023-08-31 18:37:55 +00:00
|
|
|
const symbolSize_t line1_symbol_size = SYMBOLS_SIZE_6PT;
|
2021-01-31 10:37:42 +00:00
|
|
|
const fontSize_t line2_font = FONT_SIZE_6PT;
|
2023-08-31 18:37:55 +00:00
|
|
|
const symbolSize_t line2_symbol_size = SYMBOLS_SIZE_6PT;
|
|
|
|
const fontSize_t line3_font = FONT_SIZE_6PT;
|
|
|
|
const symbolSize_t line3_symbol_size = SYMBOLS_SIZE_6PT;
|
|
|
|
const fontSize_t line3_large_font = FONT_SIZE_10PT;
|
|
|
|
const fontSize_t line4_font = FONT_SIZE_6PT;
|
|
|
|
const symbolSize_t line4_symbol_size = SYMBOLS_SIZE_6PT;
|
2021-01-03 10:22:24 +00:00
|
|
|
// Bottom bar font: 6 pt
|
2020-12-04 19:49:04 +00:00
|
|
|
const fontSize_t bottom_font = FONT_SIZE_6PT;
|
2021-02-02 11:54:09 +00:00
|
|
|
// TimeDate/Frequency input font
|
|
|
|
const fontSize_t input_font = FONT_SIZE_8PT;
|
2021-02-20 15:03:37 +00:00
|
|
|
// Menu font
|
|
|
|
const fontSize_t menu_font = FONT_SIZE_6PT;
|
2021-05-06 11:03:41 +00:00
|
|
|
// Mode screen frequency font: 9 pt
|
|
|
|
const fontSize_t mode_font_big = FONT_SIZE_9PT;
|
|
|
|
// Mode screen details font: 6 pt
|
|
|
|
const fontSize_t mode_font_small = FONT_SIZE_6PT;
|
2020-12-11 13:40:56 +00:00
|
|
|
|
2020-12-27 16:42:27 +00:00
|
|
|
// Radioddity RD-5R
|
2020-11-16 08:03:03 +00:00
|
|
|
#elif SCREEN_HEIGHT > 47
|
|
|
|
|
|
|
|
// Height and padding shown in diagram at beginning of file
|
2021-01-03 08:38:54 +00:00
|
|
|
const uint16_t top_h = 11;
|
2021-01-31 10:37:42 +00:00
|
|
|
const uint16_t top_pad = 1;
|
2021-01-03 08:52:10 +00:00
|
|
|
const uint16_t line1_h = 0;
|
2021-01-31 10:37:42 +00:00
|
|
|
const uint16_t line2_h = 10;
|
2023-08-31 18:37:55 +00:00
|
|
|
const uint16_t line3_h = 10;
|
|
|
|
const uint16_t line3_large_h = 18;
|
|
|
|
const uint16_t line4_h = 10;
|
2021-02-20 15:03:37 +00:00
|
|
|
const uint16_t menu_h = 10;
|
2021-01-31 10:37:42 +00:00
|
|
|
const uint16_t bottom_h = 0;
|
|
|
|
const uint16_t bottom_pad = 0;
|
2021-01-03 08:38:54 +00:00
|
|
|
const uint16_t status_v_pad = 1;
|
2021-01-31 10:37:42 +00:00
|
|
|
const uint16_t small_line_v_pad = 1;
|
|
|
|
const uint16_t big_line_v_pad = 0;
|
|
|
|
const uint16_t horizontal_pad = 4;
|
2020-11-16 08:03:03 +00:00
|
|
|
|
2023-08-23 12:32:36 +00:00
|
|
|
// Top bar font: 6 pt
|
|
|
|
const fontSize_t top_font = FONT_SIZE_6PT;
|
|
|
|
const symbolSize_t top_symbol_size = SYMBOLS_SIZE_6PT;
|
2020-11-16 08:03:03 +00:00
|
|
|
// Middle line fonts: 16, 16
|
2021-01-31 10:37:42 +00:00
|
|
|
const fontSize_t line2_font = FONT_SIZE_6PT;
|
2023-08-31 18:37:55 +00:00
|
|
|
const fontSize_t line3_font = FONT_SIZE_6PT;
|
|
|
|
const fontSize_t line4_font = FONT_SIZE_6PT;
|
|
|
|
const fontSize_t line3_large_font = FONT_SIZE_12PT;
|
2021-02-02 11:54:09 +00:00
|
|
|
// TimeDate/Frequency input font
|
|
|
|
const fontSize_t input_font = FONT_SIZE_8PT;
|
2021-02-20 15:03:37 +00:00
|
|
|
// Menu font
|
|
|
|
const fontSize_t menu_font = FONT_SIZE_6PT;
|
2021-05-06 11:03:41 +00:00
|
|
|
// Mode screen frequency font: 9 pt
|
|
|
|
const fontSize_t mode_font_big = FONT_SIZE_9PT;
|
|
|
|
// Mode screen details font: 6 pt
|
|
|
|
const fontSize_t mode_font_small = FONT_SIZE_6PT;
|
2021-01-31 10:37:42 +00:00
|
|
|
// Not present on this resolution
|
2021-01-03 08:52:10 +00:00
|
|
|
const fontSize_t line1_font = 0;
|
2020-11-16 08:03:03 +00:00
|
|
|
const fontSize_t bottom_font = 0;
|
|
|
|
|
|
|
|
#else
|
|
|
|
#error Unsupported vertical resolution!
|
|
|
|
#endif
|
2020-10-31 17:12:44 +00:00
|
|
|
|
|
|
|
// Calculate printing positions
|
2021-01-30 19:04:04 +00:00
|
|
|
point_t top_pos = {horizontal_pad, top_h - status_v_pad - text_v_offset};
|
2021-01-31 10:37:42 +00:00
|
|
|
point_t line1_pos = {horizontal_pad, top_h + top_pad + line1_h - small_line_v_pad - text_v_offset};
|
|
|
|
point_t line2_pos = {horizontal_pad, top_h + top_pad + line1_h + line2_h - small_line_v_pad - text_v_offset};
|
2023-08-31 18:37:55 +00:00
|
|
|
point_t line3_pos = {horizontal_pad, top_h + top_pad + line1_h + line2_h + line3_h - small_line_v_pad - text_v_offset};
|
|
|
|
point_t line4_pos = {horizontal_pad, top_h + top_pad + line1_h + line2_h + line3_h + line4_h - small_line_v_pad - text_v_offset};
|
|
|
|
point_t line3_large_pos = {horizontal_pad, top_h + top_pad + line1_h + line2_h + line3_large_h - big_line_v_pad - text_v_offset};
|
2021-01-31 10:37:42 +00:00
|
|
|
point_t bottom_pos = {horizontal_pad, SCREEN_HEIGHT - bottom_pad - status_v_pad - text_v_offset};
|
2020-10-31 17:12:44 +00:00
|
|
|
|
2020-11-16 08:03:03 +00:00
|
|
|
layout_t new_layout =
|
|
|
|
{
|
2021-01-03 08:38:54 +00:00
|
|
|
hline_h,
|
2020-11-19 16:05:10 +00:00
|
|
|
top_h,
|
2020-12-06 20:24:25 +00:00
|
|
|
line1_h,
|
2020-12-27 16:42:27 +00:00
|
|
|
line2_h,
|
|
|
|
line3_h,
|
2023-08-31 18:37:55 +00:00
|
|
|
line3_large_h,
|
|
|
|
line4_h,
|
2021-02-20 15:03:37 +00:00
|
|
|
menu_h,
|
2020-11-19 16:05:10 +00:00
|
|
|
bottom_h,
|
2021-05-09 09:19:02 +00:00
|
|
|
bottom_pad,
|
2021-01-03 08:38:54 +00:00
|
|
|
status_v_pad,
|
2020-12-06 17:03:48 +00:00
|
|
|
horizontal_pad,
|
2021-01-03 08:38:54 +00:00
|
|
|
text_v_offset,
|
2021-01-30 19:04:04 +00:00
|
|
|
top_pos,
|
|
|
|
line1_pos,
|
|
|
|
line2_pos,
|
|
|
|
line3_pos,
|
2023-08-31 18:37:55 +00:00
|
|
|
line3_large_pos,
|
|
|
|
line4_pos,
|
2021-01-30 19:04:04 +00:00
|
|
|
bottom_pos,
|
2020-10-31 17:12:44 +00:00
|
|
|
top_font,
|
2023-08-23 12:32:36 +00:00
|
|
|
top_symbol_size,
|
2020-10-31 17:12:44 +00:00
|
|
|
line1_font,
|
2023-08-31 18:37:55 +00:00
|
|
|
line1_symbol_size,
|
2020-10-31 17:12:44 +00:00
|
|
|
line2_font,
|
2023-08-31 18:37:55 +00:00
|
|
|
line2_symbol_size,
|
2020-10-31 17:12:44 +00:00
|
|
|
line3_font,
|
2023-08-31 18:37:55 +00:00
|
|
|
line3_symbol_size,
|
|
|
|
line3_large_font,
|
|
|
|
line4_font,
|
|
|
|
line4_symbol_size,
|
2021-02-02 11:54:09 +00:00
|
|
|
bottom_font,
|
2021-02-20 15:03:37 +00:00
|
|
|
input_font,
|
2021-05-06 11:03:41 +00:00
|
|
|
menu_font,
|
|
|
|
mode_font_big,
|
|
|
|
mode_font_small
|
2020-10-31 17:12:44 +00:00
|
|
|
};
|
|
|
|
return new_layout;
|
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_drawLowBatteryScreen()
|
2020-12-11 13:40:56 +00:00
|
|
|
{
|
|
|
|
gfx_clearScreen();
|
|
|
|
uint16_t bat_width = SCREEN_WIDTH / 2;
|
|
|
|
uint16_t bat_height = SCREEN_HEIGHT / 3;
|
|
|
|
point_t bat_pos = {SCREEN_WIDTH / 4, SCREEN_HEIGHT / 8};
|
2021-08-14 10:56:45 +00:00
|
|
|
gfx_drawBattery(bat_pos, bat_width, bat_height, 10);
|
2020-12-11 13:40:56 +00:00
|
|
|
point_t text_pos_1 = {0, SCREEN_HEIGHT * 2 / 3};
|
|
|
|
point_t text_pos_2 = {0, SCREEN_HEIGHT * 2 / 3 + 16};
|
|
|
|
|
|
|
|
gfx_print(text_pos_1,
|
|
|
|
FONT_SIZE_6PT,
|
|
|
|
TEXT_ALIGN_CENTER,
|
2021-04-04 20:15:07 +00:00
|
|
|
color_white,
|
2022-05-12 06:06:29 +00:00
|
|
|
currentLanguage->forEmergencyUse);
|
2020-12-11 13:40:56 +00:00
|
|
|
gfx_print(text_pos_2,
|
|
|
|
FONT_SIZE_6PT,
|
|
|
|
TEXT_ALIGN_CENTER,
|
2021-04-04 20:15:07 +00:00
|
|
|
color_white,
|
2022-05-12 06:06:29 +00:00
|
|
|
currentLanguage->pressAnyButton);
|
2020-12-11 13:40:56 +00:00
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static freq_t _ui_freq_add_digit(freq_t freq, uint8_t pos, uint8_t number)
|
2020-12-31 12:51:27 +00:00
|
|
|
{
|
2022-09-02 05:54:32 +00:00
|
|
|
freq_t coefficient = 100;
|
2020-12-31 12:51:27 +00:00
|
|
|
for(uint8_t i=0; i < FREQ_DIGITS - pos; i++)
|
|
|
|
{
|
|
|
|
coefficient *= 10;
|
|
|
|
}
|
|
|
|
return freq += number * coefficient;
|
|
|
|
}
|
|
|
|
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef RTC_PRESENT
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_timedate_add_digit(datetime_t *timedate, uint8_t pos,
|
|
|
|
uint8_t number)
|
2020-12-31 15:36:32 +00:00
|
|
|
{
|
2022-09-05 13:03:41 +00:00
|
|
|
vp_flush();
|
2022-09-05 23:23:54 +00:00
|
|
|
vp_queueInteger(number);
|
|
|
|
if (pos == 2 || pos == 4)
|
2022-09-05 13:03:41 +00:00
|
|
|
vp_queuePrompt(PROMPT_SLASH);
|
|
|
|
// just indicates separation of date and time.
|
2022-09-05 23:23:54 +00:00
|
|
|
if (pos==6) // start of time.
|
|
|
|
vp_queueString("hh:mm", vpAnnounceCommonSymbols|vpAnnounceLessCommonSymbols);
|
|
|
|
if (pos == 8)
|
2022-09-05 13:03:41 +00:00
|
|
|
vp_queuePrompt(PROMPT_COLON);
|
|
|
|
vp_play();
|
|
|
|
|
2020-12-31 18:05:29 +00:00
|
|
|
switch(pos)
|
|
|
|
{
|
|
|
|
// Set date
|
|
|
|
case 1:
|
2021-01-13 19:04:12 +00:00
|
|
|
timedate->date += number * 10;
|
2020-12-31 18:05:29 +00:00
|
|
|
break;
|
|
|
|
case 2:
|
2021-01-13 19:04:12 +00:00
|
|
|
timedate->date += number;
|
2020-12-31 18:05:29 +00:00
|
|
|
break;
|
|
|
|
// Set month
|
|
|
|
case 3:
|
2021-01-13 19:04:12 +00:00
|
|
|
timedate->month += number * 10;
|
2020-12-31 18:05:29 +00:00
|
|
|
break;
|
|
|
|
case 4:
|
2021-01-13 19:04:12 +00:00
|
|
|
timedate->month += number;
|
2020-12-31 18:05:29 +00:00
|
|
|
break;
|
|
|
|
// Set year
|
|
|
|
case 5:
|
2021-01-13 19:04:12 +00:00
|
|
|
timedate->year += number * 10;
|
2020-12-31 18:05:29 +00:00
|
|
|
break;
|
|
|
|
case 6:
|
2021-01-13 19:04:12 +00:00
|
|
|
timedate->year += number;
|
2020-12-31 18:05:29 +00:00
|
|
|
break;
|
|
|
|
// Set hour
|
|
|
|
case 7:
|
2021-01-13 19:04:12 +00:00
|
|
|
timedate->hour += number * 10;
|
2020-12-31 18:05:29 +00:00
|
|
|
break;
|
|
|
|
case 8:
|
2021-01-13 19:04:12 +00:00
|
|
|
timedate->hour += number;
|
2020-12-31 18:05:29 +00:00
|
|
|
break;
|
|
|
|
// Set minute
|
|
|
|
case 9:
|
2021-01-13 19:04:12 +00:00
|
|
|
timedate->minute += number * 10;
|
2020-12-31 18:05:29 +00:00
|
|
|
break;
|
|
|
|
case 10:
|
2021-01-13 19:04:12 +00:00
|
|
|
timedate->minute += number;
|
2020-12-31 18:05:29 +00:00
|
|
|
break;
|
|
|
|
}
|
2020-12-31 15:36:32 +00:00
|
|
|
}
|
2021-01-01 17:58:35 +00:00
|
|
|
#endif
|
2020-12-31 15:36:32 +00:00
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static bool _ui_freq_check_limits(freq_t freq)
|
2020-12-31 13:51:19 +00:00
|
|
|
{
|
|
|
|
bool valid = false;
|
2021-06-05 08:47:52 +00:00
|
|
|
const hwInfo_t* hwinfo = platform_getHwInfo();
|
|
|
|
if(hwinfo->vhf_band)
|
|
|
|
{
|
|
|
|
// hwInfo_t frequencies are in MHz
|
2021-08-14 10:56:45 +00:00
|
|
|
if(freq >= (hwinfo->vhf_minFreq * 1000000) &&
|
2021-06-05 08:47:52 +00:00
|
|
|
freq <= (hwinfo->vhf_maxFreq * 1000000))
|
2021-08-14 10:56:45 +00:00
|
|
|
valid = true;
|
2021-06-05 08:47:52 +00:00
|
|
|
}
|
|
|
|
if(hwinfo->uhf_band)
|
|
|
|
{
|
|
|
|
// hwInfo_t frequencies are in MHz
|
2021-08-14 10:56:45 +00:00
|
|
|
if(freq >= (hwinfo->uhf_minFreq * 1000000) &&
|
2021-06-05 08:47:52 +00:00
|
|
|
freq <= (hwinfo->uhf_maxFreq * 1000000))
|
2021-08-14 10:56:45 +00:00
|
|
|
valid = true;
|
2021-06-05 08:47:52 +00:00
|
|
|
}
|
2020-12-31 13:51:19 +00:00
|
|
|
return valid;
|
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static bool _ui_channel_valid(channel_t* channel)
|
2021-01-10 09:18:29 +00:00
|
|
|
{
|
|
|
|
return _ui_freq_check_limits(channel->rx_frequency) &&
|
|
|
|
_ui_freq_check_limits(channel->tx_frequency);
|
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static bool _ui_drawDarkOverlay()
|
|
|
|
{
|
2021-01-02 19:07:13 +00:00
|
|
|
color_t alpha_grey = {0, 0, 0, 255};
|
2020-12-21 15:47:34 +00:00
|
|
|
point_t origin = {0, 0};
|
|
|
|
gfx_drawRect(origin, SCREEN_WIDTH, SCREEN_HEIGHT, alpha_grey, true);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static int _ui_fsm_loadChannel(int16_t channel_index, bool *sync_rtx)
|
|
|
|
{
|
2021-01-13 19:27:39 +00:00
|
|
|
channel_t channel;
|
2022-04-05 14:17:58 +00:00
|
|
|
int32_t selected_channel = channel_index;
|
2022-03-26 12:42:10 +00:00
|
|
|
// If a bank is active, get index from current bank
|
|
|
|
if(state.bank_enabled)
|
2021-01-31 13:14:54 +00:00
|
|
|
{
|
2022-03-29 16:31:39 +00:00
|
|
|
bankHdr_t bank = { 0 };
|
|
|
|
cps_readBankHeader(&bank, state.bank);
|
2022-04-05 14:17:58 +00:00
|
|
|
if((channel_index < 0) || (channel_index >= bank.ch_count))
|
2021-01-31 13:14:54 +00:00
|
|
|
return -1;
|
2022-04-05 14:17:58 +00:00
|
|
|
channel_index = cps_readBankData(state.bank, channel_index);
|
2021-01-31 13:14:54 +00:00
|
|
|
}
|
2022-08-16 19:39:47 +00:00
|
|
|
|
2022-04-04 17:43:21 +00:00
|
|
|
int result = cps_readChannel(&channel, channel_index);
|
2021-01-13 19:27:39 +00:00
|
|
|
// Read successful and channel is valid
|
2022-08-16 19:39:47 +00:00
|
|
|
if((result != -1) && _ui_channel_valid(&channel))
|
2021-01-13 19:27:39 +00:00
|
|
|
{
|
|
|
|
// Set new channel index
|
2022-04-05 14:17:58 +00:00
|
|
|
state.channel_index = selected_channel;
|
2021-01-13 19:27:39 +00:00
|
|
|
// Copy channel read to state
|
|
|
|
state.channel = channel;
|
|
|
|
*sync_rtx = true;
|
|
|
|
}
|
2022-08-16 19:39:47 +00:00
|
|
|
|
2021-01-13 19:27:39 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_fsm_confirmVFOInput(bool *sync_rtx)
|
2022-02-26 14:23:08 +00:00
|
|
|
{
|
2022-08-31 10:37:34 +00:00
|
|
|
vp_flush();
|
2021-01-13 19:43:39 +00:00
|
|
|
// Switch to TX input
|
|
|
|
if(ui_state.input_set == SET_RX)
|
|
|
|
{
|
|
|
|
ui_state.input_set = SET_TX;
|
|
|
|
// Reset input position
|
|
|
|
ui_state.input_position = 0;
|
2022-08-16 19:39:47 +00:00
|
|
|
// announce the rx frequency just confirmed with Enter.
|
|
|
|
vp_queueFrequency(ui_state.new_rx_frequency);
|
|
|
|
// defer playing till the end.
|
|
|
|
// indicate that the user has moved to the tx freq field.
|
|
|
|
vp_announceInputReceiveOrTransmit(true, vpqDefault);
|
2021-01-13 19:43:39 +00:00
|
|
|
}
|
|
|
|
else if(ui_state.input_set == SET_TX)
|
|
|
|
{
|
|
|
|
// Save new frequency setting
|
|
|
|
// If TX frequency was not set, TX = RX
|
|
|
|
if(ui_state.new_tx_frequency == 0)
|
|
|
|
{
|
2021-06-05 08:08:15 +00:00
|
|
|
ui_state.new_tx_frequency = ui_state.new_rx_frequency;
|
2021-01-13 19:43:39 +00:00
|
|
|
}
|
2021-06-05 08:08:15 +00:00
|
|
|
// Apply new frequencies if they are valid
|
|
|
|
if(_ui_freq_check_limits(ui_state.new_rx_frequency) &&
|
|
|
|
_ui_freq_check_limits(ui_state.new_tx_frequency))
|
2021-01-13 19:43:39 +00:00
|
|
|
{
|
2021-06-05 08:08:15 +00:00
|
|
|
state.channel.rx_frequency = ui_state.new_rx_frequency;
|
|
|
|
state.channel.tx_frequency = ui_state.new_tx_frequency;
|
|
|
|
*sync_rtx = true;
|
2022-08-16 19:39:47 +00:00
|
|
|
// force init to clear any prompts in progress.
|
|
|
|
// defer play because play is called at the end of the function
|
|
|
|
//due to above freq queuing.
|
|
|
|
vp_announceFrequencies(state.channel.rx_frequency,
|
|
|
|
state.channel.tx_frequency, vpqInit);
|
2021-01-13 19:43:39 +00:00
|
|
|
}
|
2022-08-16 19:39:47 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
vp_announceError(vpqInit);
|
|
|
|
}
|
|
|
|
|
2021-01-13 19:43:39 +00:00
|
|
|
state.ui_screen = MAIN_VFO;
|
|
|
|
}
|
2022-08-16 19:39:47 +00:00
|
|
|
|
|
|
|
vp_play();
|
2021-01-13 19:43:39 +00:00
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_fsm_insertVFONumber(kbd_msg_t msg, bool *sync_rtx)
|
2022-02-26 14:23:08 +00:00
|
|
|
{
|
2021-01-13 19:43:39 +00:00
|
|
|
// Advance input position
|
|
|
|
ui_state.input_position += 1;
|
2022-08-16 19:39:47 +00:00
|
|
|
// clear any prompts in progress.
|
2022-08-31 10:37:34 +00:00
|
|
|
vp_flush();
|
2021-01-13 19:43:39 +00:00
|
|
|
// Save pressed number to calculate frequency and show in GUI
|
|
|
|
ui_state.input_number = input_getPressedNumber(msg);
|
2022-08-16 19:39:47 +00:00
|
|
|
// queue the digit just pressed.
|
|
|
|
vp_queueInteger(ui_state.input_number);
|
|
|
|
// queue point if user has entered three digits.
|
|
|
|
if (ui_state.input_position == 3)
|
|
|
|
vp_queuePrompt(PROMPT_POINT);
|
2022-05-11 11:50:51 +00:00
|
|
|
|
2021-01-13 19:43:39 +00:00
|
|
|
if(ui_state.input_set == SET_RX)
|
|
|
|
{
|
|
|
|
if(ui_state.input_position == 1)
|
|
|
|
ui_state.new_rx_frequency = 0;
|
|
|
|
// Calculate portion of the new RX frequency
|
2021-01-29 19:35:48 +00:00
|
|
|
ui_state.new_rx_frequency = _ui_freq_add_digit(ui_state.new_rx_frequency,
|
2022-08-16 19:39:47 +00:00
|
|
|
ui_state.input_position,
|
|
|
|
ui_state.input_number);
|
2021-01-13 19:43:39 +00:00
|
|
|
if(ui_state.input_position >= FREQ_DIGITS)
|
2022-05-11 11:50:51 +00:00
|
|
|
{// queue the rx freq just completed.
|
2022-08-16 19:39:47 +00:00
|
|
|
vp_queueFrequency(ui_state.new_rx_frequency);
|
|
|
|
/// now queue tx as user has changed fields.
|
|
|
|
vp_queuePrompt(PROMPT_TRANSMIT);
|
2021-01-13 19:43:39 +00:00
|
|
|
// Switch to TX input
|
|
|
|
ui_state.input_set = SET_TX;
|
|
|
|
// Reset input position
|
|
|
|
ui_state.input_position = 0;
|
|
|
|
// Reset TX frequency
|
|
|
|
ui_state.new_tx_frequency = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(ui_state.input_set == SET_TX)
|
|
|
|
{
|
|
|
|
if(ui_state.input_position == 1)
|
|
|
|
ui_state.new_tx_frequency = 0;
|
|
|
|
// Calculate portion of the new TX frequency
|
2021-01-29 19:35:48 +00:00
|
|
|
ui_state.new_tx_frequency = _ui_freq_add_digit(ui_state.new_tx_frequency,
|
2022-08-16 19:39:47 +00:00
|
|
|
ui_state.input_position,
|
|
|
|
ui_state.input_number);
|
2021-01-13 19:43:39 +00:00
|
|
|
if(ui_state.input_position >= FREQ_DIGITS)
|
|
|
|
{
|
|
|
|
// Save both inserted frequencies
|
2021-01-29 19:35:48 +00:00
|
|
|
if(_ui_freq_check_limits(ui_state.new_rx_frequency) &&
|
2021-01-13 19:43:39 +00:00
|
|
|
_ui_freq_check_limits(ui_state.new_tx_frequency))
|
|
|
|
{
|
|
|
|
state.channel.rx_frequency = ui_state.new_rx_frequency;
|
|
|
|
state.channel.tx_frequency = ui_state.new_tx_frequency;
|
|
|
|
*sync_rtx = true;
|
2022-08-16 19:39:47 +00:00
|
|
|
// play is called at end.
|
|
|
|
vp_announceFrequencies(state.channel.rx_frequency,
|
|
|
|
state.channel.tx_frequency, vpqInit);
|
2021-01-13 19:43:39 +00:00
|
|
|
}
|
2022-08-16 19:39:47 +00:00
|
|
|
|
2021-01-13 19:43:39 +00:00
|
|
|
state.ui_screen = MAIN_VFO;
|
|
|
|
}
|
|
|
|
}
|
2022-08-16 19:39:47 +00:00
|
|
|
|
|
|
|
vp_play();
|
2021-01-13 19:43:39 +00:00
|
|
|
}
|
|
|
|
|
2023-08-07 18:36:22 +00:00
|
|
|
#ifdef SCREEN_BRIGHTNESS
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_changeBrightness(int variation)
|
2021-01-29 21:41:42 +00:00
|
|
|
{
|
2022-02-26 14:23:08 +00:00
|
|
|
state.settings.brightness += variation;
|
|
|
|
|
|
|
|
// Max value for brightness is 100, min value is set to 5 to avoid complete
|
|
|
|
// display shutdown.
|
|
|
|
if(state.settings.brightness > 100) state.settings.brightness = 100;
|
|
|
|
if(state.settings.brightness < 5) state.settings.brightness = 5;
|
|
|
|
|
2023-07-13 15:30:52 +00:00
|
|
|
display_setBacklightLevel(state.settings.brightness);
|
2021-01-29 21:41:42 +00:00
|
|
|
}
|
2023-08-07 18:36:22 +00:00
|
|
|
#endif
|
2021-01-29 21:41:42 +00:00
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
#ifdef SCREEN_CONTRAST
|
|
|
|
static void _ui_changeContrast(int variation)
|
2021-01-29 21:41:42 +00:00
|
|
|
{
|
|
|
|
if(variation >= 0)
|
2021-02-24 20:00:30 +00:00
|
|
|
state.settings.contrast =
|
2021-02-13 19:32:53 +00:00
|
|
|
(255 - state.settings.contrast < variation) ? 255 : state.settings.contrast + variation;
|
2021-01-29 21:41:42 +00:00
|
|
|
else
|
2021-02-24 20:00:30 +00:00
|
|
|
state.settings.contrast =
|
2021-02-13 19:32:53 +00:00
|
|
|
(state.settings.contrast < -variation) ? 0 : state.settings.contrast + variation;
|
2022-08-16 19:39:47 +00:00
|
|
|
|
2021-02-13 19:32:53 +00:00
|
|
|
display_setContrast(state.settings.contrast);
|
2021-01-29 21:41:42 +00:00
|
|
|
}
|
2022-08-16 19:39:47 +00:00
|
|
|
#endif
|
2021-01-29 21:41:42 +00:00
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_changeTimer(int variation)
|
2021-12-13 22:18:01 +00:00
|
|
|
{
|
2021-12-21 08:15:50 +00:00
|
|
|
if ((state.settings.display_timer == TIMER_OFF && variation < 0) ||
|
|
|
|
(state.settings.display_timer == TIMER_1H && variation > 0))
|
2021-12-13 22:18:01 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-12-21 08:15:50 +00:00
|
|
|
state.settings.display_timer += variation;
|
2021-12-13 22:18:01 +00:00
|
|
|
}
|
|
|
|
|
2023-05-28 11:35:13 +00:00
|
|
|
static inline void _ui_changeM17Can(int variation)
|
|
|
|
{
|
|
|
|
uint8_t can = state.settings.m17_can;
|
|
|
|
state.settings.m17_can = (can + variation) % 16;
|
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_changeVoiceLevel(int variation)
|
2022-05-18 11:18:12 +00:00
|
|
|
{
|
2022-08-16 19:39:47 +00:00
|
|
|
if ((state.settings.vpLevel == vpNone && variation < 0) ||
|
2022-05-18 11:18:12 +00:00
|
|
|
(state.settings.vpLevel == vpHigh && variation > 0))
|
2022-08-16 19:39:47 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
state.settings.vpLevel += variation;
|
2022-08-26 14:58:43 +00:00
|
|
|
|
|
|
|
// Force these flags to ensure the changes are spoken for levels 1 through 3.
|
|
|
|
vpQueueFlags_t flags = vpqInit
|
|
|
|
| vpqAddSeparatingSilence
|
|
|
|
| vpqPlayImmediately;
|
|
|
|
|
|
|
|
if (!vp_isPlaying())
|
|
|
|
{
|
|
|
|
flags |= vpqIncludeDescriptions;
|
|
|
|
}
|
|
|
|
|
|
|
|
vp_announceSettingsVoiceLevel(flags);
|
2022-05-18 11:18:12 +00:00
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_changePhoneticSpell(bool newVal)
|
2022-05-18 11:18:12 +00:00
|
|
|
{
|
2022-08-16 19:39:47 +00:00
|
|
|
state.settings.vpPhoneticSpell = newVal ? 1 : 0;
|
2022-08-26 15:03:13 +00:00
|
|
|
|
|
|
|
vp_announceSettingsOnOffToggle(¤tLanguage->phonetic,
|
|
|
|
vp_getVoiceLevelQueueFlags(),
|
|
|
|
state.settings.vpPhoneticSpell);
|
2022-05-18 11:18:12 +00:00
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static bool _ui_checkStandby(long long time_since_last_event)
|
2021-12-13 20:52:19 +00:00
|
|
|
{
|
|
|
|
if (standby)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-12-21 08:15:50 +00:00
|
|
|
switch (state.settings.display_timer)
|
2021-12-13 20:52:19 +00:00
|
|
|
{
|
2022-08-16 19:39:47 +00:00
|
|
|
case TIMER_OFF:
|
|
|
|
return false;
|
|
|
|
case TIMER_5S:
|
|
|
|
case TIMER_10S:
|
|
|
|
case TIMER_15S:
|
|
|
|
case TIMER_20S:
|
|
|
|
case TIMER_25S:
|
|
|
|
case TIMER_30S:
|
|
|
|
return time_since_last_event >= (5000 * state.settings.display_timer);
|
|
|
|
case TIMER_1M:
|
|
|
|
case TIMER_2M:
|
|
|
|
case TIMER_3M:
|
|
|
|
case TIMER_4M:
|
|
|
|
case TIMER_5M:
|
|
|
|
return time_since_last_event >=
|
|
|
|
(60000 * (state.settings.display_timer - (TIMER_1M - 1)));
|
|
|
|
case TIMER_15M:
|
|
|
|
case TIMER_30M:
|
|
|
|
case TIMER_45M:
|
|
|
|
return time_since_last_event >=
|
|
|
|
(60000 * 15 * (state.settings.display_timer - (TIMER_15M - 1)));
|
|
|
|
case TIMER_1H:
|
|
|
|
return time_since_last_event >= 60 * 60 * 1000;
|
2021-12-13 20:52:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// unreachable code
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_enterStandby()
|
2021-11-22 22:06:11 +00:00
|
|
|
{
|
|
|
|
if(standby)
|
|
|
|
return;
|
|
|
|
|
|
|
|
standby = true;
|
2022-08-04 20:48:41 +00:00
|
|
|
redraw_needed = false;
|
2023-07-13 15:30:52 +00:00
|
|
|
display_setBacklightLevel(0);
|
2021-11-22 22:06:11 +00:00
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static bool _ui_exitStandby(long long now)
|
2021-11-22 22:06:11 +00:00
|
|
|
{
|
|
|
|
last_event_tick = now;
|
|
|
|
|
|
|
|
if(!standby)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
standby = false;
|
2022-08-04 20:48:41 +00:00
|
|
|
redraw_needed = true;
|
2023-07-13 15:30:52 +00:00
|
|
|
display_setBacklightLevel(state.settings.brightness);
|
2023-08-07 18:36:22 +00:00
|
|
|
|
2021-11-22 22:06:11 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_fsm_menuMacro(kbd_msg_t msg, bool *sync_rtx)
|
2022-02-26 14:23:08 +00:00
|
|
|
{
|
2023-09-08 07:48:03 +00:00
|
|
|
// If there is no keyboard left and right select the menu entry to edit
|
|
|
|
#if defined(UI_NO_KEYBOARD)
|
|
|
|
if (msg.keys & KNOB_LEFT)
|
|
|
|
{
|
|
|
|
ui_state.macro_menu_selected--;
|
|
|
|
ui_state.macro_menu_selected += 9;
|
|
|
|
ui_state.macro_menu_selected %= 9;
|
|
|
|
}
|
|
|
|
if (msg.keys & KNOB_RIGHT)
|
|
|
|
{
|
|
|
|
ui_state.macro_menu_selected++;
|
|
|
|
ui_state.macro_menu_selected %= 9;
|
|
|
|
}
|
|
|
|
if ((msg.keys & KEY_ENTER) && !msg.long_press)
|
|
|
|
ui_state.input_number = ui_state.macro_menu_selected + 1;
|
|
|
|
else
|
|
|
|
ui_state.input_number = 0;
|
|
|
|
#else // UI_NO_KEYBOARD
|
2021-01-13 19:50:35 +00:00
|
|
|
ui_state.input_number = input_getPressedNumber(msg);
|
2023-09-08 07:48:03 +00:00
|
|
|
#endif // UI_NO_KEYBOARD
|
2021-01-13 19:50:35 +00:00
|
|
|
// CTCSS Encode/Decode Selection
|
|
|
|
bool tone_tx_enable = state.channel.fm.txToneEn;
|
|
|
|
bool tone_rx_enable = state.channel.fm.rxToneEn;
|
|
|
|
uint8_t tone_flags = tone_tx_enable << 1 | tone_rx_enable;
|
2022-08-16 19:39:47 +00:00
|
|
|
vpQueueFlags_t queueFlags = vp_getVoiceLevelQueueFlags();
|
|
|
|
|
2021-01-13 19:50:35 +00:00
|
|
|
switch(ui_state.input_number)
|
|
|
|
{
|
|
|
|
case 1:
|
2021-11-08 12:50:36 +00:00
|
|
|
if(state.channel.mode == OPMODE_FM)
|
2021-07-04 14:09:31 +00:00
|
|
|
{
|
2023-06-28 17:52:53 +00:00
|
|
|
if(state.channel.fm.txTone == 0)
|
|
|
|
{
|
|
|
|
state.channel.fm.txTone = MAX_TONE_INDEX-1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
state.channel.fm.txTone--;
|
|
|
|
}
|
|
|
|
|
2021-07-04 14:09:31 +00:00
|
|
|
state.channel.fm.txTone %= MAX_TONE_INDEX;
|
|
|
|
state.channel.fm.rxTone = state.channel.fm.txTone;
|
|
|
|
*sync_rtx = true;
|
2022-08-16 19:39:47 +00:00
|
|
|
vp_announceCTCSS(state.channel.fm.rxToneEn,
|
|
|
|
state.channel.fm.rxTone,
|
|
|
|
state.channel.fm.txToneEn,
|
|
|
|
state.channel.fm.txTone,
|
|
|
|
queueFlags);
|
2021-07-04 14:09:31 +00:00
|
|
|
}
|
2021-01-13 19:50:35 +00:00
|
|
|
break;
|
2022-08-16 19:39:47 +00:00
|
|
|
|
2021-01-13 19:50:35 +00:00
|
|
|
case 2:
|
2022-09-25 18:55:35 +00:00
|
|
|
if(state.channel.mode == OPMODE_FM)
|
|
|
|
{
|
2022-09-27 20:28:57 +00:00
|
|
|
state.channel.fm.txTone++;
|
2022-09-25 18:55:35 +00:00
|
|
|
state.channel.fm.txTone %= MAX_TONE_INDEX;
|
|
|
|
state.channel.fm.rxTone = state.channel.fm.txTone;
|
|
|
|
*sync_rtx = true;
|
2022-09-27 22:52:29 +00:00
|
|
|
vp_announceCTCSS(state.channel.fm.rxToneEn,
|
|
|
|
state.channel.fm.rxTone,
|
|
|
|
state.channel.fm.txToneEn,
|
|
|
|
state.channel.fm.txTone,
|
|
|
|
queueFlags);
|
2022-09-25 18:55:35 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
2021-11-08 12:50:36 +00:00
|
|
|
if(state.channel.mode == OPMODE_FM)
|
2021-07-04 14:09:31 +00:00
|
|
|
{
|
|
|
|
tone_flags++;
|
|
|
|
tone_flags %= 4;
|
|
|
|
tone_tx_enable = tone_flags >> 1;
|
|
|
|
tone_rx_enable = tone_flags & 1;
|
|
|
|
state.channel.fm.txToneEn = tone_tx_enable;
|
|
|
|
state.channel.fm.rxToneEn = tone_rx_enable;
|
|
|
|
*sync_rtx = true;
|
2022-08-16 19:39:47 +00:00
|
|
|
vp_announceCTCSS(state.channel.fm.rxToneEn,
|
|
|
|
state.channel.fm.rxTone,
|
|
|
|
state.channel.fm.txToneEn,
|
|
|
|
state.channel.fm.txTone,
|
2022-09-06 07:57:53 +00:00
|
|
|
queueFlags |vpqIncludeDescriptions);
|
2021-07-04 14:09:31 +00:00
|
|
|
}
|
2021-01-13 19:50:35 +00:00
|
|
|
break;
|
|
|
|
case 4:
|
2021-11-08 12:50:36 +00:00
|
|
|
if(state.channel.mode == OPMODE_FM)
|
2021-07-04 14:09:31 +00:00
|
|
|
{
|
|
|
|
state.channel.bandwidth++;
|
|
|
|
state.channel.bandwidth %= 3;
|
|
|
|
*sync_rtx = true;
|
2022-08-16 19:39:47 +00:00
|
|
|
vp_announceBandwidth(state.channel.bandwidth, queueFlags);
|
2021-07-04 14:09:31 +00:00
|
|
|
}
|
2021-01-13 19:50:35 +00:00
|
|
|
break;
|
2021-01-26 20:19:11 +00:00
|
|
|
case 5:
|
2021-08-23 20:05:13 +00:00
|
|
|
// Cycle through radio modes
|
2021-11-08 12:50:36 +00:00
|
|
|
if(state.channel.mode == OPMODE_FM)
|
|
|
|
state.channel.mode = OPMODE_M17;
|
|
|
|
else if(state.channel.mode == OPMODE_M17)
|
|
|
|
state.channel.mode = OPMODE_FM;
|
2022-10-16 20:52:13 +00:00
|
|
|
else //catch any invalid states so they don't get locked out
|
|
|
|
state.channel.mode = OPMODE_FM;
|
2021-01-26 20:19:11 +00:00
|
|
|
*sync_rtx = true;
|
2022-08-16 19:39:47 +00:00
|
|
|
vp_announceRadioMode(state.channel.mode, queueFlags);
|
2022-09-27 20:28:57 +00:00
|
|
|
break;
|
2022-09-25 18:55:35 +00:00
|
|
|
case 6:
|
|
|
|
if (state.channel.power == 100)
|
|
|
|
state.channel.power = 135;
|
|
|
|
else
|
|
|
|
state.channel.power = 100;
|
|
|
|
*sync_rtx = true;
|
2022-09-05 15:36:07 +00:00
|
|
|
float power = dBmToWatt(state.channel.power);
|
|
|
|
vp_anouncePower(power, queueFlags);
|
2021-01-26 20:19:11 +00:00
|
|
|
break;
|
2023-08-07 18:36:22 +00:00
|
|
|
#ifdef SCREEN_BRIGHTNESS
|
2021-01-13 19:50:35 +00:00
|
|
|
case 7:
|
2022-09-27 20:28:57 +00:00
|
|
|
_ui_changeBrightness(-5);
|
2022-09-02 11:02:53 +00:00
|
|
|
vp_announceSettingsInt(¤tLanguage->brightness, queueFlags,
|
|
|
|
state.settings.brightness);
|
2021-01-13 19:50:35 +00:00
|
|
|
break;
|
|
|
|
case 8:
|
2022-09-27 20:28:57 +00:00
|
|
|
_ui_changeBrightness(+5);
|
2022-09-02 11:02:53 +00:00
|
|
|
vp_announceSettingsInt(¤tLanguage->brightness, queueFlags,
|
|
|
|
state.settings.brightness);
|
2021-01-13 19:50:35 +00:00
|
|
|
break;
|
2023-08-07 18:36:22 +00:00
|
|
|
#endif
|
2023-08-23 23:03:02 +00:00
|
|
|
case 9:
|
|
|
|
if (!ui_state.input_locked)
|
|
|
|
ui_state.input_locked = true;
|
|
|
|
else
|
|
|
|
ui_state.input_locked = false;
|
|
|
|
break;
|
2021-01-13 19:50:35 +00:00
|
|
|
}
|
2021-01-28 11:51:22 +00:00
|
|
|
|
2023-09-10 11:04:38 +00:00
|
|
|
#if defined(PLATFORM_TTWRPLUS)
|
|
|
|
if(msg.keys & KEY_VOLDOWN)
|
|
|
|
#else
|
2021-11-08 20:44:33 +00:00
|
|
|
if(msg.keys & KEY_LEFT || msg.keys & KEY_DOWN || msg.keys & KNOB_LEFT)
|
2023-09-10 11:04:38 +00:00
|
|
|
#endif // PLATFORM_TTWRPLUS
|
2021-11-08 20:44:33 +00:00
|
|
|
{
|
2023-09-10 11:04:38 +00:00
|
|
|
#ifdef HAS_ABSOLUTE_KNOB // If the radio has an absolute position knob
|
|
|
|
state.settings.sqlLevel = platform_getChSelector() - 1;
|
|
|
|
#endif // HAS_ABSOLUTE_KNOB
|
2021-11-08 20:44:33 +00:00
|
|
|
if(state.settings.sqlLevel > 0)
|
|
|
|
{
|
|
|
|
state.settings.sqlLevel -= 1;
|
|
|
|
*sync_rtx = true;
|
2022-08-16 19:39:47 +00:00
|
|
|
vp_announceSquelch(state.settings.sqlLevel, queueFlags);
|
2021-11-08 20:44:33 +00:00
|
|
|
}
|
2021-01-28 11:51:22 +00:00
|
|
|
}
|
2021-11-22 20:07:40 +00:00
|
|
|
|
2023-09-10 11:04:38 +00:00
|
|
|
#if defined(PLATFORM_TTWRPLUS)
|
|
|
|
else if(msg.keys & KEY_VOLUP)
|
2021-11-22 20:07:40 +00:00
|
|
|
#else
|
2021-11-08 20:44:33 +00:00
|
|
|
else if(msg.keys & KEY_RIGHT || msg.keys & KEY_UP || msg.keys & KNOB_RIGHT)
|
2023-09-10 11:04:38 +00:00
|
|
|
#endif // PLATFORM_TTWRPLUS
|
2021-11-08 20:44:33 +00:00
|
|
|
{
|
2023-09-10 11:04:38 +00:00
|
|
|
#ifdef HAS_ABSOLUTE_KNOB
|
|
|
|
state.settings.sqlLevel = platform_getChSelector() - 1;
|
|
|
|
#endif
|
2021-11-08 20:44:33 +00:00
|
|
|
if(state.settings.sqlLevel < 15)
|
|
|
|
{
|
|
|
|
state.settings.sqlLevel += 1;
|
|
|
|
*sync_rtx = true;
|
2022-08-16 19:39:47 +00:00
|
|
|
vp_announceSquelch(state.settings.sqlLevel, queueFlags);
|
2021-11-08 20:44:33 +00:00
|
|
|
}
|
2021-01-28 11:51:22 +00:00
|
|
|
}
|
2021-01-13 19:50:35 +00:00
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_menuUp(uint8_t menu_entries)
|
2021-02-13 15:35:03 +00:00
|
|
|
{
|
|
|
|
if(ui_state.menu_selected > 0)
|
|
|
|
ui_state.menu_selected -= 1;
|
|
|
|
else
|
|
|
|
ui_state.menu_selected = menu_entries - 1;
|
2022-09-06 02:18:45 +00:00
|
|
|
vp_playMenuBeepIfNeeded(ui_state.menu_selected==0);
|
2021-02-13 15:35:03 +00:00
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_menuDown(uint8_t menu_entries)
|
2021-02-13 15:35:03 +00:00
|
|
|
{
|
|
|
|
if(ui_state.menu_selected < menu_entries - 1)
|
|
|
|
ui_state.menu_selected += 1;
|
|
|
|
else
|
|
|
|
ui_state.menu_selected = 0;
|
2022-09-06 02:18:45 +00:00
|
|
|
vp_playMenuBeepIfNeeded(ui_state.menu_selected==0);
|
2021-02-13 15:35:03 +00:00
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_menuBack(uint8_t prev_state)
|
2021-02-13 20:29:25 +00:00
|
|
|
{
|
|
|
|
if(ui_state.edit_mode)
|
|
|
|
{
|
|
|
|
ui_state.edit_mode = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Return to previous menu
|
|
|
|
state.ui_screen = prev_state;
|
|
|
|
// Reset menu selection
|
|
|
|
ui_state.menu_selected = 0;
|
2022-09-06 02:18:45 +00:00
|
|
|
vp_playMenuBeepIfNeeded(true);
|
2021-02-13 20:29:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_textInputReset(char *buf)
|
2021-07-18 13:50:08 +00:00
|
|
|
{
|
|
|
|
ui_state.input_number = 0;
|
|
|
|
ui_state.input_position = 0;
|
|
|
|
ui_state.input_set = 0;
|
|
|
|
ui_state.last_keypress = 0;
|
|
|
|
memset(buf, 0, 9);
|
|
|
|
buf[0] = '_';
|
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_textInputKeypad(char *buf, uint8_t max_len, kbd_msg_t msg,
|
|
|
|
bool callsign)
|
2021-05-11 06:20:18 +00:00
|
|
|
{
|
|
|
|
if(ui_state.input_position >= max_len)
|
|
|
|
return;
|
|
|
|
long long now = getTick();
|
|
|
|
// Get currently pressed number key
|
2023-10-22 21:07:58 +00:00
|
|
|
uint8_t num_key = input_getPressedChar(msg);
|
2021-05-11 06:20:18 +00:00
|
|
|
// Get number of symbols related to currently pressed key
|
2021-07-18 13:50:08 +00:00
|
|
|
uint8_t num_symbols = 0;
|
|
|
|
if(callsign)
|
2023-10-23 00:42:47 +00:00
|
|
|
{
|
2021-07-18 13:50:08 +00:00
|
|
|
num_symbols = strlen(symbols_ITU_T_E161_callsign[num_key]);
|
2023-10-23 00:42:47 +00:00
|
|
|
if(num_symbols == 0)
|
|
|
|
return;
|
|
|
|
}
|
2021-07-18 13:50:08 +00:00
|
|
|
else
|
|
|
|
num_symbols = strlen(symbols_ITU_T_E161[num_key]);
|
2022-02-26 14:23:08 +00:00
|
|
|
|
2021-07-18 13:50:08 +00:00
|
|
|
// Skip keypad logic for first keypress
|
|
|
|
if(ui_state.last_keypress != 0)
|
2021-05-11 06:20:18 +00:00
|
|
|
{
|
2021-07-18 13:50:08 +00:00
|
|
|
// Same key pressed and timeout not expired: cycle over chars of current key
|
2022-06-14 05:34:53 +00:00
|
|
|
if((ui_state.input_number == num_key) && ((now - ui_state.last_keypress) < input_longPressTimeout))
|
2021-07-18 13:50:08 +00:00
|
|
|
{
|
|
|
|
ui_state.input_set = (ui_state.input_set + 1) % num_symbols;
|
|
|
|
}
|
2022-05-10 12:20:06 +00:00
|
|
|
// Different key pressed: save current char and change key
|
2021-07-18 13:50:08 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ui_state.input_position += 1;
|
|
|
|
ui_state.input_set = 0;
|
|
|
|
}
|
2021-05-11 06:20:18 +00:00
|
|
|
}
|
2021-07-18 13:50:08 +00:00
|
|
|
// Show current character on buffer
|
|
|
|
if(callsign)
|
|
|
|
buf[ui_state.input_position] = symbols_ITU_T_E161_callsign[num_key][ui_state.input_set];
|
2021-05-11 06:20:18 +00:00
|
|
|
else
|
2022-08-16 19:39:47 +00:00
|
|
|
{
|
2021-07-18 13:50:08 +00:00
|
|
|
buf[ui_state.input_position] = symbols_ITU_T_E161[num_key][ui_state.input_set];
|
2022-08-16 19:39:47 +00:00
|
|
|
}
|
|
|
|
// Announce the character
|
|
|
|
vp_announceInputChar(buf[ui_state.input_position]);
|
2021-05-11 06:20:18 +00:00
|
|
|
// Update reference values
|
|
|
|
ui_state.input_number = num_key;
|
|
|
|
ui_state.last_keypress = now;
|
2021-07-18 13:50:08 +00:00
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_textInputConfirm(char *buf)
|
2021-07-18 13:50:08 +00:00
|
|
|
{
|
|
|
|
buf[ui_state.input_position + 1] = '\0';
|
2021-05-11 06:20:18 +00:00
|
|
|
}
|
|
|
|
|
2022-08-16 19:39:47 +00:00
|
|
|
static void _ui_textInputDel(char *buf)
|
2021-07-13 19:12:07 +00:00
|
|
|
{
|
2022-09-05 11:35:42 +00:00
|
|
|
// announce the char about to be backspaced.
|
2022-09-05 11:59:10 +00:00
|
|
|
// Note this assumes editing callsign.
|
|
|
|
// If we edit a different buffer which allows the underline char, we may
|
|
|
|
// not want to exclude it, but when editing callsign, we do not want to say
|
|
|
|
// underline since it means the field is empty.
|
|
|
|
if(buf[ui_state.input_position]
|
|
|
|
&& buf[ui_state.input_position]!='_')
|
2022-09-05 11:35:42 +00:00
|
|
|
vp_announceInputChar(buf[ui_state.input_position]);
|
|
|
|
|
2021-07-18 13:50:08 +00:00
|
|
|
buf[ui_state.input_position] = '\0';
|
|
|
|
// Move back input cursor
|
2021-07-13 19:12:07 +00:00
|
|
|
if(ui_state.input_position > 0)
|
2022-08-16 19:39:47 +00:00
|
|
|
{
|
2021-07-13 19:12:07 +00:00
|
|
|
ui_state.input_position--;
|
2021-07-18 13:50:08 +00:00
|
|
|
// If we deleted the initial character, reset starting condition
|
2022-08-16 19:39:47 +00:00
|
|
|
}
|
2021-07-18 13:50:08 +00:00
|
|
|
else
|
|
|
|
ui_state.last_keypress = 0;
|
2021-07-13 19:12:07 +00:00
|
|
|
ui_state.input_set = 0;
|
|
|
|
}
|
|
|
|
|
2023-09-29 09:41:27 +00:00
|
|
|
static void _ui_numberInputKeypad(uint32_t *num, kbd_msg_t msg)
|
|
|
|
{
|
2023-09-29 13:43:54 +00:00
|
|
|
long long now = getTick();
|
|
|
|
|
|
|
|
#ifdef UI_NO_KEYBOARD
|
|
|
|
// If knob is turned, increment or Decrement
|
|
|
|
if (msg.keys & KNOB_LEFT)
|
|
|
|
{
|
|
|
|
*num = *num + 1;
|
|
|
|
if (*num % 10 == 0)
|
|
|
|
*num = *num - 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg.keys & KNOB_RIGHT)
|
|
|
|
{
|
|
|
|
if (*num == 0)
|
|
|
|
*num = 9;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*num = *num - 1;
|
|
|
|
if (*num % 10 == 9)
|
|
|
|
*num = *num + 10;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If enter is pressed, advance to the next digit
|
|
|
|
if (msg.keys & KEY_ENTER)
|
|
|
|
*num *= 10;
|
|
|
|
|
|
|
|
// Announce the character
|
|
|
|
vp_announceInputChar('0' + *num % 10);
|
|
|
|
|
|
|
|
// Update reference values
|
|
|
|
ui_state.input_number = *num % 10;
|
|
|
|
#else
|
2023-09-29 09:41:27 +00:00
|
|
|
// Maximum frequency len is uint32_t max value number of decimal digits
|
|
|
|
if(ui_state.input_position >= 10)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Get currently pressed number key
|
|
|
|
uint8_t num_key = input_getPressedNumber(msg);
|
|
|
|
*num *= 10;
|
|
|
|
*num += num_key;
|
|
|
|
|
|
|
|
// Announce the character
|
|
|
|
vp_announceInputChar('0' + num_key);
|
|
|
|
|
|
|
|
// Update reference values
|
|
|
|
ui_state.input_number = num_key;
|
2023-09-29 13:43:54 +00:00
|
|
|
#endif
|
|
|
|
|
2023-09-29 09:41:27 +00:00
|
|
|
ui_state.last_keypress = now;
|
|
|
|
}
|
2022-08-16 19:39:47 +00:00
|
|
|
|
2023-10-22 23:51:29 +00:00
|
|
|
static void _ui_signedNumberInputKeypad(int32_t *num, kbd_msg_t msg)
|
|
|
|
{
|
|
|
|
long long now = getTick();
|
|
|
|
|
|
|
|
#ifdef UI_NO_KEYBOARD
|
|
|
|
// TODO
|
|
|
|
#else
|
|
|
|
// Maximum frequency len is uint32_t max value number of decimal digits
|
|
|
|
if(ui_state.input_position >= 6)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(msg.keys & KEY_HASH)
|
|
|
|
{
|
|
|
|
*num *= -1;
|
|
|
|
vp_announceInputChar('-');
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
// Get currently pressed number key
|
|
|
|
uint8_t num_key = input_getPressedNumber(msg);
|
|
|
|
*num *= 10;
|
|
|
|
*num += num_key;
|
|
|
|
// Announce the character
|
|
|
|
vp_announceInputChar('0' + num_key);
|
|
|
|
// Update reference values
|
|
|
|
ui_state.input_number = num_key;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ui_state.last_keypress = now;
|
|
|
|
}
|
|
|
|
|
2023-09-29 09:41:27 +00:00
|
|
|
static void _ui_numberInputDel(uint32_t *num)
|
|
|
|
{
|
|
|
|
// announce the digit about to be backspaced.
|
2023-09-29 13:43:54 +00:00
|
|
|
vp_announceInputChar('0' + *num % 10);
|
2023-10-22 23:51:29 +00:00
|
|
|
|
|
|
|
// Move back input cursor
|
|
|
|
if(ui_state.input_position > 0)
|
|
|
|
ui_state.input_position--;
|
|
|
|
else
|
|
|
|
ui_state.last_keypress = 0;
|
|
|
|
|
|
|
|
ui_state.input_set = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void _ui_signedNumberInputDel(int32_t *num)
|
|
|
|
{
|
|
|
|
// announce the digit about to be backspaced.
|
|
|
|
vp_announceInputChar('0' + *num % 10);
|
|
|
|
|
2023-09-29 09:41:27 +00:00
|
|
|
// Move back input cursor
|
|
|
|
if(ui_state.input_position > 0)
|
|
|
|
ui_state.input_position--;
|
|
|
|
else
|
|
|
|
ui_state.last_keypress = 0;
|
|
|
|
|
|
|
|
ui_state.input_set = 0;
|
|
|
|
}
|
2022-08-16 19:39:47 +00:00
|
|
|
|
|
|
|
void ui_init()
|
|
|
|
{
|
|
|
|
last_event_tick = getTick();
|
|
|
|
redraw_needed = true;
|
|
|
|
layout = _ui_calculateLayout();
|
|
|
|
layout_ready = true;
|
|
|
|
// Initialize struct ui_state to all zeroes
|
|
|
|
// This syntax is called compound literal
|
|
|
|
// https://stackoverflow.com/questions/6891720/initialize-reset-struct-to-zero-null
|
|
|
|
ui_state = (const struct ui_state_t){ 0 };
|
|
|
|
}
|
|
|
|
|
2023-10-23 01:02:04 +00:00
|
|
|
void ui_drawSplashScreen()
|
2022-08-16 19:39:47 +00:00
|
|
|
{
|
|
|
|
gfx_clearScreen();
|
2022-10-26 14:13:02 +00:00
|
|
|
|
2023-10-23 01:02:04 +00:00
|
|
|
#if SCREEN_HEIGHT > 64
|
|
|
|
static const point_t logo_orig = {0, (SCREEN_HEIGHT / 2) - 6};
|
|
|
|
static const point_t call_orig = {0, SCREEN_HEIGHT - 8};
|
|
|
|
static const fontSize_t logo_font = FONT_SIZE_12PT;
|
|
|
|
static const fontSize_t call_font = FONT_SIZE_8PT;
|
|
|
|
#else
|
|
|
|
static const point_t logo_orig = {0, 19};
|
|
|
|
static const point_t call_orig = {0, SCREEN_HEIGHT - 8};
|
|
|
|
static const fontSize_t logo_font = FONT_SIZE_8PT;
|
|
|
|
static const fontSize_t call_font = FONT_SIZE_6PT;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
gfx_print(logo_orig, logo_font, TEXT_ALIGN_CENTER, yellow_fab413, "O P N\nR T X");
|
|
|
|
gfx_print(call_orig, call_font, TEXT_ALIGN_CENTER, color_white, state.settings.callsign);
|
2022-10-26 14:13:02 +00:00
|
|
|
|
|
|
|
vp_announceSplashScreen();
|
2022-08-16 19:39:47 +00:00
|
|
|
}
|
|
|
|
|
2021-01-30 07:33:39 +00:00
|
|
|
void ui_saveState()
|
|
|
|
{
|
|
|
|
last_state = state;
|
|
|
|
}
|
|
|
|
|
2022-09-13 05:40:12 +00:00
|
|
|
#ifdef GPS_PRESENT
|
|
|
|
static float priorGPSSpeed = 0;
|
|
|
|
static float priorGPSAltitude = 0;
|
2022-09-15 08:40:11 +00:00
|
|
|
static float priorGPSDirection = 500; // impossible value init.
|
2022-09-15 12:01:48 +00:00
|
|
|
static uint8_t priorGPSFixQuality= 0;
|
|
|
|
static uint8_t priorGPSFixType = 0;
|
|
|
|
static uint8_t priorSatellitesInView = 0;
|
2022-09-13 05:40:12 +00:00
|
|
|
static uint32_t vpGPSLastUpdate = 0;
|
|
|
|
|
|
|
|
static vpGPSInfoFlags_t GetGPSDirectionOrSpeedChanged()
|
|
|
|
{
|
|
|
|
if (!state.settings.gps_enabled)
|
|
|
|
return vpGPSNone;
|
2022-09-15 12:01:48 +00:00
|
|
|
|
2022-09-13 12:59:08 +00:00
|
|
|
uint32_t now = getTick();
|
2022-09-15 12:01:48 +00:00
|
|
|
if (now - vpGPSLastUpdate < 8000)
|
2022-09-13 12:59:08 +00:00
|
|
|
return vpGPSNone;
|
|
|
|
|
2022-09-13 05:40:12 +00:00
|
|
|
vpGPSInfoFlags_t whatChanged= vpGPSNone;
|
2022-09-13 12:59:08 +00:00
|
|
|
|
|
|
|
if (state.gps_data.fix_quality != priorGPSFixQuality)
|
|
|
|
{
|
|
|
|
whatChanged |= vpGPSFixQuality;
|
|
|
|
priorGPSFixQuality= state.gps_data.fix_quality;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state.gps_data.fix_type != priorGPSFixType)
|
|
|
|
{
|
|
|
|
whatChanged |= vpGPSFixType;
|
|
|
|
priorGPSFixType = state.gps_data.fix_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
float speedDiff=fabs(state.gps_data.speed - priorGPSSpeed);
|
|
|
|
if (speedDiff >= 1)
|
|
|
|
{
|
2022-09-13 05:40:12 +00:00
|
|
|
whatChanged |= vpGPSSpeed;
|
2022-09-13 12:59:08 +00:00
|
|
|
priorGPSSpeed = state.gps_data.speed;
|
|
|
|
}
|
2022-09-13 05:40:12 +00:00
|
|
|
|
2022-09-13 12:59:08 +00:00
|
|
|
float altitudeDiff = fabs(state.gps_data.altitude - priorGPSAltitude);
|
|
|
|
if (altitudeDiff >= 5)
|
|
|
|
{
|
|
|
|
whatChanged |= vpGPSAltitude;
|
|
|
|
priorGPSAltitude = state.gps_data.altitude;
|
|
|
|
}
|
2022-09-13 05:40:12 +00:00
|
|
|
|
2022-09-13 12:59:08 +00:00
|
|
|
float degreeDiff = fabs(state.gps_data.tmg_true - priorGPSDirection);
|
|
|
|
if (degreeDiff >= 1)
|
|
|
|
{
|
|
|
|
whatChanged |= vpGPSDirection;
|
|
|
|
priorGPSDirection = state.gps_data.tmg_true;
|
|
|
|
}
|
2022-09-13 05:40:12 +00:00
|
|
|
|
2022-09-15 12:01:48 +00:00
|
|
|
if (state.gps_data.satellites_in_view != priorSatellitesInView)
|
|
|
|
{
|
|
|
|
whatChanged |= vpGPSSatCount;
|
|
|
|
priorSatellitesInView = state.gps_data.satellites_in_view;
|
|
|
|
}
|
|
|
|
|
2022-09-15 08:40:11 +00:00
|
|
|
if (whatChanged)
|
|
|
|
vpGPSLastUpdate=now;
|
|
|
|
|
2022-09-13 05:40:12 +00:00
|
|
|
return whatChanged;
|
|
|
|
}
|
|
|
|
#endif // GPS_PRESENT
|
|
|
|
|
2022-06-29 05:47:38 +00:00
|
|
|
void ui_updateFSM(bool *sync_rtx)
|
2020-10-30 19:13:52 +00:00
|
|
|
{
|
2022-06-29 05:47:38 +00:00
|
|
|
// Check for events
|
|
|
|
if(evQueue_wrPos == evQueue_rdPos) return;
|
|
|
|
|
|
|
|
// Pop an event from the queue
|
|
|
|
uint8_t newTail = (evQueue_rdPos + 1) % MAX_NUM_EVENTS;
|
|
|
|
event_t event = evQueue[evQueue_rdPos];
|
|
|
|
evQueue_rdPos = newTail;
|
|
|
|
|
2022-08-04 20:48:41 +00:00
|
|
|
// There is some event to process, we need an UI redraw.
|
|
|
|
// UI redraw request is cancelled if we're in standby mode.
|
|
|
|
redraw_needed = true;
|
|
|
|
if(standby) redraw_needed = false;
|
|
|
|
|
2021-02-24 20:00:30 +00:00
|
|
|
// Check if battery has enough charge to operate.
|
|
|
|
// Check is skipped if there is an ongoing transmission, since the voltage
|
|
|
|
// drop caused by the RF PA power absorption causes spurious triggers of
|
|
|
|
// the low battery alert.
|
|
|
|
bool txOngoing = platform_getPttStatus();
|
2023-09-04 19:05:22 +00:00
|
|
|
#if !defined(PLATFORM_TTWRPLUS)
|
2021-02-24 20:00:30 +00:00
|
|
|
if ((!state.emergency) && (!txOngoing) && (state.charge <= 0))
|
2020-12-18 18:03:34 +00:00
|
|
|
{
|
|
|
|
state.ui_screen = LOW_BAT;
|
2021-02-24 20:00:30 +00:00
|
|
|
if(event.type == EVENT_KBD && event.payload)
|
|
|
|
{
|
2021-01-09 18:37:51 +00:00
|
|
|
state.ui_screen = MAIN_VFO;
|
2020-12-18 18:03:34 +00:00
|
|
|
state.emergency = true;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2023-09-04 19:05:22 +00:00
|
|
|
#endif // PLATFORM_TTWRPLUS
|
2020-12-18 18:03:34 +00:00
|
|
|
|
2021-11-20 21:03:44 +00:00
|
|
|
long long now = getTick();
|
2020-12-05 17:40:08 +00:00
|
|
|
// Process pressed keys
|
2020-12-06 07:46:12 +00:00
|
|
|
if(event.type == EVENT_KBD)
|
2020-11-26 21:44:39 +00:00
|
|
|
{
|
2020-12-14 14:41:37 +00:00
|
|
|
kbd_msg_t msg;
|
|
|
|
msg.value = event.payload;
|
2022-08-16 19:39:47 +00:00
|
|
|
bool f1Handled = false;
|
|
|
|
vpQueueFlags_t queueFlags = vp_getVoiceLevelQueueFlags();
|
2021-11-22 22:06:11 +00:00
|
|
|
// If we get out of standby, we ignore the kdb event
|
|
|
|
// unless is the MONI key for the MACRO functions
|
|
|
|
if (_ui_exitStandby(now) && !(msg.keys & KEY_MONI))
|
|
|
|
return;
|
2021-01-31 12:29:23 +00:00
|
|
|
// If MONI is pressed, activate MACRO functions
|
2023-09-10 11:04:38 +00:00
|
|
|
bool moniPressed = msg.keys & KEY_MONI;
|
2023-08-08 18:20:14 +00:00
|
|
|
if(moniPressed || macro_latched)
|
2022-08-16 19:39:47 +00:00
|
|
|
{
|
2021-01-31 12:29:23 +00:00
|
|
|
macro_menu = true;
|
2022-08-16 19:39:47 +00:00
|
|
|
// long press moni on its own latches function.
|
2023-08-08 18:20:14 +00:00
|
|
|
if (moniPressed && msg.long_press && !macro_latched)
|
2022-08-16 19:39:47 +00:00
|
|
|
{
|
2023-08-08 18:20:14 +00:00
|
|
|
macro_latched = true;
|
|
|
|
vp_beep(BEEP_FUNCTION_LATCH_ON, LONG_BEEP);
|
2022-08-16 19:39:47 +00:00
|
|
|
}
|
2023-08-08 18:20:14 +00:00
|
|
|
else if (moniPressed && macro_latched)
|
2022-08-16 19:39:47 +00:00
|
|
|
{
|
2023-08-08 18:20:14 +00:00
|
|
|
macro_latched = false;
|
|
|
|
vp_beep(BEEP_FUNCTION_LATCH_OFF, LONG_BEEP);
|
2022-08-16 19:39:47 +00:00
|
|
|
}
|
2021-01-31 12:29:23 +00:00
|
|
|
_ui_fsm_menuMacro(msg, sync_rtx);
|
|
|
|
return;
|
2021-02-24 20:00:30 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-01-31 12:29:23 +00:00
|
|
|
macro_menu = false;
|
|
|
|
}
|
2023-09-10 11:04:38 +00:00
|
|
|
#if defined(PLATFORM_TTWRPLUS)
|
|
|
|
// T-TWR Plus has no KEY_MONI, using KEY_VOLDOWN long press instead
|
|
|
|
if ((msg.keys & KEY_VOLDOWN) && msg.long_press)
|
|
|
|
{
|
|
|
|
macro_menu = true;
|
|
|
|
macro_latched = true;
|
|
|
|
}
|
|
|
|
#endif // PLA%FORM_TTWRPLUS
|
2022-08-29 19:35:44 +00:00
|
|
|
|
2023-07-01 17:24:43 +00:00
|
|
|
if(state.tone_enabled && !(msg.keys & KEY_HASH))
|
|
|
|
{
|
|
|
|
state.tone_enabled = false;
|
|
|
|
*sync_rtx = true;
|
|
|
|
}
|
|
|
|
|
2022-08-29 19:35:44 +00:00
|
|
|
int priorUIScreen = state.ui_screen;
|
2020-12-06 19:31:06 +00:00
|
|
|
switch(state.ui_screen)
|
2020-12-05 17:40:08 +00:00
|
|
|
{
|
2020-12-06 19:31:06 +00:00
|
|
|
// VFO screen
|
2021-01-09 18:37:51 +00:00
|
|
|
case MAIN_VFO:
|
2023-09-10 20:57:04 +00:00
|
|
|
// Enable Tx in MAIN_VFO mode
|
|
|
|
if (state.txDisable)
|
|
|
|
{
|
|
|
|
state.txDisable = false;
|
|
|
|
*sync_rtx = true;
|
|
|
|
}
|
2022-09-15 13:59:52 +00:00
|
|
|
// M17 Destination callsign input
|
2023-08-23 23:03:02 +00:00
|
|
|
if (ui_state.input_locked)
|
|
|
|
break;
|
2022-09-15 13:59:52 +00:00
|
|
|
if(ui_state.edit_mode)
|
2020-12-06 19:31:06 +00:00
|
|
|
{
|
2022-09-15 13:59:52 +00:00
|
|
|
if(state.channel.mode == OPMODE_M17)
|
2020-12-31 13:51:19 +00:00
|
|
|
{
|
2022-09-15 13:59:52 +00:00
|
|
|
if(msg.keys & KEY_ENTER)
|
|
|
|
{
|
|
|
|
_ui_textInputConfirm(ui_state.new_callsign);
|
|
|
|
// Save selected dst ID and disable input mode
|
2023-10-22 04:09:29 +00:00
|
|
|
strncpy(state.settings.m17_dest, ui_state.new_callsign, 10);
|
2022-09-15 13:59:52 +00:00
|
|
|
ui_state.edit_mode = false;
|
|
|
|
*sync_rtx = true;
|
2022-09-22 01:24:26 +00:00
|
|
|
vp_announceM17Info(NULL, ui_state.edit_mode,
|
|
|
|
queueFlags);
|
2022-09-15 13:59:52 +00:00
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_HASH)
|
|
|
|
{
|
|
|
|
// Save selected dst ID and disable input mode
|
2023-10-22 04:09:29 +00:00
|
|
|
strncpy(state.settings.m17_dest, "", 1);
|
2022-09-15 13:59:52 +00:00
|
|
|
ui_state.edit_mode = false;
|
|
|
|
*sync_rtx = true;
|
2022-09-22 01:24:26 +00:00
|
|
|
vp_announceM17Info(NULL, ui_state.edit_mode,
|
|
|
|
queueFlags);
|
2022-09-15 13:59:52 +00:00
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_ESC)
|
|
|
|
// Discard selected dst ID and disable input mode
|
|
|
|
ui_state.edit_mode = false;
|
|
|
|
else if(msg.keys & KEY_UP || msg.keys & KEY_DOWN ||
|
|
|
|
msg.keys & KEY_LEFT || msg.keys & KEY_RIGHT)
|
|
|
|
_ui_textInputDel(ui_state.new_callsign);
|
2023-10-22 21:07:58 +00:00
|
|
|
else if(input_isCharPressed(msg))
|
2022-09-15 13:59:52 +00:00
|
|
|
_ui_textInputKeypad(ui_state.new_callsign, 9, msg, true);
|
|
|
|
break;
|
2020-12-31 13:51:19 +00:00
|
|
|
}
|
2020-12-06 19:31:06 +00:00
|
|
|
}
|
2022-09-15 13:59:52 +00:00
|
|
|
else
|
2020-12-06 19:31:06 +00:00
|
|
|
{
|
2022-09-15 13:59:52 +00:00
|
|
|
if(msg.keys & KEY_ENTER)
|
2020-12-31 13:51:19 +00:00
|
|
|
{
|
2022-09-15 13:59:52 +00:00
|
|
|
// Save current main state
|
|
|
|
ui_state.last_main_state = state.ui_screen;
|
|
|
|
// Open Menu
|
|
|
|
state.ui_screen = MENU_TOP;
|
2022-08-16 19:39:47 +00:00
|
|
|
// The selected item will be announced when the item is first selected.
|
2020-12-31 13:51:19 +00:00
|
|
|
}
|
2022-09-15 13:59:52 +00:00
|
|
|
else if(msg.keys & KEY_ESC)
|
|
|
|
{
|
|
|
|
// Save VFO channel
|
|
|
|
state.vfo_channel = state.channel;
|
|
|
|
int result = _ui_fsm_loadChannel(state.channel_index, sync_rtx);
|
|
|
|
// Read successful and channel is valid
|
|
|
|
if(result != -1)
|
|
|
|
{
|
|
|
|
// Switch to MEM screen
|
|
|
|
state.ui_screen = MAIN_MEM;
|
2022-08-16 19:39:47 +00:00
|
|
|
// anounce the active channel name.
|
|
|
|
vp_announceChannelName(&state.channel,
|
|
|
|
state.channel_index,
|
|
|
|
queueFlags);
|
2022-09-15 13:59:52 +00:00
|
|
|
}
|
|
|
|
}
|
2022-09-15 13:59:52 +00:00
|
|
|
else if(msg.keys & KEY_HASH)
|
2021-01-10 09:18:29 +00:00
|
|
|
{
|
2023-06-13 07:02:50 +00:00
|
|
|
// Only enter edit mode when using M17
|
|
|
|
if(state.channel.mode == OPMODE_M17)
|
|
|
|
{
|
|
|
|
// Enable dst ID input
|
|
|
|
ui_state.edit_mode = true;
|
|
|
|
// Reset text input variables
|
|
|
|
_ui_textInputReset(ui_state.new_callsign);
|
|
|
|
vp_announceM17Info(NULL, ui_state.edit_mode,
|
|
|
|
queueFlags);
|
|
|
|
}
|
2023-07-01 17:24:43 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if(!state.tone_enabled)
|
|
|
|
{
|
|
|
|
state.tone_enabled = true;
|
|
|
|
*sync_rtx = true;
|
|
|
|
}
|
|
|
|
}
|
2022-09-15 13:59:52 +00:00
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_UP || msg.keys & KNOB_RIGHT)
|
|
|
|
{
|
|
|
|
// Increment TX and RX frequency of 12.5KHz
|
2023-09-25 12:16:32 +00:00
|
|
|
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]))
|
2022-09-15 13:59:52 +00:00
|
|
|
{
|
2023-09-25 12:16:32 +00:00
|
|
|
state.channel.rx_frequency += freq_steps[state.step_index];
|
|
|
|
state.channel.tx_frequency += freq_steps[state.step_index];
|
2022-09-15 13:59:52 +00:00
|
|
|
*sync_rtx = true;
|
2022-08-16 19:39:47 +00:00
|
|
|
vp_announceFrequencies(state.channel.rx_frequency,
|
|
|
|
state.channel.tx_frequency,
|
|
|
|
queueFlags);
|
2022-09-15 13:59:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_DOWN || msg.keys & KNOB_LEFT)
|
|
|
|
{
|
|
|
|
// Decrement TX and RX frequency of 12.5KHz
|
2023-09-25 12:16:32 +00:00
|
|
|
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]))
|
2022-09-15 13:59:52 +00:00
|
|
|
{
|
2023-09-25 12:16:32 +00:00
|
|
|
state.channel.rx_frequency -= freq_steps[state.step_index];
|
|
|
|
state.channel.tx_frequency -= freq_steps[state.step_index];
|
2022-09-15 13:59:52 +00:00
|
|
|
*sync_rtx = true;
|
2022-08-16 19:39:47 +00:00
|
|
|
vp_announceFrequencies(state.channel.rx_frequency,
|
|
|
|
state.channel.tx_frequency,
|
|
|
|
queueFlags);
|
2022-09-15 13:59:52 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-19 04:27:10 +00:00
|
|
|
else if(msg.keys & KEY_F1)
|
|
|
|
{
|
2022-08-16 19:39:47 +00:00
|
|
|
if (state.settings.vpLevel > vpBeep)
|
|
|
|
{// quick press repeat vp, long press summary.
|
|
|
|
if (msg.long_press)
|
|
|
|
vp_announceChannelSummary(&state.channel, 0,
|
2022-10-24 23:47:51 +00:00
|
|
|
state.bank, vpAllInfo);
|
2022-08-16 19:39:47 +00:00
|
|
|
else
|
|
|
|
vp_replayLastPrompt();
|
2022-09-06 12:07:56 +00:00
|
|
|
f1Handled = true;
|
|
|
|
}
|
2022-05-19 04:27:10 +00:00
|
|
|
}
|
2022-09-15 13:59:52 +00:00
|
|
|
else if(input_isNumberPressed(msg))
|
|
|
|
{
|
|
|
|
// Open Frequency input screen
|
|
|
|
state.ui_screen = MAIN_VFO_INPUT;
|
|
|
|
// Reset input position and selection
|
|
|
|
ui_state.input_position = 1;
|
|
|
|
ui_state.input_set = SET_RX;
|
2022-08-16 19:39:47 +00:00
|
|
|
// do not play because we will also announce the number just entered.
|
|
|
|
vp_announceInputReceiveOrTransmit(false, vpqInit);
|
2022-10-19 10:05:34 +00:00
|
|
|
vp_queueInteger(input_getPressedNumber(msg));
|
|
|
|
vp_play();
|
|
|
|
|
2022-09-15 13:59:52 +00:00
|
|
|
ui_state.new_rx_frequency = 0;
|
|
|
|
ui_state.new_tx_frequency = 0;
|
|
|
|
// Save pressed number to calculare frequency and show in GUI
|
|
|
|
ui_state.input_number = input_getPressedNumber(msg);
|
|
|
|
// Calculate portion of the new frequency
|
|
|
|
ui_state.new_rx_frequency = _ui_freq_add_digit(ui_state.new_rx_frequency,
|
2022-08-16 19:39:47 +00:00
|
|
|
ui_state.input_position,
|
|
|
|
ui_state.input_number);
|
2021-01-10 09:18:29 +00:00
|
|
|
}
|
2020-12-30 18:55:51 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
// VFO frequency input screen
|
2021-01-09 18:37:51 +00:00
|
|
|
case MAIN_VFO_INPUT:
|
2020-12-30 18:55:51 +00:00
|
|
|
if(msg.keys & KEY_ENTER)
|
|
|
|
{
|
2021-01-13 19:43:39 +00:00
|
|
|
_ui_fsm_confirmVFOInput(sync_rtx);
|
2020-12-30 18:55:51 +00:00
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_ESC)
|
|
|
|
{
|
2021-01-12 18:25:47 +00:00
|
|
|
// Cancel frequency input, return to VFO mode
|
2021-01-09 18:37:51 +00:00
|
|
|
state.ui_screen = MAIN_VFO;
|
2020-12-30 18:55:51 +00:00
|
|
|
}
|
2020-12-30 21:23:21 +00:00
|
|
|
else if(msg.keys & KEY_UP || msg.keys & KEY_DOWN)
|
|
|
|
{
|
2021-01-09 08:25:24 +00:00
|
|
|
if(ui_state.input_set == SET_RX)
|
2022-08-16 19:39:47 +00:00
|
|
|
{
|
2021-01-09 08:25:24 +00:00
|
|
|
ui_state.input_set = SET_TX;
|
2022-08-16 19:39:47 +00:00
|
|
|
vp_announceInputReceiveOrTransmit(true, queueFlags);
|
|
|
|
}
|
2021-01-09 08:25:24 +00:00
|
|
|
else if(ui_state.input_set == SET_TX)
|
2022-08-16 19:39:47 +00:00
|
|
|
{
|
2021-01-09 08:25:24 +00:00
|
|
|
ui_state.input_set = SET_RX;
|
2022-08-16 19:39:47 +00:00
|
|
|
vp_announceInputReceiveOrTransmit(false, queueFlags);
|
|
|
|
}
|
2020-12-30 21:23:21 +00:00
|
|
|
// Reset input position
|
2021-01-09 08:25:24 +00:00
|
|
|
ui_state.input_position = 0;
|
2020-12-30 21:23:21 +00:00
|
|
|
}
|
2020-12-30 18:55:51 +00:00
|
|
|
else if(input_isNumberPressed(msg))
|
|
|
|
{
|
2021-01-13 19:43:39 +00:00
|
|
|
_ui_fsm_insertVFONumber(msg, sync_rtx);
|
2020-12-30 18:55:51 +00:00
|
|
|
}
|
2020-12-06 19:31:06 +00:00
|
|
|
break;
|
2021-01-09 18:37:51 +00:00
|
|
|
// MEM screen
|
|
|
|
case MAIN_MEM:
|
2023-09-10 20:57:04 +00:00
|
|
|
// Enable Tx in MAIN_MEM mode
|
|
|
|
if (state.txDisable)
|
|
|
|
{
|
|
|
|
state.txDisable = false;
|
|
|
|
*sync_rtx = true;
|
|
|
|
}
|
2023-08-23 23:03:02 +00:00
|
|
|
if (ui_state.input_locked)
|
|
|
|
break;
|
2022-09-15 13:59:52 +00:00
|
|
|
// M17 Destination callsign input
|
|
|
|
if(ui_state.edit_mode)
|
2021-05-06 11:03:41 +00:00
|
|
|
{
|
2021-10-09 16:35:42 +00:00
|
|
|
{
|
|
|
|
if(msg.keys & KEY_ENTER)
|
|
|
|
{
|
|
|
|
_ui_textInputConfirm(ui_state.new_callsign);
|
|
|
|
// Save selected dst ID and disable input mode
|
2023-10-22 04:09:29 +00:00
|
|
|
strncpy(state.settings.m17_dest, ui_state.new_callsign, 10);
|
2021-10-09 16:35:42 +00:00
|
|
|
ui_state.edit_mode = false;
|
|
|
|
*sync_rtx = true;
|
|
|
|
}
|
2022-09-15 13:59:52 +00:00
|
|
|
else if(msg.keys & KEY_HASH)
|
|
|
|
{
|
|
|
|
// Save selected dst ID and disable input mode
|
2023-10-22 04:09:29 +00:00
|
|
|
strncpy(state.settings.m17_dest, "", 1);
|
2022-09-15 13:59:52 +00:00
|
|
|
ui_state.edit_mode = false;
|
|
|
|
*sync_rtx = true;
|
|
|
|
}
|
2021-10-09 16:35:42 +00:00
|
|
|
else if(msg.keys & KEY_ESC)
|
|
|
|
// Discard selected dst ID and disable input mode
|
|
|
|
ui_state.edit_mode = false;
|
2022-05-17 11:36:57 +00:00
|
|
|
else if(msg.keys & KEY_F1)
|
|
|
|
{
|
2022-08-16 19:39:47 +00:00
|
|
|
if (state.settings.vpLevel > vpBeep)
|
|
|
|
{
|
|
|
|
// Quick press repeat vp, long press summary.
|
|
|
|
if (msg.long_press)
|
|
|
|
{
|
2022-09-06 12:07:56 +00:00
|
|
|
vp_announceChannelSummary(
|
|
|
|
&state.channel,
|
|
|
|
state.channel_index,
|
|
|
|
state.bank,
|
2022-10-24 23:47:51 +00:00
|
|
|
vpAllInfo);
|
2022-08-16 19:39:47 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vp_replayLastPrompt();
|
|
|
|
}
|
|
|
|
|
|
|
|
f1Handled = true;
|
|
|
|
}
|
2022-05-17 11:36:57 +00:00
|
|
|
}
|
2021-10-09 16:35:42 +00:00
|
|
|
else if(msg.keys & KEY_UP || msg.keys & KEY_DOWN ||
|
|
|
|
msg.keys & KEY_LEFT || msg.keys & KEY_RIGHT)
|
|
|
|
_ui_textInputDel(ui_state.new_callsign);
|
2023-10-22 21:07:58 +00:00
|
|
|
else if(input_isCharPressed(msg))
|
2021-10-09 16:35:42 +00:00
|
|
|
_ui_textInputKeypad(ui_state.new_callsign, 9, msg, true);
|
2022-09-15 13:59:52 +00:00
|
|
|
break;
|
2021-10-09 16:35:42 +00:00
|
|
|
}
|
2021-05-06 11:03:41 +00:00
|
|
|
}
|
2021-10-09 16:35:42 +00:00
|
|
|
else
|
2021-05-06 11:03:41 +00:00
|
|
|
{
|
2021-10-09 16:35:42 +00:00
|
|
|
if(msg.keys & KEY_ENTER)
|
|
|
|
{
|
|
|
|
// Save current main state
|
|
|
|
ui_state.last_main_state = state.ui_screen;
|
|
|
|
// Open Menu
|
|
|
|
state.ui_screen = MENU_TOP;
|
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_ESC)
|
|
|
|
{
|
2022-09-15 13:59:52 +00:00
|
|
|
// Restore VFO channel
|
|
|
|
state.channel = state.vfo_channel;
|
|
|
|
// Update RTX configuration
|
|
|
|
*sync_rtx = true;
|
2021-10-09 16:35:42 +00:00
|
|
|
// Switch to VFO screen
|
|
|
|
state.ui_screen = MAIN_VFO;
|
|
|
|
}
|
2022-09-15 13:59:52 +00:00
|
|
|
else if(msg.keys & KEY_HASH)
|
2021-10-09 16:35:42 +00:00
|
|
|
{
|
2023-06-13 07:02:50 +00:00
|
|
|
// Only enter edit mode when using M17
|
|
|
|
if(state.channel.mode == OPMODE_M17)
|
|
|
|
{
|
|
|
|
// Enable dst ID input
|
|
|
|
ui_state.edit_mode = true;
|
|
|
|
// Reset text input variables
|
|
|
|
_ui_textInputReset(ui_state.new_callsign);
|
|
|
|
}
|
2023-07-01 17:24:43 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if(!state.tone_enabled)
|
|
|
|
{
|
|
|
|
state.tone_enabled = true;
|
|
|
|
*sync_rtx = true;
|
|
|
|
}
|
|
|
|
}
|
2021-10-09 16:35:42 +00:00
|
|
|
}
|
2022-05-19 04:27:10 +00:00
|
|
|
else if(msg.keys & KEY_F1)
|
|
|
|
{
|
2022-09-02 22:58:23 +00:00
|
|
|
if (state.settings.vpLevel > vpBeep)
|
|
|
|
{// quick press repeat vp, long press summary.
|
|
|
|
if (msg.long_press)
|
|
|
|
{
|
|
|
|
vp_announceChannelSummary(&state.channel,
|
|
|
|
state.channel_index+1,
|
2022-10-24 23:47:51 +00:00
|
|
|
state.bank, vpAllInfo);
|
2022-09-02 22:58:23 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vp_replayLastPrompt();
|
|
|
|
}
|
|
|
|
|
|
|
|
f1Handled = true;
|
|
|
|
}
|
2022-05-19 04:27:10 +00:00
|
|
|
}
|
2022-09-15 13:59:52 +00:00
|
|
|
else if(msg.keys & KEY_UP || msg.keys & KNOB_RIGHT)
|
2021-10-09 16:35:42 +00:00
|
|
|
{
|
2022-09-15 13:59:52 +00:00
|
|
|
_ui_fsm_loadChannel(state.channel_index + 1, sync_rtx);
|
2022-09-02 22:58:23 +00:00
|
|
|
vp_announceChannelName(&state.channel,
|
|
|
|
state.channel_index+1,
|
|
|
|
queueFlags);
|
2021-10-09 16:35:42 +00:00
|
|
|
}
|
2022-09-15 13:59:52 +00:00
|
|
|
else if(msg.keys & KEY_DOWN || msg.keys & KNOB_LEFT)
|
2021-10-09 16:35:42 +00:00
|
|
|
{
|
2022-09-15 13:59:52 +00:00
|
|
|
_ui_fsm_loadChannel(state.channel_index - 1, sync_rtx);
|
2022-09-02 22:58:23 +00:00
|
|
|
vp_announceChannelName(&state.channel,
|
|
|
|
state.channel_index+1,
|
|
|
|
queueFlags);
|
2021-10-09 16:35:42 +00:00
|
|
|
}
|
2021-05-06 11:03:41 +00:00
|
|
|
}
|
|
|
|
break;
|
2020-12-06 19:31:06 +00:00
|
|
|
// Top menu screen
|
|
|
|
case MENU_TOP:
|
2021-06-05 16:11:30 +00:00
|
|
|
if(msg.keys & KEY_UP || msg.keys & KNOB_LEFT)
|
2021-02-13 15:35:03 +00:00
|
|
|
_ui_menuUp(menu_num);
|
2021-06-05 16:11:30 +00:00
|
|
|
else if(msg.keys & KEY_DOWN || msg.keys & KNOB_RIGHT)
|
2021-02-13 15:35:03 +00:00
|
|
|
_ui_menuDown(menu_num);
|
2020-12-20 09:47:07 +00:00
|
|
|
else if(msg.keys & KEY_ENTER)
|
|
|
|
{
|
2021-02-15 21:02:09 +00:00
|
|
|
switch(ui_state.menu_selected)
|
|
|
|
{
|
2022-03-26 12:42:10 +00:00
|
|
|
case M_BANK:
|
|
|
|
state.ui_screen = MENU_BANK;
|
2021-02-15 21:02:09 +00:00
|
|
|
break;
|
|
|
|
case M_CHANNEL:
|
|
|
|
state.ui_screen = MENU_CHANNEL;
|
|
|
|
break;
|
|
|
|
case M_CONTACTS:
|
|
|
|
state.ui_screen = MENU_CONTACTS;
|
|
|
|
break;
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef GPS_PRESENT
|
2021-02-15 21:02:09 +00:00
|
|
|
case M_GPS:
|
|
|
|
state.ui_screen = MENU_GPS;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case M_SETTINGS:
|
|
|
|
state.ui_screen = MENU_SETTINGS;
|
|
|
|
break;
|
|
|
|
case M_INFO:
|
|
|
|
state.ui_screen = MENU_INFO;
|
|
|
|
break;
|
|
|
|
case M_ABOUT:
|
|
|
|
state.ui_screen = MENU_ABOUT;
|
|
|
|
break;
|
|
|
|
}
|
2020-12-20 10:00:59 +00:00
|
|
|
// Reset menu selection
|
2021-01-09 08:25:24 +00:00
|
|
|
ui_state.menu_selected = 0;
|
2020-12-20 09:47:07 +00:00
|
|
|
}
|
2020-12-14 14:41:37 +00:00
|
|
|
else if(msg.keys & KEY_ESC)
|
2021-02-13 20:29:25 +00:00
|
|
|
_ui_menuBack(ui_state.last_main_state);
|
2020-12-20 09:47:07 +00:00
|
|
|
break;
|
2021-01-24 17:53:43 +00:00
|
|
|
// Zone menu screen
|
2022-03-26 12:42:10 +00:00
|
|
|
case MENU_BANK:
|
2021-01-01 21:06:35 +00:00
|
|
|
// Channel menu screen
|
|
|
|
case MENU_CHANNEL:
|
2021-01-24 17:53:43 +00:00
|
|
|
// Contacts menu screen
|
|
|
|
case MENU_CONTACTS:
|
2021-06-05 16:11:30 +00:00
|
|
|
if(msg.keys & KEY_UP || msg.keys & KNOB_LEFT)
|
2021-02-13 15:35:03 +00:00
|
|
|
// Using 1 as parameter disables menu wrap around
|
|
|
|
_ui_menuUp(1);
|
2021-06-05 16:11:30 +00:00
|
|
|
else if(msg.keys & KEY_DOWN || msg.keys & KNOB_RIGHT)
|
2021-01-24 17:53:43 +00:00
|
|
|
{
|
2022-03-26 12:42:10 +00:00
|
|
|
if(state.ui_screen == MENU_BANK)
|
2021-01-26 19:10:31 +00:00
|
|
|
{
|
2022-03-29 16:31:39 +00:00
|
|
|
bankHdr_t bank;
|
|
|
|
// manu_selected is 0-based
|
|
|
|
// bank 0 means "All Channel" mode
|
|
|
|
// banks (1, n) are mapped to banks (0, n-1)
|
2022-04-04 17:43:21 +00:00
|
|
|
if(cps_readBankHeader(&bank, ui_state.menu_selected) != -1)
|
2021-01-26 19:18:55 +00:00
|
|
|
ui_state.menu_selected += 1;
|
|
|
|
}
|
|
|
|
else if(state.ui_screen == MENU_CHANNEL)
|
|
|
|
{
|
|
|
|
channel_t channel;
|
2022-04-04 17:43:21 +00:00
|
|
|
if(cps_readChannel(&channel, ui_state.menu_selected + 1) != -1)
|
2021-01-26 19:18:55 +00:00
|
|
|
ui_state.menu_selected += 1;
|
|
|
|
}
|
|
|
|
else if(state.ui_screen == MENU_CONTACTS)
|
|
|
|
{
|
|
|
|
contact_t contact;
|
2022-04-04 17:43:21 +00:00
|
|
|
if(cps_readContact(&contact, ui_state.menu_selected + 1) != -1)
|
2021-01-26 19:18:55 +00:00
|
|
|
ui_state.menu_selected += 1;
|
2021-01-26 19:10:31 +00:00
|
|
|
}
|
2021-01-24 17:53:43 +00:00
|
|
|
}
|
2021-01-26 19:57:39 +00:00
|
|
|
else if(msg.keys & KEY_ENTER)
|
|
|
|
{
|
2022-03-26 12:42:10 +00:00
|
|
|
if(state.ui_screen == MENU_BANK)
|
2021-01-31 13:14:54 +00:00
|
|
|
{
|
2022-03-29 16:31:39 +00:00
|
|
|
bankHdr_t newbank;
|
2021-01-31 13:14:54 +00:00
|
|
|
int result = 0;
|
2022-03-26 12:42:10 +00:00
|
|
|
// If "All channels" is selected, load default bank
|
2021-01-31 13:14:54 +00:00
|
|
|
if(ui_state.menu_selected == 0)
|
2022-03-26 12:42:10 +00:00
|
|
|
state.bank_enabled = false;
|
2021-01-31 13:14:54 +00:00
|
|
|
else
|
|
|
|
{
|
2022-03-26 12:42:10 +00:00
|
|
|
state.bank_enabled = true;
|
2022-03-29 16:31:39 +00:00
|
|
|
result = cps_readBankHeader(&newbank, ui_state.menu_selected - 1);
|
2021-01-31 13:14:54 +00:00
|
|
|
}
|
|
|
|
if(result != -1)
|
|
|
|
{
|
2022-03-29 16:31:39 +00:00
|
|
|
state.bank = ui_state.menu_selected - 1;
|
2021-01-31 13:14:54 +00:00
|
|
|
// If we were in VFO mode, save VFO channel
|
|
|
|
if(ui_state.last_main_state == MAIN_VFO)
|
|
|
|
state.vfo_channel = state.channel;
|
2022-03-26 12:42:10 +00:00
|
|
|
// Load bank first channel
|
2022-04-05 14:17:58 +00:00
|
|
|
_ui_fsm_loadChannel(0, sync_rtx);
|
2021-01-31 13:14:54 +00:00
|
|
|
// Switch to MEM screen
|
|
|
|
state.ui_screen = MAIN_MEM;
|
|
|
|
}
|
|
|
|
}
|
2021-01-26 19:57:39 +00:00
|
|
|
if(state.ui_screen == MENU_CHANNEL)
|
|
|
|
{
|
|
|
|
// If we were in VFO mode, save VFO channel
|
|
|
|
if(ui_state.last_main_state == MAIN_VFO)
|
|
|
|
state.vfo_channel = state.channel;
|
2022-04-04 17:43:21 +00:00
|
|
|
_ui_fsm_loadChannel(ui_state.menu_selected, sync_rtx);
|
2021-01-26 19:57:39 +00:00
|
|
|
// Switch to MEM screen
|
|
|
|
state.ui_screen = MAIN_MEM;
|
|
|
|
}
|
|
|
|
}
|
2021-01-24 17:53:43 +00:00
|
|
|
else if(msg.keys & KEY_ESC)
|
2021-02-13 20:29:25 +00:00
|
|
|
_ui_menuBack(MENU_TOP);
|
2020-12-21 15:47:34 +00:00
|
|
|
break;
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef GPS_PRESENT
|
2021-02-11 08:44:41 +00:00
|
|
|
// GPS menu screen
|
|
|
|
case MENU_GPS:
|
2022-08-16 19:39:47 +00:00
|
|
|
if ((msg.keys & KEY_F1) && (state.settings.vpLevel > vpBeep))
|
|
|
|
{// quick press repeat vp, long press summary.
|
|
|
|
if (msg.long_press)
|
2022-09-13 05:40:12 +00:00
|
|
|
vp_announceGPSInfo(vpGPSAll);
|
2022-08-16 19:39:47 +00:00
|
|
|
else
|
|
|
|
vp_replayLastPrompt();
|
|
|
|
f1Handled = true;
|
|
|
|
}
|
2022-05-19 10:29:24 +00:00
|
|
|
else if(msg.keys & KEY_ESC)
|
2021-02-13 20:29:25 +00:00
|
|
|
_ui_menuBack(MENU_TOP);
|
2021-02-11 08:44:41 +00:00
|
|
|
break;
|
2021-02-14 16:49:23 +00:00
|
|
|
#endif
|
2020-12-20 09:47:07 +00:00
|
|
|
// Settings menu screen
|
|
|
|
case MENU_SETTINGS:
|
2021-06-05 16:11:30 +00:00
|
|
|
if(msg.keys & KEY_UP || msg.keys & KNOB_LEFT)
|
2021-02-13 15:35:03 +00:00
|
|
|
_ui_menuUp(settings_num);
|
2021-06-05 16:11:30 +00:00
|
|
|
else if(msg.keys & KEY_DOWN || msg.keys & KNOB_RIGHT)
|
2021-02-13 15:35:03 +00:00
|
|
|
_ui_menuDown(settings_num);
|
2021-01-26 21:04:19 +00:00
|
|
|
else if(msg.keys & KEY_ENTER)
|
2020-12-22 16:49:00 +00:00
|
|
|
{
|
2021-02-15 21:02:09 +00:00
|
|
|
|
|
|
|
switch(ui_state.menu_selected)
|
|
|
|
{
|
|
|
|
case S_DISPLAY:
|
|
|
|
state.ui_screen = SETTINGS_DISPLAY;
|
|
|
|
break;
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef RTC_PRESENT
|
2021-02-15 21:02:09 +00:00
|
|
|
case S_TIMEDATE:
|
|
|
|
state.ui_screen = SETTINGS_TIMEDATE;
|
|
|
|
break;
|
|
|
|
#endif
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef GPS_PRESENT
|
2021-02-15 21:02:09 +00:00
|
|
|
case S_GPS:
|
|
|
|
state.ui_screen = SETTINGS_GPS;
|
|
|
|
break;
|
2021-02-14 16:49:23 +00:00
|
|
|
#endif
|
2023-09-25 12:16:32 +00:00
|
|
|
case S_RADIO:
|
|
|
|
state.ui_screen = SETTINGS_RADIO;
|
|
|
|
break;
|
2021-05-10 20:20:10 +00:00
|
|
|
case S_M17:
|
|
|
|
state.ui_screen = SETTINGS_M17;
|
|
|
|
break;
|
2022-08-16 19:39:47 +00:00
|
|
|
case S_VOICE:
|
2022-05-18 11:18:12 +00:00
|
|
|
state.ui_screen = SETTINGS_VOICE;
|
|
|
|
break;
|
2022-08-16 19:39:47 +00:00
|
|
|
case S_RESET2DEFAULTS:
|
2022-02-26 11:42:28 +00:00
|
|
|
state.ui_screen = SETTINGS_RESET2DEFAULTS;
|
|
|
|
break;
|
2021-02-16 21:09:28 +00:00
|
|
|
default:
|
|
|
|
state.ui_screen = MENU_SETTINGS;
|
2021-02-15 21:02:09 +00:00
|
|
|
}
|
2020-12-22 16:49:00 +00:00
|
|
|
// Reset menu selection
|
2021-01-09 08:25:24 +00:00
|
|
|
ui_state.menu_selected = 0;
|
2020-12-22 16:49:00 +00:00
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_ESC)
|
2021-02-13 20:29:25 +00:00
|
|
|
_ui_menuBack(MENU_TOP);
|
2020-12-06 19:31:06 +00:00
|
|
|
break;
|
2022-03-12 23:21:52 +00:00
|
|
|
// Flash backup and restore menu screen
|
|
|
|
case MENU_BACKUP_RESTORE:
|
|
|
|
if(msg.keys & KEY_UP || msg.keys & KNOB_LEFT)
|
|
|
|
_ui_menuUp(settings_num);
|
|
|
|
else if(msg.keys & KEY_DOWN || msg.keys & KNOB_RIGHT)
|
|
|
|
_ui_menuDown(settings_num);
|
|
|
|
else if(msg.keys & KEY_ENTER)
|
|
|
|
{
|
|
|
|
|
|
|
|
switch(ui_state.menu_selected)
|
|
|
|
{
|
|
|
|
case BR_BACKUP:
|
|
|
|
state.ui_screen = MENU_BACKUP;
|
|
|
|
break;
|
|
|
|
case BR_RESTORE:
|
|
|
|
state.ui_screen = MENU_RESTORE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
state.ui_screen = MENU_BACKUP_RESTORE;
|
|
|
|
}
|
|
|
|
// Reset menu selection
|
|
|
|
ui_state.menu_selected = 0;
|
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_ESC)
|
|
|
|
_ui_menuBack(MENU_TOP);
|
|
|
|
break;
|
2022-09-06 12:53:31 +00:00
|
|
|
case MENU_BACKUP:
|
|
|
|
case MENU_RESTORE:
|
|
|
|
if(msg.keys & KEY_ESC)
|
|
|
|
_ui_menuBack(MENU_TOP);
|
|
|
|
break;
|
2021-01-30 07:02:41 +00:00
|
|
|
// Info menu screen
|
|
|
|
case MENU_INFO:
|
2021-06-05 16:11:30 +00:00
|
|
|
if(msg.keys & KEY_UP || msg.keys & KNOB_LEFT)
|
2021-02-13 15:35:03 +00:00
|
|
|
_ui_menuUp(info_num);
|
2021-06-05 16:11:30 +00:00
|
|
|
else if(msg.keys & KEY_DOWN || msg.keys & KNOB_RIGHT)
|
2021-02-13 15:35:03 +00:00
|
|
|
_ui_menuDown(info_num);
|
2021-01-30 07:02:41 +00:00
|
|
|
else if(msg.keys & KEY_ESC)
|
2021-02-13 20:29:25 +00:00
|
|
|
_ui_menuBack(MENU_TOP);
|
2021-01-30 07:02:41 +00:00
|
|
|
break;
|
2021-01-30 10:57:00 +00:00
|
|
|
// About screen
|
|
|
|
case MENU_ABOUT:
|
2022-09-06 07:23:49 +00:00
|
|
|
if(msg.keys & KEY_ESC)
|
2021-02-13 20:29:25 +00:00
|
|
|
_ui_menuBack(MENU_TOP);
|
2021-01-30 10:57:00 +00:00
|
|
|
break;
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef RTC_PRESENT
|
2020-12-31 15:36:32 +00:00
|
|
|
// Time&Date settings screen
|
2020-12-22 16:49:00 +00:00
|
|
|
case SETTINGS_TIMEDATE:
|
2022-09-05 13:03:41 +00:00
|
|
|
if(msg.keys & KEY_ENTER)
|
2020-12-31 15:36:32 +00:00
|
|
|
{
|
|
|
|
// Switch to set Time&Date mode
|
|
|
|
state.ui_screen = SETTINGS_TIMEDATE_SET;
|
|
|
|
// Reset input position and selection
|
2021-01-09 08:25:24 +00:00
|
|
|
ui_state.input_position = 0;
|
2022-06-16 07:13:36 +00:00
|
|
|
memset(&ui_state.new_timedate, 0, sizeof(datetime_t));
|
2022-09-05 13:03:41 +00:00
|
|
|
vp_announceBuffer(¤tLanguage->timeAndDate,
|
2022-09-05 23:23:54 +00:00
|
|
|
true, false, "dd/mm/yy");
|
2020-12-31 15:36:32 +00:00
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_ESC)
|
2021-02-13 20:29:25 +00:00
|
|
|
_ui_menuBack(MENU_SETTINGS);
|
2020-12-22 16:49:00 +00:00
|
|
|
break;
|
2020-12-31 15:36:32 +00:00
|
|
|
// Time&Date settings screen, edit mode
|
|
|
|
case SETTINGS_TIMEDATE_SET:
|
|
|
|
if(msg.keys & KEY_ENTER)
|
|
|
|
{
|
2020-12-31 18:05:29 +00:00
|
|
|
// Save time only if all digits have been inserted
|
2021-01-09 08:25:24 +00:00
|
|
|
if(ui_state.input_position < TIMEDATE_DIGITS)
|
2020-12-31 18:05:29 +00:00
|
|
|
break;
|
2020-12-31 15:36:32 +00:00
|
|
|
// Return to Time&Date menu, saving values
|
2021-04-10 13:39:59 +00:00
|
|
|
// NOTE: The user inserted a local time, we must save an UTC time
|
2022-06-16 07:13:36 +00:00
|
|
|
datetime_t utc_time = localTimeToUtc(ui_state.new_timedate,
|
|
|
|
state.settings.utc_timezone);
|
2023-07-21 05:58:29 +00:00
|
|
|
platform_setTime(utc_time);
|
2021-04-10 13:39:59 +00:00
|
|
|
state.time = utc_time;
|
2022-09-05 13:03:41 +00:00
|
|
|
vp_announceSettingsTimeDate();
|
2020-12-31 15:36:32 +00:00
|
|
|
state.ui_screen = SETTINGS_TIMEDATE;
|
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_ESC)
|
2021-02-13 20:29:25 +00:00
|
|
|
_ui_menuBack(SETTINGS_TIMEDATE);
|
2020-12-31 15:36:32 +00:00
|
|
|
else if(input_isNumberPressed(msg))
|
|
|
|
{
|
2020-12-31 18:05:29 +00:00
|
|
|
// Discard excess digits
|
2021-01-09 08:25:24 +00:00
|
|
|
if(ui_state.input_position > TIMEDATE_DIGITS)
|
2020-12-31 18:05:29 +00:00
|
|
|
break;
|
2021-01-09 08:25:24 +00:00
|
|
|
ui_state.input_position += 1;
|
|
|
|
ui_state.input_number = input_getPressedNumber(msg);
|
2021-02-24 20:00:30 +00:00
|
|
|
_ui_timedate_add_digit(&ui_state.new_timedate, ui_state.input_position,
|
2021-02-13 21:11:25 +00:00
|
|
|
ui_state.input_number);
|
2020-12-31 15:36:32 +00:00
|
|
|
}
|
|
|
|
break;
|
2021-01-01 17:58:35 +00:00
|
|
|
#endif
|
2021-01-26 21:04:19 +00:00
|
|
|
case SETTINGS_DISPLAY:
|
2021-06-05 16:11:30 +00:00
|
|
|
if(msg.keys & KEY_LEFT || (ui_state.edit_mode &&
|
|
|
|
(msg.keys & KEY_DOWN || msg.keys & KNOB_LEFT)))
|
2021-01-26 21:04:19 +00:00
|
|
|
{
|
2021-02-15 21:02:09 +00:00
|
|
|
switch(ui_state.menu_selected)
|
2021-01-29 21:41:42 +00:00
|
|
|
{
|
2023-08-07 18:36:22 +00:00
|
|
|
#ifdef SCREEN_BRIGHTNESS
|
2021-02-15 21:02:09 +00:00
|
|
|
case D_BRIGHTNESS:
|
2022-02-26 14:23:08 +00:00
|
|
|
_ui_changeBrightness(-5);
|
2022-09-02 11:02:53 +00:00
|
|
|
vp_announceSettingsInt(¤tLanguage->brightness, queueFlags,
|
|
|
|
state.settings.brightness);
|
2021-02-15 21:02:09 +00:00
|
|
|
break;
|
2023-08-07 18:36:22 +00:00
|
|
|
#endif
|
2021-02-15 21:02:09 +00:00
|
|
|
#ifdef SCREEN_CONTRAST
|
|
|
|
case D_CONTRAST:
|
2021-03-14 10:21:39 +00:00
|
|
|
_ui_changeContrast(-4);
|
2022-09-02 11:02:53 +00:00
|
|
|
vp_announceSettingsInt(¤tLanguage->brightness, queueFlags,
|
|
|
|
state.settings.contrast);
|
2021-02-15 21:02:09 +00:00
|
|
|
break;
|
|
|
|
#endif
|
2021-12-13 22:18:01 +00:00
|
|
|
case D_TIMER:
|
|
|
|
_ui_changeTimer(-1);
|
2022-09-06 00:23:47 +00:00
|
|
|
vp_announceDisplayTimer();
|
2021-12-13 22:18:01 +00:00
|
|
|
break;
|
2021-02-16 21:09:28 +00:00
|
|
|
default:
|
|
|
|
state.ui_screen = SETTINGS_DISPLAY;
|
2021-01-29 21:41:42 +00:00
|
|
|
}
|
2021-01-26 21:04:19 +00:00
|
|
|
}
|
2021-06-05 16:11:30 +00:00
|
|
|
else if(msg.keys & KEY_RIGHT || (ui_state.edit_mode &&
|
|
|
|
(msg.keys & KEY_UP || msg.keys & KNOB_RIGHT)))
|
2021-01-26 21:04:19 +00:00
|
|
|
{
|
2021-02-15 21:02:09 +00:00
|
|
|
switch(ui_state.menu_selected)
|
2021-01-29 21:41:42 +00:00
|
|
|
{
|
2023-08-07 18:36:22 +00:00
|
|
|
#ifdef SCREEN_BRIGHTNESS
|
2021-02-15 21:02:09 +00:00
|
|
|
case D_BRIGHTNESS:
|
2022-02-26 14:23:08 +00:00
|
|
|
_ui_changeBrightness(+5);
|
2022-09-02 11:02:53 +00:00
|
|
|
vp_announceSettingsInt(¤tLanguage->brightness, queueFlags,
|
|
|
|
state.settings.brightness);
|
2021-02-15 21:02:09 +00:00
|
|
|
break;
|
2023-08-07 18:36:22 +00:00
|
|
|
#endif
|
2021-02-15 21:02:09 +00:00
|
|
|
#ifdef SCREEN_CONTRAST
|
|
|
|
case D_CONTRAST:
|
2021-03-14 10:21:39 +00:00
|
|
|
_ui_changeContrast(+4);
|
2022-09-02 11:02:53 +00:00
|
|
|
vp_announceSettingsInt(¤tLanguage->brightness, queueFlags,
|
|
|
|
state.settings.contrast);
|
2021-02-15 21:02:09 +00:00
|
|
|
break;
|
|
|
|
#endif
|
2021-12-13 22:18:01 +00:00
|
|
|
case D_TIMER:
|
|
|
|
_ui_changeTimer(+1);
|
2022-09-06 00:23:47 +00:00
|
|
|
vp_announceDisplayTimer();
|
2021-12-13 22:18:01 +00:00
|
|
|
break;
|
2021-02-16 21:09:28 +00:00
|
|
|
default:
|
|
|
|
state.ui_screen = SETTINGS_DISPLAY;
|
2021-01-29 21:41:42 +00:00
|
|
|
}
|
2021-01-26 21:04:19 +00:00
|
|
|
}
|
2021-06-05 16:11:30 +00:00
|
|
|
else if(msg.keys & KEY_UP || msg.keys & KNOB_LEFT)
|
2021-02-13 20:29:25 +00:00
|
|
|
_ui_menuUp(display_num);
|
2021-06-05 16:11:30 +00:00
|
|
|
else if(msg.keys & KEY_DOWN || msg.keys & KNOB_RIGHT)
|
2021-02-13 20:29:25 +00:00
|
|
|
_ui_menuDown(display_num);
|
|
|
|
else if(msg.keys & KEY_ENTER)
|
|
|
|
ui_state.edit_mode = !ui_state.edit_mode;
|
2021-01-26 21:04:19 +00:00
|
|
|
else if(msg.keys & KEY_ESC)
|
2021-02-13 20:29:25 +00:00
|
|
|
_ui_menuBack(MENU_SETTINGS);
|
2021-01-26 21:04:19 +00:00
|
|
|
break;
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef GPS_PRESENT
|
2021-02-13 16:23:16 +00:00
|
|
|
case SETTINGS_GPS:
|
2021-02-24 20:00:30 +00:00
|
|
|
if(msg.keys & KEY_LEFT || msg.keys & KEY_RIGHT ||
|
2021-06-05 16:11:30 +00:00
|
|
|
(ui_state.edit_mode &&
|
|
|
|
(msg.keys & KEY_DOWN || msg.keys & KNOB_LEFT ||
|
|
|
|
msg.keys & KEY_UP || msg.keys & KNOB_RIGHT)))
|
2021-02-13 16:23:16 +00:00
|
|
|
{
|
2021-02-15 21:02:09 +00:00
|
|
|
switch(ui_state.menu_selected)
|
2021-02-14 13:04:01 +00:00
|
|
|
{
|
2021-02-15 21:02:09 +00:00
|
|
|
case G_ENABLED:
|
|
|
|
if(state.settings.gps_enabled)
|
2021-02-16 21:22:20 +00:00
|
|
|
state.settings.gps_enabled = 0;
|
2021-02-15 21:02:09 +00:00
|
|
|
else
|
2021-02-16 21:22:20 +00:00
|
|
|
state.settings.gps_enabled = 1;
|
2022-09-01 11:43:53 +00:00
|
|
|
vp_announceSettingsOnOffToggle(¤tLanguage->gpsEnabled,
|
|
|
|
queueFlags,
|
|
|
|
state.settings.gps_enabled);
|
2021-02-15 21:02:09 +00:00
|
|
|
break;
|
|
|
|
case G_SET_TIME:
|
2021-11-08 20:44:33 +00:00
|
|
|
state.gps_set_time = !state.gps_set_time;
|
2022-09-01 11:43:53 +00:00
|
|
|
vp_announceSettingsOnOffToggle(¤tLanguage->gpsSetTime,
|
|
|
|
queueFlags,
|
|
|
|
state.gps_set_time);
|
2021-02-15 21:02:09 +00:00
|
|
|
break;
|
|
|
|
case G_TIMEZONE:
|
2022-10-31 10:41:54 +00:00
|
|
|
if(msg.keys & KEY_LEFT || msg.keys & KEY_DOWN ||
|
2021-06-05 16:11:30 +00:00
|
|
|
msg.keys & KNOB_LEFT)
|
2021-02-15 21:02:09 +00:00
|
|
|
state.settings.utc_timezone -= 1;
|
2022-10-31 10:41:54 +00:00
|
|
|
else if(msg.keys & KEY_RIGHT || msg.keys & KEY_UP ||
|
2021-06-05 16:11:30 +00:00
|
|
|
msg.keys & KNOB_RIGHT)
|
2021-02-15 21:02:09 +00:00
|
|
|
state.settings.utc_timezone += 1;
|
2022-10-31 17:04:08 +00:00
|
|
|
vp_announceTimeZone(state.settings.utc_timezone, queueFlags);
|
2021-02-15 21:02:09 +00:00
|
|
|
break;
|
2021-02-16 21:09:28 +00:00
|
|
|
default:
|
|
|
|
state.ui_screen = SETTINGS_GPS;
|
2021-02-14 13:04:01 +00:00
|
|
|
}
|
2021-02-13 16:23:16 +00:00
|
|
|
}
|
2021-06-05 16:11:30 +00:00
|
|
|
else if(msg.keys & KEY_UP || msg.keys & KNOB_LEFT)
|
2021-02-13 20:29:25 +00:00
|
|
|
_ui_menuUp(settings_gps_num);
|
2021-06-05 16:11:30 +00:00
|
|
|
else if(msg.keys & KEY_DOWN || msg.keys & KNOB_RIGHT)
|
2021-02-13 20:29:25 +00:00
|
|
|
_ui_menuDown(settings_gps_num);
|
|
|
|
else if(msg.keys & KEY_ENTER)
|
|
|
|
ui_state.edit_mode = !ui_state.edit_mode;
|
2021-02-13 16:23:16 +00:00
|
|
|
else if(msg.keys & KEY_ESC)
|
2021-02-13 20:29:25 +00:00
|
|
|
_ui_menuBack(MENU_SETTINGS);
|
2021-02-13 16:23:16 +00:00
|
|
|
break;
|
2021-02-14 16:49:23 +00:00
|
|
|
#endif
|
2023-09-25 12:16:32 +00:00
|
|
|
// Radio Settings
|
|
|
|
case SETTINGS_RADIO:
|
2023-09-29 09:41:27 +00:00
|
|
|
// If the entry is selected with enter we are in edit_mode
|
|
|
|
if (ui_state.edit_mode)
|
2023-09-25 12:16:32 +00:00
|
|
|
{
|
|
|
|
switch(ui_state.menu_selected)
|
|
|
|
{
|
2023-10-22 21:53:19 +00:00
|
|
|
case R_SHIFT:
|
|
|
|
// Handle split frequency input
|
2023-09-29 13:43:54 +00:00
|
|
|
#if defined(UI_NO_KEYBOARD)
|
|
|
|
if(msg.long_press && msg.keys & KEY_ENTER)
|
|
|
|
{
|
|
|
|
// Long press on UI_NO_KEYBOARD causes digits to advance by one
|
2023-10-22 21:53:19 +00:00
|
|
|
ui_state.new_shift /= 10;
|
2023-09-29 13:43:54 +00:00
|
|
|
#else
|
2023-09-29 09:41:27 +00:00
|
|
|
if(msg.keys & KEY_ENTER)
|
|
|
|
{
|
2023-09-29 13:43:54 +00:00
|
|
|
#endif
|
2023-09-29 09:41:27 +00:00
|
|
|
// Apply new offset
|
2023-10-22 21:53:19 +00:00
|
|
|
state.channel.tx_frequency = state.channel.rx_frequency + ui_state.new_shift;
|
|
|
|
vp_queueStringTableEntry(¤tLanguage->repeaterShift);
|
|
|
|
vp_queueFrequency(ui_state.new_shift);
|
2023-09-29 13:43:54 +00:00
|
|
|
ui_state.edit_mode = false;
|
2023-09-29 09:41:27 +00:00
|
|
|
}
|
2023-09-29 13:43:54 +00:00
|
|
|
else
|
|
|
|
if(msg.keys & KEY_ESC)
|
2023-09-29 09:41:27 +00:00
|
|
|
{
|
|
|
|
// Announce old frequency offset
|
2023-10-22 21:53:19 +00:00
|
|
|
vp_queueStringTableEntry(¤tLanguage->repeaterShift);
|
2023-09-29 09:41:27 +00:00
|
|
|
vp_queueFrequency((int32_t)state.channel.tx_frequency - (int32_t)state.channel.rx_frequency);
|
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_UP || msg.keys & KEY_DOWN ||
|
|
|
|
msg.keys & KEY_LEFT || msg.keys & KEY_RIGHT)
|
|
|
|
{
|
2023-10-22 21:53:19 +00:00
|
|
|
_ui_numberInputDel(&ui_state.new_shift);
|
2023-09-29 09:41:27 +00:00
|
|
|
}
|
2023-09-29 13:43:54 +00:00
|
|
|
#if defined(UI_NO_KEYBOARD)
|
|
|
|
else if(msg.keys & KNOB_LEFT || msg.keys & KNOB_RIGHT || msg.keys & KEY_ENTER)
|
|
|
|
#else
|
2023-09-29 09:41:27 +00:00
|
|
|
else if(input_isNumberPressed(msg))
|
2023-09-29 13:43:54 +00:00
|
|
|
#endif
|
2023-09-29 09:41:27 +00:00
|
|
|
{
|
2023-10-22 21:53:19 +00:00
|
|
|
_ui_numberInputKeypad(&ui_state.new_shift, msg);
|
2023-09-29 09:41:27 +00:00
|
|
|
ui_state.input_position += 1;
|
|
|
|
}
|
|
|
|
else if (msg.long_press && (msg.keys & KEY_F1) && (state.settings.vpLevel > vpBeep))
|
|
|
|
{
|
2023-10-22 21:53:19 +00:00
|
|
|
vp_queueFrequency(ui_state.new_shift);
|
2023-09-29 09:41:27 +00:00
|
|
|
f1Handled=true;
|
|
|
|
}
|
2023-09-25 12:16:32 +00:00
|
|
|
break;
|
|
|
|
case R_DIRECTION:
|
2023-09-29 09:41:27 +00:00
|
|
|
if(msg.keys & KEY_UP || msg.keys & KEY_DOWN ||
|
2023-09-29 13:43:54 +00:00
|
|
|
msg.keys & KEY_LEFT || msg.keys & KEY_RIGHT ||
|
|
|
|
msg.keys & KNOB_LEFT || msg.keys & KNOB_RIGHT)
|
2023-09-29 09:41:27 +00:00
|
|
|
{
|
|
|
|
// 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);
|
|
|
|
}
|
2023-09-25 12:16:32 +00:00
|
|
|
break;
|
|
|
|
case R_STEP:
|
2023-09-29 13:43:54 +00:00
|
|
|
if (msg.keys & KEY_UP || msg.keys & KEY_RIGHT || msg.keys & KNOB_RIGHT)
|
2023-09-29 09:41:27 +00:00
|
|
|
{
|
|
|
|
// Cycle over the available frequency steps
|
|
|
|
state.step_index++;
|
|
|
|
state.step_index %= n_freq_steps;
|
|
|
|
}
|
2023-09-29 13:43:54 +00:00
|
|
|
else if(msg.keys & KEY_DOWN || msg.keys & KEY_LEFT || msg.keys & KNOB_LEFT)
|
2023-09-29 09:41:27 +00:00
|
|
|
{
|
|
|
|
state.step_index += n_freq_steps;
|
|
|
|
state.step_index--;
|
|
|
|
state.step_index %= n_freq_steps;
|
|
|
|
}
|
2023-09-25 12:16:32 +00:00
|
|
|
break;
|
2023-10-22 23:51:29 +00:00
|
|
|
case R_PPM:
|
|
|
|
// Handle PPM offset input
|
|
|
|
#if defined(UI_NO_KEYBOARD)
|
|
|
|
if(msg.long_press && msg.keys & KEY_ENTER)
|
|
|
|
{
|
|
|
|
// Long press on UI_NO_KEYBOARD causes digits to advance by one
|
|
|
|
ui_state.new_ppm /= 10;
|
|
|
|
#else
|
|
|
|
if(msg.keys & KEY_ENTER)
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
// Apply new offset
|
2023-11-19 15:35:28 +00:00
|
|
|
state.settings.ppm_offset = ui_state.new_ppm*ui_state.new_ppm_sign;
|
2023-10-22 23:51:29 +00:00
|
|
|
vp_queueStringTableEntry(¤tLanguage->ppmFreqOffset);
|
|
|
|
vp_queuePPM(ui_state.new_ppm);
|
|
|
|
ui_state.edit_mode = false;
|
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_ESC)
|
|
|
|
{
|
|
|
|
// Announce old frequency offset
|
|
|
|
vp_queueStringTableEntry(¤tLanguage->ppmFreqOffset);
|
|
|
|
vp_queuePPM(ui_state.new_ppm);
|
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_UP || msg.keys & KEY_DOWN ||
|
|
|
|
msg.keys & KEY_LEFT || msg.keys & KEY_RIGHT)
|
|
|
|
{
|
2023-11-19 15:35:28 +00:00
|
|
|
uint32_t tmp = (uint32_t)ui_state.new_ppm;
|
|
|
|
_ui_numberInputDel(&tmp);
|
|
|
|
ui_state.new_ppm = (uint16_t)tmp;
|
2023-10-22 23:51:29 +00:00
|
|
|
}
|
|
|
|
#if defined(UI_NO_KEYBOARD)
|
|
|
|
else if(msg.keys & KNOB_LEFT || msg.keys & KNOB_RIGHT || msg.keys & KEY_ENTER)
|
|
|
|
#else
|
|
|
|
else if(input_isNumberPressed(msg))
|
|
|
|
#endif
|
|
|
|
{
|
2023-11-19 15:35:28 +00:00
|
|
|
uint32_t tmp = (uint32_t)ui_state.new_ppm;
|
|
|
|
_ui_numberInputKeypad(&tmp, msg);
|
2023-11-18 21:33:36 +00:00
|
|
|
//The PPM correction holds in an INT16 even though here we use a UINT16.
|
|
|
|
if(tmp <= INT16_MAX) {
|
|
|
|
ui_state.new_ppm = (uint16_t)tmp;
|
|
|
|
ui_state.input_position += 1;
|
|
|
|
}
|
2023-10-22 23:51:29 +00:00
|
|
|
}
|
|
|
|
#if !defined(UI_NO_KEYBOARD)
|
|
|
|
else if(msg.keys & KEY_HASH)
|
|
|
|
{
|
2023-11-19 15:35:28 +00:00
|
|
|
ui_state.new_ppm_sign *= -1;
|
|
|
|
if(ui_state.new_ppm_sign > 0)
|
2023-10-22 23:51:29 +00:00
|
|
|
{
|
|
|
|
ui_state.input_position -= 1;
|
|
|
|
}
|
|
|
|
else if(ui_state.new_ppm < 0)
|
|
|
|
{
|
|
|
|
ui_state.input_position += 1;
|
|
|
|
}
|
|
|
|
vp_flush();
|
2023-11-19 15:35:28 +00:00
|
|
|
vp_queuePPM((int16_t)ui_state.new_ppm_sign*ui_state.new_ppm);
|
2023-10-22 23:51:29 +00:00
|
|
|
vp_play();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
else if (msg.long_press && (msg.keys & KEY_F1) && (state.settings.vpLevel > vpBeep))
|
|
|
|
{
|
2023-11-19 15:35:28 +00:00
|
|
|
vp_queuePPM((int16_t)ui_state.new_ppm_sign*ui_state.new_ppm);
|
2023-10-22 23:51:29 +00:00
|
|
|
f1Handled=true;
|
|
|
|
}
|
|
|
|
break;
|
2023-09-25 12:16:32 +00:00
|
|
|
default:
|
2023-09-29 09:41:27 +00:00
|
|
|
state.ui_screen = SETTINGS_RADIO;
|
2023-09-25 12:16:32 +00:00
|
|
|
}
|
2023-10-22 21:53:19 +00:00
|
|
|
// If ENTER or ESC are pressed, exit edit mode, R_SHIFT is managed separately
|
|
|
|
if((ui_state.menu_selected != R_SHIFT && msg.keys & KEY_ENTER) || msg.keys & KEY_ESC)
|
2023-09-29 09:41:27 +00:00
|
|
|
ui_state.edit_mode = false;
|
2023-09-25 12:16:32 +00:00
|
|
|
}
|
|
|
|
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);
|
2023-09-29 09:41:27 +00:00
|
|
|
else if(msg.keys & KEY_ENTER) {
|
|
|
|
ui_state.edit_mode = true;
|
2023-10-22 21:53:19 +00:00
|
|
|
// If we are entering R_SHIFT clear temp offset
|
|
|
|
if (ui_state.menu_selected == R_SHIFT)
|
|
|
|
ui_state.new_shift = 0;
|
2023-11-19 15:35:28 +00:00
|
|
|
else if(ui_state.menu_selected == R_PPM) {
|
2023-10-22 23:51:29 +00:00
|
|
|
ui_state.new_ppm = 0;
|
2023-11-19 15:35:28 +00:00
|
|
|
ui_state.new_ppm_sign = 1;
|
|
|
|
}
|
2023-09-29 09:41:27 +00:00
|
|
|
// Reset input position
|
|
|
|
ui_state.input_position = 0;
|
|
|
|
}
|
2023-09-25 12:16:32 +00:00
|
|
|
else if(msg.keys & KEY_ESC)
|
|
|
|
_ui_menuBack(MENU_SETTINGS);
|
|
|
|
break;
|
2021-05-10 20:20:10 +00:00
|
|
|
// M17 Settings
|
|
|
|
case SETTINGS_M17:
|
2021-05-11 06:20:18 +00:00
|
|
|
if(ui_state.edit_mode)
|
|
|
|
{
|
2023-09-05 18:38:22 +00:00
|
|
|
switch (ui_state.menu_selected)
|
2022-09-05 11:17:43 +00:00
|
|
|
{
|
2023-09-05 18:38:22 +00:00
|
|
|
case M17_CALLSIGN:
|
|
|
|
// Handle text input for M17 callsign
|
|
|
|
if(msg.keys & KEY_ENTER)
|
|
|
|
{
|
|
|
|
_ui_textInputConfirm(ui_state.new_callsign);
|
|
|
|
// Save selected callsign and disable input mode
|
|
|
|
strncpy(state.settings.callsign, ui_state.new_callsign, 10);
|
|
|
|
ui_state.edit_mode = false;
|
|
|
|
vp_announceBuffer(¤tLanguage->callsign,
|
|
|
|
false, true, state.settings.callsign);
|
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_ESC)
|
|
|
|
{
|
|
|
|
// Discard selected callsign and disable input mode
|
|
|
|
ui_state.edit_mode = false;
|
|
|
|
vp_announceBuffer(¤tLanguage->callsign,
|
|
|
|
false, true, state.settings.callsign);
|
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_UP || msg.keys & KEY_DOWN ||
|
|
|
|
msg.keys & KEY_LEFT || msg.keys & KEY_RIGHT)
|
|
|
|
{
|
|
|
|
_ui_textInputDel(ui_state.new_callsign);
|
|
|
|
}
|
2023-10-22 21:07:58 +00:00
|
|
|
else if(input_isCharPressed(msg))
|
2023-09-05 18:38:22 +00:00
|
|
|
{
|
|
|
|
_ui_textInputKeypad(ui_state.new_callsign, 9, msg, true);
|
|
|
|
}
|
|
|
|
else if (msg.long_press && (msg.keys & KEY_F1) && (state.settings.vpLevel > vpBeep))
|
|
|
|
{
|
|
|
|
vp_announceBuffer(¤tLanguage->callsign,
|
|
|
|
true, true, ui_state.new_callsign);
|
|
|
|
f1Handled=true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case M17_CAN:
|
|
|
|
if(msg.keys & KEY_DOWN || msg.keys & KNOB_LEFT)
|
|
|
|
_ui_changeM17Can(-1);
|
|
|
|
else if(msg.keys & KEY_UP || msg.keys & KNOB_RIGHT)
|
|
|
|
_ui_changeM17Can(+1);
|
|
|
|
else if(msg.keys & KEY_ENTER)
|
|
|
|
ui_state.edit_mode = !ui_state.edit_mode;
|
|
|
|
else if(msg.keys & KEY_ESC)
|
|
|
|
ui_state.edit_mode = false;
|
|
|
|
break;
|
|
|
|
case M17_CAN_RX:
|
|
|
|
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)))
|
|
|
|
{
|
|
|
|
state.settings.m17_can_rx =
|
|
|
|
!state.settings.m17_can_rx;
|
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_ENTER)
|
|
|
|
ui_state.edit_mode = !ui_state.edit_mode;
|
|
|
|
else if(msg.keys & KEY_ESC)
|
|
|
|
ui_state.edit_mode = false;
|
2022-09-05 11:01:58 +00:00
|
|
|
}
|
2021-05-11 06:20:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(msg.keys & KEY_ENTER)
|
|
|
|
{
|
2023-05-28 11:35:13 +00:00
|
|
|
// Enable edit mode
|
2021-05-11 06:20:18 +00:00
|
|
|
ui_state.edit_mode = true;
|
2023-05-28 11:35:13 +00:00
|
|
|
|
|
|
|
// If callsign input, reset text input variables
|
|
|
|
if(ui_state.menu_selected == M17_CALLSIGN)
|
|
|
|
{
|
|
|
|
_ui_textInputReset(ui_state.new_callsign);
|
|
|
|
vp_announceBuffer(¤tLanguage->callsign,
|
|
|
|
true, true, ui_state.new_callsign);
|
|
|
|
}
|
2021-05-11 06:20:18 +00:00
|
|
|
}
|
2023-05-28 11:35:13 +00:00
|
|
|
else if(msg.keys & KEY_UP || msg.keys & KNOB_LEFT)
|
|
|
|
_ui_menuUp(settings_m17_num);
|
|
|
|
else if(msg.keys & KEY_DOWN || msg.keys & KNOB_RIGHT)
|
|
|
|
_ui_menuDown(settings_m17_num);
|
|
|
|
else if((msg.keys & KEY_RIGHT) && (ui_state.menu_selected == M17_CAN))
|
|
|
|
_ui_changeM17Can(+1);
|
|
|
|
else if((msg.keys & KEY_LEFT) && (ui_state.menu_selected == M17_CAN))
|
|
|
|
_ui_changeM17Can(-1);
|
2021-05-11 06:20:18 +00:00
|
|
|
else if(msg.keys & KEY_ESC)
|
2023-05-28 11:35:13 +00:00
|
|
|
{
|
|
|
|
*sync_rtx = true;
|
2021-05-11 06:20:18 +00:00
|
|
|
_ui_menuBack(MENU_SETTINGS);
|
2023-05-28 11:35:13 +00:00
|
|
|
}
|
2021-05-11 06:20:18 +00:00
|
|
|
}
|
2021-05-10 20:20:10 +00:00
|
|
|
break;
|
2022-05-18 11:18:12 +00:00
|
|
|
case SETTINGS_VOICE:
|
|
|
|
if(msg.keys & KEY_LEFT || (ui_state.edit_mode &&
|
|
|
|
(msg.keys & KEY_DOWN || msg.keys & KNOB_LEFT)))
|
|
|
|
{
|
|
|
|
switch(ui_state.menu_selected)
|
|
|
|
{
|
|
|
|
case VP_LEVEL:
|
|
|
|
_ui_changeVoiceLevel(-1);
|
|
|
|
break;
|
|
|
|
case VP_PHONETIC:
|
|
|
|
_ui_changePhoneticSpell(false);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
state.ui_screen = SETTINGS_VOICE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_RIGHT || (ui_state.edit_mode &&
|
|
|
|
(msg.keys & KEY_UP || msg.keys & KNOB_RIGHT)))
|
|
|
|
{
|
|
|
|
switch(ui_state.menu_selected)
|
|
|
|
{
|
|
|
|
case VP_LEVEL:
|
|
|
|
_ui_changeVoiceLevel(1);
|
|
|
|
break;
|
|
|
|
case VP_PHONETIC:
|
|
|
|
_ui_changePhoneticSpell(true);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
state.ui_screen = SETTINGS_VOICE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_UP || msg.keys & KNOB_LEFT)
|
|
|
|
_ui_menuUp(settings_voice_num);
|
|
|
|
else if(msg.keys & KEY_DOWN || msg.keys & KNOB_RIGHT)
|
|
|
|
_ui_menuDown(settings_voice_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;
|
2022-02-26 11:42:28 +00:00
|
|
|
case SETTINGS_RESET2DEFAULTS:
|
|
|
|
if(! ui_state.edit_mode){
|
|
|
|
//require a confirmation ENTER, then another
|
|
|
|
//edit_mode is slightly misused to allow for this
|
|
|
|
if(msg.keys & KEY_ENTER)
|
|
|
|
{
|
|
|
|
ui_state.edit_mode = true;
|
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_ESC)
|
|
|
|
{
|
|
|
|
_ui_menuBack(MENU_SETTINGS);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(msg.keys & KEY_ENTER)
|
|
|
|
{
|
|
|
|
ui_state.edit_mode = false;
|
2022-03-26 15:42:02 +00:00
|
|
|
state_resetSettingsAndVfo();
|
2022-02-26 11:42:28 +00:00
|
|
|
_ui_menuBack(MENU_SETTINGS);
|
|
|
|
}
|
|
|
|
else if(msg.keys & KEY_ESC)
|
|
|
|
{
|
|
|
|
ui_state.edit_mode = false;
|
|
|
|
_ui_menuBack(MENU_SETTINGS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2020-12-05 17:40:08 +00:00
|
|
|
}
|
2023-09-10 20:57:04 +00:00
|
|
|
|
|
|
|
// Enable Tx only if in MAIN_VFO or MAIN_MEM states
|
|
|
|
bool inMemOrVfo = (state.ui_screen == MAIN_VFO) || (state.ui_screen == MAIN_MEM);
|
|
|
|
if ((macro_menu == true) || ((inMemOrVfo == false) && (state.txDisable == false)))
|
|
|
|
{
|
|
|
|
state.txDisable = true;
|
|
|
|
*sync_rtx = true;
|
|
|
|
}
|
2022-08-16 19:39:47 +00:00
|
|
|
if (!f1Handled && (msg.keys & KEY_F1) && (state.settings.vpLevel > vpBeep))
|
|
|
|
{
|
|
|
|
vp_replayLastPrompt();
|
|
|
|
}
|
2022-08-29 19:35:44 +00:00
|
|
|
else if ((priorUIScreen!=state.ui_screen) && state.settings.vpLevel > vpLow)
|
|
|
|
{
|
|
|
|
// When we switch to VFO or Channel screen, we need to announce it.
|
2022-09-01 11:43:53 +00:00
|
|
|
// Likewise for information screens.
|
2022-08-29 19:35:44 +00:00
|
|
|
// All other cases are handled as needed.
|
2022-09-01 11:43:53 +00:00
|
|
|
vp_announceScreen(state.ui_screen);
|
2022-08-29 19:35:44 +00:00
|
|
|
}
|
2022-09-11 09:38:40 +00:00
|
|
|
// generic beep for any keydown if beep is enabled.
|
2022-09-09 13:24:08 +00:00
|
|
|
// At vp levels higher than beep, keys will generate voice so no need
|
|
|
|
// to beep or you'll get an unwanted click.
|
|
|
|
if ((msg.keys &0xffff) && (state.settings.vpLevel == vpBeep))
|
2022-09-11 09:38:40 +00:00
|
|
|
vp_beep(BEEP_KEY_GENERIC, SHORT_BEEP);
|
2022-09-10 00:11:01 +00:00
|
|
|
// If we exit and re-enter the same menu, we want to ensure it speaks.
|
|
|
|
if (msg.keys & KEY_ESC)
|
|
|
|
_ui_reset_menu_anouncement_tracking();
|
2020-11-26 21:44:39 +00:00
|
|
|
}
|
2021-11-22 22:06:11 +00:00
|
|
|
else if(event.type == EVENT_STATUS)
|
|
|
|
{
|
2022-09-13 05:40:12 +00:00
|
|
|
#ifdef GPS_PRESENT
|
|
|
|
if ((state.ui_screen == MENU_GPS) &&
|
2022-09-13 06:37:36 +00:00
|
|
|
(!vp_isPlaying()) &&
|
|
|
|
(state.settings.vpLevel > vpLow) &&
|
|
|
|
(!txOngoing && !rtx_rxSquelchOpen()))
|
2022-09-13 05:40:12 +00:00
|
|
|
{// automatically read speed and direction changes only!
|
|
|
|
vpGPSInfoFlags_t whatChanged = GetGPSDirectionOrSpeedChanged();
|
|
|
|
if (whatChanged != vpGPSNone)
|
|
|
|
vp_announceGPSInfo(whatChanged);
|
|
|
|
}
|
|
|
|
#endif // GPS_PRESENT
|
2022-06-03 12:22:08 +00:00
|
|
|
|
2021-12-07 22:13:15 +00:00
|
|
|
if (txOngoing || rtx_rxSquelchOpen())
|
2021-12-13 20:52:19 +00:00
|
|
|
{
|
2022-10-01 09:17:35 +00:00
|
|
|
if (txOngoing)
|
2023-08-08 18:49:12 +00:00
|
|
|
macro_latched = 0;
|
2021-12-13 20:52:19 +00:00
|
|
|
_ui_exitStandby(now);
|
|
|
|
return;
|
|
|
|
}
|
2021-11-22 22:06:11 +00:00
|
|
|
|
2021-12-13 20:52:19 +00:00
|
|
|
if (_ui_checkStandby(now - last_event_tick))
|
2021-11-22 22:06:11 +00:00
|
|
|
{
|
2021-12-13 20:52:19 +00:00
|
|
|
_ui_enterStandby();
|
2021-11-22 22:06:11 +00:00
|
|
|
}
|
|
|
|
}
|
2020-11-26 21:44:39 +00:00
|
|
|
}
|
2020-11-24 13:23:05 +00:00
|
|
|
|
2022-08-04 20:48:41 +00:00
|
|
|
bool ui_updateGUI()
|
2020-11-26 21:44:39 +00:00
|
|
|
{
|
2022-08-04 20:48:41 +00:00
|
|
|
if(redraw_needed == false)
|
|
|
|
return false;
|
|
|
|
|
2020-10-31 17:12:44 +00:00
|
|
|
if(!layout_ready)
|
|
|
|
{
|
|
|
|
layout = _ui_calculateLayout();
|
|
|
|
layout_ready = true;
|
|
|
|
}
|
2020-12-06 19:31:06 +00:00
|
|
|
// Draw current GUI page
|
|
|
|
switch(last_state.ui_screen)
|
|
|
|
{
|
2020-12-30 14:46:43 +00:00
|
|
|
// VFO main screen
|
2021-01-09 18:37:51 +00:00
|
|
|
case MAIN_VFO:
|
2022-09-15 13:59:52 +00:00
|
|
|
_ui_drawMainVFO(&ui_state);
|
2020-12-06 19:31:06 +00:00
|
|
|
break;
|
2020-12-30 14:46:43 +00:00
|
|
|
// VFO frequency input screen
|
2021-01-09 18:37:51 +00:00
|
|
|
case MAIN_VFO_INPUT:
|
2021-01-30 07:33:39 +00:00
|
|
|
_ui_drawMainVFOInput(&ui_state);
|
2021-01-09 18:37:51 +00:00
|
|
|
break;
|
|
|
|
// MEM main screen
|
|
|
|
case MAIN_MEM:
|
2022-09-15 13:59:52 +00:00
|
|
|
_ui_drawMainMEM(&ui_state);
|
2021-05-06 11:03:41 +00:00
|
|
|
break;
|
2020-12-06 19:31:06 +00:00
|
|
|
// Top menu screen
|
|
|
|
case MENU_TOP:
|
2021-01-09 08:25:24 +00:00
|
|
|
_ui_drawMenuTop(&ui_state);
|
2020-12-20 09:47:07 +00:00
|
|
|
break;
|
2021-01-24 17:53:43 +00:00
|
|
|
// Zone menu screen
|
2022-03-26 12:42:10 +00:00
|
|
|
case MENU_BANK:
|
|
|
|
_ui_drawMenuBank(&ui_state);
|
2021-01-24 17:53:43 +00:00
|
|
|
break;
|
2021-01-01 21:06:35 +00:00
|
|
|
// Channel menu screen
|
|
|
|
case MENU_CHANNEL:
|
2021-01-09 08:25:24 +00:00
|
|
|
_ui_drawMenuChannel(&ui_state);
|
2021-01-01 21:06:35 +00:00
|
|
|
break;
|
2021-01-24 17:53:43 +00:00
|
|
|
// Contacts menu screen
|
|
|
|
case MENU_CONTACTS:
|
|
|
|
_ui_drawMenuContacts(&ui_state);
|
|
|
|
break;
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef GPS_PRESENT
|
2021-02-11 08:44:41 +00:00
|
|
|
// GPS menu screen
|
|
|
|
case MENU_GPS:
|
2021-02-14 13:04:01 +00:00
|
|
|
_ui_drawMenuGPS();
|
2021-02-11 08:44:41 +00:00
|
|
|
break;
|
2021-02-14 16:49:23 +00:00
|
|
|
#endif
|
2020-12-20 09:47:07 +00:00
|
|
|
// Settings menu screen
|
|
|
|
case MENU_SETTINGS:
|
2021-01-09 08:25:24 +00:00
|
|
|
_ui_drawMenuSettings(&ui_state);
|
2020-12-06 19:31:06 +00:00
|
|
|
break;
|
2022-03-12 23:21:52 +00:00
|
|
|
// Flash backup and restore screen
|
|
|
|
case MENU_BACKUP_RESTORE:
|
|
|
|
_ui_drawMenuBackupRestore(&ui_state);
|
|
|
|
break;
|
|
|
|
// Flash backup screen
|
|
|
|
case MENU_BACKUP:
|
|
|
|
_ui_drawMenuBackup(&ui_state);
|
|
|
|
break;
|
|
|
|
// Flash restore screen
|
|
|
|
case MENU_RESTORE:
|
|
|
|
_ui_drawMenuRestore(&ui_state);
|
|
|
|
break;
|
2021-01-30 07:02:41 +00:00
|
|
|
// Info menu screen
|
|
|
|
case MENU_INFO:
|
|
|
|
_ui_drawMenuInfo(&ui_state);
|
|
|
|
break;
|
2021-01-30 10:57:00 +00:00
|
|
|
// About menu screen
|
|
|
|
case MENU_ABOUT:
|
2021-01-30 18:58:25 +00:00
|
|
|
_ui_drawMenuAbout();
|
2021-01-30 10:57:00 +00:00
|
|
|
break;
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef RTC_PRESENT
|
2020-12-22 16:49:00 +00:00
|
|
|
// Time&Date settings screen
|
|
|
|
case SETTINGS_TIMEDATE:
|
2021-01-30 07:33:39 +00:00
|
|
|
_ui_drawSettingsTimeDate();
|
2020-12-22 16:49:00 +00:00
|
|
|
break;
|
2020-12-31 15:36:32 +00:00
|
|
|
// Time&Date settings screen, edit mode
|
|
|
|
case SETTINGS_TIMEDATE_SET:
|
2021-01-30 07:33:39 +00:00
|
|
|
_ui_drawSettingsTimeDateSet(&ui_state);
|
2020-12-31 15:36:32 +00:00
|
|
|
break;
|
2021-01-01 17:58:35 +00:00
|
|
|
#endif
|
2021-02-13 16:23:16 +00:00
|
|
|
// Display settings screen
|
2021-01-26 21:04:19 +00:00
|
|
|
case SETTINGS_DISPLAY:
|
2021-01-29 21:59:38 +00:00
|
|
|
_ui_drawSettingsDisplay(&ui_state);
|
2021-01-26 21:04:19 +00:00
|
|
|
break;
|
2022-06-28 09:19:50 +00:00
|
|
|
#ifdef GPS_PRESENT
|
2021-02-13 16:23:16 +00:00
|
|
|
// GPS settings screen
|
|
|
|
case SETTINGS_GPS:
|
|
|
|
_ui_drawSettingsGPS(&ui_state);
|
|
|
|
break;
|
2021-02-14 16:49:23 +00:00
|
|
|
#endif
|
2021-05-10 20:20:10 +00:00
|
|
|
// M17 settings screen
|
|
|
|
case SETTINGS_M17:
|
2021-05-11 06:20:18 +00:00
|
|
|
_ui_drawSettingsM17(&ui_state);
|
2021-05-10 20:20:10 +00:00
|
|
|
break;
|
2022-08-16 19:39:47 +00:00
|
|
|
case SETTINGS_VOICE:
|
|
|
|
_ui_drawSettingsVoicePrompts(&ui_state);
|
|
|
|
break;
|
2022-02-26 11:42:28 +00:00
|
|
|
// Screen to support resetting Settings and VFO to defaults
|
|
|
|
case SETTINGS_RESET2DEFAULTS:
|
|
|
|
_ui_drawSettingsReset2Defaults(&ui_state);
|
|
|
|
break;
|
2023-09-25 12:16:32 +00:00
|
|
|
// Screen to set frequency offset and step
|
|
|
|
case SETTINGS_RADIO:
|
|
|
|
_ui_drawSettingsRadio(&ui_state);
|
|
|
|
break;
|
2020-12-18 18:03:34 +00:00
|
|
|
// Low battery screen
|
|
|
|
case LOW_BAT:
|
2021-01-01 20:11:22 +00:00
|
|
|
_ui_drawLowBatteryScreen();
|
2020-12-18 18:03:34 +00:00
|
|
|
break;
|
2020-12-06 19:31:06 +00:00
|
|
|
}
|
2022-08-04 20:48:41 +00:00
|
|
|
|
2021-01-31 12:29:23 +00:00
|
|
|
// If MACRO menu is active draw it
|
2022-08-04 20:48:41 +00:00
|
|
|
if(macro_menu)
|
|
|
|
{
|
2021-01-31 12:29:23 +00:00
|
|
|
_ui_drawDarkOverlay();
|
2023-09-08 07:48:03 +00:00
|
|
|
_ui_drawMacroMenu(&ui_state);
|
2021-01-31 12:29:23 +00:00
|
|
|
}
|
2022-08-04 20:48:41 +00:00
|
|
|
|
|
|
|
redraw_needed = false;
|
|
|
|
return true;
|
2020-10-30 19:13:52 +00:00
|
|
|
}
|
|
|
|
|
2022-08-10 11:59:46 +00:00
|
|
|
bool ui_pushEvent(const uint8_t type, const uint32_t data)
|
2022-06-29 05:47:38 +00:00
|
|
|
{
|
|
|
|
uint8_t newHead = (evQueue_wrPos + 1) % MAX_NUM_EVENTS;
|
|
|
|
|
|
|
|
// Queue is full
|
|
|
|
if(newHead == evQueue_rdPos) return false;
|
|
|
|
|
2022-08-10 11:59:46 +00:00
|
|
|
// Preserve atomicity when writing the new element into the queue.
|
|
|
|
event_t event;
|
|
|
|
event.type = type;
|
|
|
|
event.payload = data;
|
|
|
|
|
2022-06-29 05:47:38 +00:00
|
|
|
evQueue[evQueue_wrPos] = event;
|
|
|
|
evQueue_wrPos = newHead;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-10-30 19:13:52 +00:00
|
|
|
void ui_terminate()
|
|
|
|
{
|
|
|
|
}
|