diff --git a/meson.build b/meson.build
index 5620979f..f22406c9 100644
--- a/meson.build
+++ b/meson.build
@@ -22,6 +22,7 @@ def = {'VCOM_ENABLED' : ''}
openrtx_src = ['openrtx/src/state.c',
'openrtx/src/ui/ui.c',
'openrtx/src/ui/ui_main.c',
+ 'openrtx/src/ui/ui_mode.c',
'openrtx/src/ui/ui_menu.c',
'openrtx/src/threads.c',
'openrtx/src/battery.c',
diff --git a/openrtx/include/interfaces/graphics.h b/openrtx/include/interfaces/graphics.h
index 27146e6b..dd7d43be 100644
--- a/openrtx/include/interfaces/graphics.h
+++ b/openrtx/include/interfaces/graphics.h
@@ -298,10 +298,31 @@ void gfx_drawBattery(point_t start, uint16_t width, uint16_t height, uint8_t per
* @param height: Smeter height
* @param rssi: rssi level in dBm
* @param squelch: squelch level in percentage
- * @param color: color of the squelch and smeter bar
+ * @param color: color of the squelch bar
*/
void gfx_drawSmeter(point_t start, uint16_t width, uint16_t height, float rssi, float squelch, color_t color);
+/**
+ * Function to draw Smeter of arbitrary size.
+ * Version without squelch bar for digital protocols
+ * Starting coordinates are relative to the top left point.
+ * @param start: Smeter start point, in pixel coordinates.
+ * @param width: Smeter width
+ * @param height: Smeter height
+ * @param rssi: rssi level in dBm
+ */
+void gfx_drawSmeterNoSquelch(point_t start, uint16_t width, uint16_t height, float rssi);
+
+/**
+ * Function to draw level meter of arbitrary size.
+ * Starting coordinates are relative to the top left point.
+ * @param start: level meter start point, in pixel coordinates.
+ * @param width: level meter width
+ * @param height: level meter height
+ * @param level: level in range {0, 255}
+ */
+void gfx_drawLevelMeter(point_t start, uint16_t width, uint16_t height, uint8_t level);
+
/**
* Function to draw GPS SNR bar graph of arbitrary size.
* Starting coordinates are relative to the top left point.
diff --git a/openrtx/include/ui.h b/openrtx/include/ui.h
index bd9a3d0a..2ba848c3 100644
--- a/openrtx/include/ui.h
+++ b/openrtx/include/ui.h
@@ -40,6 +40,8 @@ enum uiScreen
MAIN_VFO = 0,
MAIN_VFO_INPUT,
MAIN_MEM,
+ MODE_VFO,
+ MODE_MEM,
MENU_TOP,
MENU_ZONE,
MENU_CHANNEL,
@@ -134,6 +136,8 @@ typedef struct layout_t
fontSize_t bottom_font;
fontSize_t input_font;
fontSize_t menu_font;
+ fontSize_t mode_font_big;
+ fontSize_t mode_font_small;
} layout_t;
/**
diff --git a/openrtx/src/graphics.c b/openrtx/src/graphics.c
index e94128e5..5db7f9f7 100644
--- a/openrtx/src/graphics.c
+++ b/openrtx/src/graphics.c
@@ -612,15 +612,15 @@ void gfx_drawBattery(point_t start, uint16_t width, uint16_t height,
* Function to draw RSSI-meter of arbitrary size
* starting coordinates are relative to the top left point.
*
- * * * * * * * *|
- * ***************************************** |
- * ****************************************** <- RSSI |
- * ****************************************** | <-- Height (px)
- * ****************************************** |
- * **************** <-- Squelch |
- * *************** |
- * * * * * * * *|
- * ___________________________________________________________________
+ * 1 2 3 4 5 6 7 8 9 +10 +20|
+ * ****************************************** |
+ * ****************************************** <- RSSI |
+ * ****************************************** | <-- Height (px)
+ * ****************************************** |
+ * **************** <-- Squelch |
+ * *************** |
+ * * * * * * * * * * * *|
+ * _________________________________________________________________
*
* ^
* |
@@ -675,6 +675,101 @@ void gfx_drawSmeter(point_t start, uint16_t width, uint16_t height, float rssi,
gfx_drawRect(squelch_pos, squelch_width, squelch_height, color, true);
}
+/*
+ * Function to draw RSSI-meter of arbitrary size
+ * Version without squelch bar for digital protocols
+ * starting coordinates are relative to the top left point.
+ *
+ * ****************************************** |
+ * ****************************************** <- RSSI |
+ * ****************************************** | <-- Height (px)
+ * ****************************************** |
+ * 1 2 3 4 5 6 7 8 9 +10 +20|
+ * _________________________________________________________________
+ *
+ * ^
+ * |
+ *
+ * Width (px)
+ *
+ */
+void gfx_drawSmeterNoSquelch(point_t start, uint16_t width, uint16_t height, float rssi)
+{
+ color_t white = {255, 255, 255, 255};
+ color_t yellow = {250, 180, 19 , 255};
+ color_t red = {255, 0, 0 , 255};
+
+ fontSize_t font = FONT_SIZE_5PT;
+ uint8_t font_height = gfx_getFontHeight(font);
+ // S-level marks and numbers
+ for(int i = 0; i < 11; i++)
+ {
+ color_t color = (i % 3 == 0) ? yellow : white;
+ color = (i > 9) ? red : color;
+ point_t pixel_pos = {start.x + i * (width - 1) / 11, start.y};
+ pixel_pos.y += ((height - 1) + font_height);
+ if (i == 10) {
+ pixel_pos.x -= 8;
+ gfx_print(pixel_pos, font, TEXT_ALIGN_LEFT, color, "+%d", i);
+ }
+ else
+ gfx_print(pixel_pos, font, TEXT_ALIGN_LEFT, color, "%d", i);
+ if (i == 10) {
+ pixel_pos.x += 8;
+ }
+ }
+
+ point_t pixel_pos = {start.x + width - 11, start.y};
+ pixel_pos.y += ((height - 1) + font_height);
+ gfx_print(pixel_pos, font, TEXT_ALIGN_LEFT, red, "+20");
+
+ // RSSI bar
+ uint16_t rssi_height = height - 4;
+ float s_level = (127.0f + rssi) / 6.0f;
+ uint16_t rssi_width = (s_level < 0.0f) ? 0 : (s_level * (width - 1) / 11);
+ rssi_width = (s_level > 10.0f) ? width : rssi_width;
+ point_t rssi_pos = { start.x, start.y + 1 };
+ gfx_drawRect(rssi_pos, rssi_width, rssi_height, white, true);
+}
+
+/*
+ * Function to draw level meter of arbitrary size
+ * starting coordinates are relative to the top left point.
+ *
+ * * * * * *|
+ * ****************************************** |
+ * ****************************************** <- level |
+ * ****************************************** | <-- Height (px)
+ * ****************************************** |
+ * * * * * *|
+ * _________________________________________________________________
+ *
+ * ^
+ * |
+ *
+ * Width (px)
+ *
+ */
+void gfx_drawLevelMeter(point_t start, uint16_t width, uint16_t height, uint8_t level)
+{
+ color_t white = {255, 255, 255, 255};
+
+ // S-level marks and numbers
+ for(int i = 0; i <= 4; i++)
+ {
+ point_t pixel_pos = {start.x + i * (width - 1) / 4, start.y};
+ gfx_setPixel(pixel_pos, white);
+ pixel_pos.y += (height - 1);
+ gfx_setPixel(pixel_pos, white);
+ }
+
+ // Level bar
+ uint16_t level_height = height - 4;
+ uint16_t level_width = (level / 255 * width);
+ point_t level_pos = { start.x, start.y + 2 };
+ gfx_drawRect(level_pos, level_width, level_height, white, true);
+}
+
/*
* Function to draw GPS satellites snr bar graph of arbitrary size
* starting coordinates are relative to the top left point.
diff --git a/openrtx/src/ui/ui.c b/openrtx/src/ui/ui.c
index 8bf4120a..ed8ea54d 100644
--- a/openrtx/src/ui/ui.c
+++ b/openrtx/src/ui/ui.c
@@ -85,6 +85,8 @@ extern void _ui_drawMEMBottom();
extern void _ui_drawMainVFO();
extern void _ui_drawMainVFOInput(ui_state_t* ui_state);
extern void _ui_drawMainMEM();
+extern void _ui_drawModeVFO();
+extern void _ui_drawModeMEM();
/* UI menu functions, their implementation is in "ui_menu.c" */
extern void _ui_drawMenuTop(ui_state_t* ui_state);
extern void _ui_drawMenuZone(ui_state_t* ui_state);
@@ -226,6 +228,10 @@ layout_t _ui_calculateLayout()
const fontSize_t input_font = FONT_SIZE_12PT;
// Menu font
const fontSize_t menu_font = FONT_SIZE_8PT;
+ // 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;
// Radioddity GD-77
#elif SCREEN_HEIGHT > 63
@@ -256,6 +262,10 @@ layout_t _ui_calculateLayout()
const fontSize_t input_font = FONT_SIZE_8PT;
// Menu font
const fontSize_t menu_font = FONT_SIZE_6PT;
+ // 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;
// Radioddity RD-5R
#elif SCREEN_HEIGHT > 47
@@ -283,6 +293,10 @@ layout_t _ui_calculateLayout()
const fontSize_t input_font = FONT_SIZE_8PT;
// Menu font
const fontSize_t menu_font = FONT_SIZE_6PT;
+ // 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;
// Not present on this resolution
const fontSize_t line1_font = 0;
const fontSize_t bottom_font = 0;
@@ -321,7 +335,9 @@ layout_t _ui_calculateLayout()
line3_font,
bottom_font,
input_font,
- menu_font
+ menu_font,
+ mode_font_big,
+ mode_font_small
};
return new_layout;
}
@@ -779,6 +795,11 @@ void ui_updateFSM(event_t event, bool *sync_rtx)
state.ui_screen = MAIN_MEM;
}
}
+ else if(msg.keys & KEY_F1)
+ {
+ // Switch to Digital Mode VFO screen
+ state.ui_screen = MODE_VFO;
+ }
else if(input_isNumberPressed(msg))
{
// Open Frequency input screen
@@ -847,6 +868,46 @@ void ui_updateFSM(event_t event, bool *sync_rtx)
_ui_fsm_loadChannel(state.channel_index - 1, sync_rtx);
}
break;
+ // Digital Mode VFO screen
+ case MODE_VFO:
+ 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)
+ {
+ // Switch to VFO screen
+ state.ui_screen = MAIN_VFO;
+ }
+ else if(msg.keys & KEY_F1)
+ {
+ // Switch to Main VFO screen
+ state.ui_screen = MAIN_VFO;
+ }
+ break;
+ // Digital Mode MEM screen
+ case MODE_MEM:
+ 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)
+ {
+ // Switch to MEM screen
+ state.ui_screen = MAIN_MEM;
+ }
+ else if(msg.keys & KEY_F1)
+ {
+ // Switch to Main MEM screen
+ state.ui_screen = MAIN_MEM;
+ }
+ break;
// Top menu screen
case MENU_TOP:
if(msg.keys & KEY_UP || msg.keys & KNOB_LEFT)
@@ -1173,6 +1234,14 @@ void ui_updateGUI()
case MAIN_MEM:
_ui_drawMainMEM();
break;
+ // Digital Mode VFO screen
+ case MODE_VFO:
+ _ui_drawModeVFO();
+ break;
+ // Digital Mode MEM screen
+ case MODE_MEM:
+ _ui_drawModeMEM();
+ break;
// Top menu screen
case MENU_TOP:
_ui_drawMenuTop(&ui_state);
diff --git a/openrtx/src/ui/ui_main.c b/openrtx/src/ui/ui_main.c
index 7fdce81b..f00e7b92 100644
--- a/openrtx/src/ui/ui_main.c
+++ b/openrtx/src/ui/ui_main.c
@@ -145,22 +145,40 @@ void _ui_drawVFOMiddleInput(ui_state_t* ui_state)
}
}
-void _ui_drawBottom()
+void _ui_drawMainBottom()
{
// Squelch bar
float rssi = last_state.rssi;
float squelch = last_state.sqlLevel / 16.0f;
- point_t smeter_pos = { layout.horizontal_pad,
- layout.bottom_pos.y +
- layout.status_v_pad +
- layout.text_v_offset -
- layout.bottom_h };
- gfx_drawSmeter(smeter_pos,
- SCREEN_WIDTH - 2 * layout.horizontal_pad,
- layout.bottom_h - 1,
- rssi,
- squelch,
- color_white);
+ point_t meter_pos = { layout.horizontal_pad,
+ layout.bottom_pos.y +
+ layout.status_v_pad +
+ layout.text_v_offset -
+ layout.bottom_h };
+ uint16_t meter_height = layout.bottom_h - 1;
+ switch(last_state.channel.mode)
+ {
+ case FM:
+ gfx_drawSmeter(meter_pos,
+ SCREEN_WIDTH - 2 * layout.horizontal_pad,
+ meter_height,
+ rssi,
+ squelch,
+ color_white);
+ break;
+ case DMR:
+ meter_height = (meter_height / 2);
+ gfx_drawLevelMeter(meter_pos,
+ SCREEN_WIDTH - 2 * layout.horizontal_pad,
+ meter_height,
+ 255);
+ meter_pos.y += meter_height;
+ gfx_drawSmeterNoSquelch(meter_pos,
+ SCREEN_WIDTH - 2 * layout.horizontal_pad,
+ meter_height,
+ rssi);
+ break;
+ }
}
void _ui_drawMainVFO()
@@ -168,7 +186,7 @@ void _ui_drawMainVFO()
gfx_clearScreen();
_ui_drawMainTop();
_ui_drawFrequency();
- _ui_drawBottom();
+ _ui_drawMainBottom();
}
void _ui_drawMainVFOInput(ui_state_t* ui_state)
@@ -176,7 +194,7 @@ void _ui_drawMainVFOInput(ui_state_t* ui_state)
gfx_clearScreen();
_ui_drawMainTop();
_ui_drawVFOMiddleInput(ui_state);
- _ui_drawBottom();
+ _ui_drawMainBottom();
}
void _ui_drawMainMEM()
@@ -185,5 +203,5 @@ void _ui_drawMainMEM()
_ui_drawMainTop();
_ui_drawZoneChannel();
_ui_drawFrequency();
- _ui_drawBottom();
+ _ui_drawMainBottom();
}
diff --git a/openrtx/src/ui/ui_menu.c b/openrtx/src/ui/ui_menu.c
index d24ffff3..4b2ce940 100644
--- a/openrtx/src/ui/ui_menu.c
+++ b/openrtx/src/ui/ui_menu.c
@@ -594,17 +594,34 @@ bool _ui_drawMacroMenu() {
// Smeter bar
float rssi = last_state.rssi;
float squelch = last_state.sqlLevel / 16.0f;
- point_t smeter_pos = { layout.horizontal_pad,
+ point_t meter_pos = { layout.horizontal_pad,
layout.bottom_pos.y +
layout.status_v_pad +
layout.text_v_offset -
layout.bottom_h };
- gfx_drawSmeter(smeter_pos,
- SCREEN_WIDTH - 2 * layout.horizontal_pad,
- layout.bottom_h - 1,
- rssi,
- squelch,
- yellow_fab413);
-
+ uint16_t meter_height = layout.bottom_h - 1;
+ switch(last_state.channel.mode)
+ {
+ case FM:
+ gfx_drawSmeter(meter_pos,
+ SCREEN_WIDTH - 2 * layout.horizontal_pad,
+ meter_height,
+ rssi,
+ squelch,
+ yellow_fab413);
+ break;
+ case DMR:
+ meter_height = (meter_height / 2);
+ gfx_drawLevelMeter(meter_pos,
+ SCREEN_WIDTH - 2 * layout.horizontal_pad,
+ meter_height,
+ 255);
+ meter_pos.y += meter_height;
+ gfx_drawSmeterNoSquelch(meter_pos,
+ SCREEN_WIDTH - 2 * layout.horizontal_pad,
+ meter_height,
+ rssi);
+ break;
+ }
return true;
}
diff --git a/openrtx/src/ui/ui_mode.c b/openrtx/src/ui/ui_mode.c
new file mode 100644
index 00000000..c6904b4f
--- /dev/null
+++ b/openrtx/src/ui/ui_mode.c
@@ -0,0 +1,115 @@
+/***************************************************************************
+ * Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, *
+ * Niccolò Izzo IU2KIN *
+ * Frederik Saraci IU2NRO *
+ * Silvano Seva IU2KWO *
+ * *
+ * 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 *
+ ***************************************************************************/
+
+#include
+#include
+#include
+#include
+
+/* UI main screen helper functions, their implementation is in "ui_main.c" */
+extern void _ui_drawMainTop();
+extern void _ui_drawMainBottom();
+
+void _ui_drawModeVFOFreq()
+{
+ // Print VFO RX Frequency on line 1 of 3
+ gfx_printLine(1, 3, layout.top_h, SCREEN_HEIGHT - layout.bottom_h,
+ layout.horizontal_pad, layout.mode_font_big,
+ TEXT_ALIGN_CENTER, color_white, "%03lu.%05lu",
+ (unsigned long)last_state.channel.rx_frequency/1000000,
+ (unsigned long)last_state.channel.rx_frequency%1000000/10);
+}
+
+void _ui_drawMEMChannel()
+{
+ // Print Channel name on line 1 of 3
+ gfx_printLine(1, 3, layout.top_h, SCREEN_HEIGHT - layout.bottom_h,
+ layout.horizontal_pad, layout.mode_font_small,
+ TEXT_ALIGN_CENTER, color_white, "%03d: %.12s",
+ last_state.channel_index, last_state.channel.name);
+}
+
+void _ui_drawModeDetails()
+{
+ char bw_str[8] = { 0 };
+ char encdec_str[9] = { 0 };
+ switch(last_state.channel.mode)
+ {
+ case FM:
+ // Get Bandwith string
+ if(last_state.channel.bandwidth == BW_12_5)
+ snprintf(bw_str, 8, "12.5");
+ else if(last_state.channel.bandwidth == BW_20)
+ snprintf(bw_str, 8, "20");
+ else if(last_state.channel.bandwidth == BW_25)
+ snprintf(bw_str, 8, "25");
+ // Get encdec string
+ bool tone_tx_enable = last_state.channel.fm.txToneEn;
+ bool tone_rx_enable = last_state.channel.fm.rxToneEn;
+ if (tone_tx_enable && tone_rx_enable)
+ snprintf(encdec_str, 9, "E+D");
+ else if (tone_tx_enable && !tone_rx_enable)
+ snprintf(encdec_str, 9, "E");
+ else if (!tone_tx_enable && tone_rx_enable)
+ snprintf(encdec_str, 9, "D");
+ else
+ snprintf(encdec_str, 9, " ");
+
+ // Print Bandwidth info
+ gfx_printLine(2, 3, layout.top_h, SCREEN_HEIGHT - layout.bottom_h,
+ layout.horizontal_pad, layout.mode_font_small,
+ TEXT_ALIGN_LEFT, color_white, "BW:%s", bw_str);
+ // Print Tone and encdec info
+ gfx_printLine(3, 3, layout.top_h, SCREEN_HEIGHT - layout.bottom_h,
+ layout.horizontal_pad, layout.mode_font_small,
+ TEXT_ALIGN_LEFT, color_white, "T:%4.1f S:%s",
+ ctcss_tone[last_state.channel.fm.txTone]/10.0f,
+ encdec_str);
+ break;
+ case DMR:
+ // Print Module Frequency on line 2 of 3
+ gfx_printLine(2, 3, layout.top_h, SCREEN_HEIGHT - layout.bottom_h,
+ layout.horizontal_pad, layout.mode_font_small,
+ TEXT_ALIGN_LEFT, color_white, "TG:");
+ // Print User ID on line 3 of 3
+ gfx_printLine(3, 3, layout.top_h, SCREEN_HEIGHT - layout.bottom_h,
+ layout.horizontal_pad, layout.mode_font_small,
+ TEXT_ALIGN_LEFT, color_white, "ID:");
+ break;
+ }
+}
+
+void _ui_drawModeVFO()
+{
+ gfx_clearScreen();
+ _ui_drawMainTop();
+ _ui_drawModeVFOFreq();
+ _ui_drawModeDetails();
+ _ui_drawMainBottom();
+}
+
+void _ui_drawModeMEM()
+{
+ gfx_clearScreen();
+ _ui_drawMainTop();
+ _ui_drawMEMChannel();
+ _ui_drawModeDetails();
+ _ui_drawMainBottom();
+}
diff --git a/platform/drivers/keyboard/keyboard_linux.c b/platform/drivers/keyboard/keyboard_linux.c
index c1789f72..c67c9366 100644
--- a/platform/drivers/keyboard/keyboard_linux.c
+++ b/platform/drivers/keyboard/keyboard_linux.c
@@ -50,7 +50,7 @@ keyboard_t kbd_getKeys() {
if (state[SDL_SCANCODE_RIGHT]) keys |= KEY_RIGHT;
if (state[SDL_SCANCODE_RETURN]) keys |= KEY_ENTER;
if (state[SDL_SCANCODE_NONUSHASH]) keys |= KEY_HASH;
- if (state[SDL_SCANCODE_MINUS]) keys |= KEY_F1;
+ if (state[SDL_SCANCODE_N]) keys |= KEY_F1;
if (state[SDL_SCANCODE_M]) keys |= KEY_MONI;
if (state[SDL_SCANCODE_PAGEUP]) keys |= KNOB_LEFT;
if (state[SDL_SCANCODE_PAGEDOWN]) keys |= KNOB_RIGHT;