mirror of
https://github.com/eried/portapack-mayhem.git
synced 2025-11-08 06:32:59 -05:00
Multi screen support, with dyn alignment (#2801)
This commit is contained in:
parent
23cabb8b8a
commit
371b6b5079
161 changed files with 4042 additions and 4157 deletions
|
|
@ -279,7 +279,6 @@ set(CPPSRC
|
|||
apps/ui_aprs_rx.cpp
|
||||
apps/ui_aprs_tx.cpp
|
||||
apps/ui_battinfo.cpp
|
||||
apps/ui_bht_tx.cpp
|
||||
apps/ui_bmp_file_viewer.cpp
|
||||
apps/ui_btle_rx.cpp
|
||||
apps/ui_debug.cpp
|
||||
|
|
@ -314,7 +313,6 @@ set(CPPSRC
|
|||
apps/ui_weatherstation.cpp
|
||||
protocols/aprs.cpp
|
||||
protocols/ax25.cpp
|
||||
protocols/bht.cpp
|
||||
protocols/dcs.cpp
|
||||
protocols/encoders.cpp
|
||||
protocols/modems.cpp
|
||||
|
|
|
|||
|
|
@ -272,14 +272,14 @@ void RecentEntriesTable<AISRecentEntries>::draw(
|
|||
const Entry& entry,
|
||||
const Rect& target_rect,
|
||||
Painter& painter,
|
||||
const Style& style) {
|
||||
const Style& style,
|
||||
RecentEntriesColumns&) {
|
||||
std::string line = ais::format::mmsi(entry.mmsi) + " ";
|
||||
if (!entry.name.empty()) {
|
||||
line += ais::format::text(entry.name);
|
||||
} else {
|
||||
line += ais::format::text(entry.call_sign);
|
||||
}
|
||||
|
||||
line.resize(target_rect.width() / 8, ' ');
|
||||
painter.draw_string(target_rect.location(), style, line);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,10 +137,10 @@ class AISRecentEntryDetailView : public View {
|
|||
AISRecentEntry entry_{};
|
||||
|
||||
Button button_done{
|
||||
{125, 224, 96, 24},
|
||||
{UI_POS_X_CENTER(12) + UI_POS_WIDTH(6), UI_POS_Y(14), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
|
||||
"Done"};
|
||||
Button button_see_map{
|
||||
{19, 224, 96, 24},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), UI_POS_Y(14), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
|
||||
"See on map"};
|
||||
GeoMapView* geomap_view{nullptr};
|
||||
bool send_updates{false};
|
||||
|
|
@ -179,9 +179,9 @@ class AISAppView : public View {
|
|||
AISRecentEntries recent{};
|
||||
std::unique_ptr<AISLogger> logger{};
|
||||
|
||||
const RecentEntriesColumns columns{{
|
||||
RecentEntriesColumns columns{{
|
||||
{"MMSI", 9},
|
||||
{"Name/Call", 20},
|
||||
{"Name/Call", 0},
|
||||
}};
|
||||
AISRecentEntriesView recent_entries_view{columns, recent};
|
||||
AISRecentEntryDetailView recent_entry_detail_view{nav_};
|
||||
|
|
@ -189,11 +189,11 @@ class AISAppView : public View {
|
|||
static constexpr auto header_height = 1 * 16;
|
||||
|
||||
Text label_channel{
|
||||
{0 * 8, 0 * 16, 2 * 8, 1 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0), 2 * 8, 1 * 16},
|
||||
"Ch"};
|
||||
|
||||
OptionsField options_channel{
|
||||
{3 * 8, 0 * 16},
|
||||
{3 * 8, UI_POS_Y(0)},
|
||||
3,
|
||||
{
|
||||
{"87B", 161975000},
|
||||
|
|
@ -201,23 +201,23 @@ class AISAppView : public View {
|
|||
}};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{13 * 8, 0 * 16}};
|
||||
{13 * 8, UI_POS_Y(0)}};
|
||||
|
||||
LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
{15 * 8, UI_POS_Y(0)}};
|
||||
|
||||
VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
|
||||
RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4},
|
||||
{UI_POS_X(21), UI_POS_Y(0), UI_POS_WIDTH_REMAINING(23), 4},
|
||||
};
|
||||
|
||||
AudioVolumeField field_volume{
|
||||
{screen_width - 2 * 8, 0 * 16}};
|
||||
{UI_POS_X_RIGHT(2), UI_POS_Y(0)}};
|
||||
|
||||
Channel channel{
|
||||
{21 * 8, 5, 6 * 8, 4},
|
||||
{UI_POS_X(21), 5, UI_POS_WIDTH_REMAINING(23), 4},
|
||||
};
|
||||
SignalToken signal_token_tick_second{};
|
||||
uint8_t timer_seconds = 0;
|
||||
|
|
|
|||
|
|
@ -43,19 +43,19 @@ class AMOptionsView : public View {
|
|||
|
||||
private:
|
||||
Text label_config{
|
||||
{0 * 8, 0 * 16, 2 * 8, 1 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0), UI_POS_WIDTH(2), UI_POS_HEIGHT(1)},
|
||||
"BW",
|
||||
};
|
||||
|
||||
OptionsField options_config{
|
||||
{3 * 8, 0 * 16},
|
||||
{UI_POS_X(3), UI_POS_Y(0)},
|
||||
6, // Max option length
|
||||
{
|
||||
// Using common messages from freqman_ui.cpp
|
||||
}};
|
||||
|
||||
OptionsField zoom_config{
|
||||
{23 * 8, 0 * 16},
|
||||
{UI_POS_X_RIGHT(7), UI_POS_Y(0)},
|
||||
7,
|
||||
{{"ZOOM x1", 0},
|
||||
{"ZOOM x2", 6}} // offset index AM modes array FIR filters.
|
||||
|
|
@ -68,19 +68,19 @@ class AMFMAptOptionsView : public View {
|
|||
|
||||
private:
|
||||
Text label_config{
|
||||
{0 * 8, 0 * 16, 2 * 8, 1 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0), UI_POS_WIDTH(2), UI_POS_HEIGHT(1)},
|
||||
"BW",
|
||||
};
|
||||
|
||||
OptionsField options_config{
|
||||
{3 * 8, 0 * 16},
|
||||
{UI_POS_X(3), UI_POS_Y(0)},
|
||||
17, // Max option length chars "USB+FM(Wefax Apt)"
|
||||
{
|
||||
// Using common messages from freqman_ui.cpp In HF USB , Here we only need USB Audio demod, + post-FM demod fsubcarrier FM tone to get APT signal.
|
||||
}};
|
||||
|
||||
OptionsField zoom_config{
|
||||
{23 * 8, 0 * 16},
|
||||
{UI_POS_X_RIGHT(7), UI_POS_Y(0)},
|
||||
7,
|
||||
{{"ZOOM x1", 0},
|
||||
{"ZOOM x2", 6}} // offset index array filters.
|
||||
|
|
@ -93,21 +93,21 @@ class NBFMOptionsView : public View {
|
|||
|
||||
private:
|
||||
Text label_config{
|
||||
{0 * 8, 0 * 16, 2 * 8, 1 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0), UI_POS_WIDTH(2), UI_POS_HEIGHT(1)},
|
||||
"BW",
|
||||
};
|
||||
OptionsField options_config{
|
||||
{3 * 8, 0 * 16},
|
||||
{UI_POS_X(3), UI_POS_Y(0)},
|
||||
3, // Max option length
|
||||
{
|
||||
// Using common messages from freqman_ui.cpp
|
||||
}};
|
||||
|
||||
Text text_squelch{
|
||||
{7 * 8, 0 * 16, 8 * 8, 1 * 16},
|
||||
{UI_POS_X(7), UI_POS_Y(0), UI_POS_WIDTH(8), UI_POS_HEIGHT(1)},
|
||||
"SQ /99"};
|
||||
NumberField field_squelch{
|
||||
{10 * 8, 0 * 16},
|
||||
{UI_POS_X(10), UI_POS_Y(0)},
|
||||
2,
|
||||
{0, 99},
|
||||
1,
|
||||
|
|
@ -121,11 +121,11 @@ class WFMOptionsView : public View {
|
|||
|
||||
private:
|
||||
Text label_config{
|
||||
{0 * 8, 0 * 16, 2 * 8, 1 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0), UI_POS_WIDTH(2), UI_POS_HEIGHT(1)},
|
||||
"BW",
|
||||
};
|
||||
OptionsField options_config{
|
||||
{3 * 8, 0 * 16},
|
||||
{UI_POS_X(3), UI_POS_Y(0)},
|
||||
4, // Max option length
|
||||
{
|
||||
// Using common messages from freqman_ui.cpp
|
||||
|
|
@ -138,11 +138,11 @@ class WFMAMAptOptionsView : public View {
|
|||
|
||||
private:
|
||||
Text label_config{
|
||||
{0 * 8, 0 * 16, 2 * 8, 1 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0), UI_POS_WIDTH(2), UI_POS_HEIGHT(1)},
|
||||
"BW",
|
||||
};
|
||||
OptionsField options_config{
|
||||
{3 * 8, 0 * 16},
|
||||
{UI_POS_X(3), UI_POS_Y(0)},
|
||||
16, // Max option char length "80k-NOAA Apt LPF" , example.
|
||||
{
|
||||
// Using common messages from freqman_ui.cpp
|
||||
|
|
@ -155,11 +155,11 @@ class SPECOptionsView : public View {
|
|||
|
||||
private:
|
||||
Text label_config{
|
||||
{0 * 8, 0 * 16, 2 * 8, 1 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0), UI_POS_WIDTH(2), UI_POS_HEIGHT(1)},
|
||||
"BW",
|
||||
};
|
||||
OptionsField options_config{
|
||||
{3 * 8, 0 * 16},
|
||||
{UI_POS_X(3), UI_POS_Y(0)},
|
||||
4,
|
||||
{
|
||||
{"20m ", 20000000},
|
||||
|
|
@ -172,20 +172,20 @@ class SPECOptionsView : public View {
|
|||
}};
|
||||
|
||||
Text text_speed{
|
||||
{9 * 8, 0 * 16, 8 * 8, 1 * 16},
|
||||
{UI_POS_X(9), UI_POS_Y(0), UI_POS_WIDTH(8), UI_POS_HEIGHT(1)},
|
||||
"SP /63"};
|
||||
NumberField field_speed{
|
||||
{12 * 8, 0 * 16},
|
||||
{UI_POS_X(12), UI_POS_Y(0)},
|
||||
2,
|
||||
{0, 63},
|
||||
1,
|
||||
' ',
|
||||
};
|
||||
Text text_rx_cal{
|
||||
{19 * 8, 0 * 16, 11 * 8, 1 * 16}, // 18 (x col.) x char_size, 12 (length) x 8 blanking space to delete previous chars.
|
||||
{UI_POS_X(19), UI_POS_Y(0), UI_POS_WIDTH(11), UI_POS_HEIGHT(1)}, // 18 (x col.) x char_size, 12 (length) x 8 blanking space to delete previous chars.
|
||||
"Rx_IQ_CAL "};
|
||||
NumberField field_rx_iq_phase_cal{
|
||||
{screen_width - 2 * 8, 0 * 16},
|
||||
{screen_width - 2 * 8, UI_POS_Y(0)},
|
||||
2,
|
||||
{0, 63}, // 5 or 6 bits IQ CAL phase adjustment (range updated later)
|
||||
1,
|
||||
|
|
@ -244,34 +244,34 @@ class AnalogAudioView : public View {
|
|||
{"previous_zoom"sv, &previous_zoom}, // we are saving and restoring AMFM ZOOM factor from Settings.
|
||||
}};
|
||||
|
||||
const Rect options_view_rect{0 * 8, 1 * 16, screen_width, 1 * 16};
|
||||
const Rect nbfm_view_rect{0 * 8, 1 * 16, 18 * 8, 1 * 16};
|
||||
const Rect options_view_rect{UI_POS_X(0), UI_POS_Y(1), UI_POS_MAXWIDTH, UI_POS_HEIGHT(1)};
|
||||
const Rect nbfm_view_rect{UI_POS_X(0), UI_POS_Y(1), UI_POS_WIDTH(18), UI_POS_HEIGHT(1)};
|
||||
|
||||
size_t spec_bw_index = 0;
|
||||
uint32_t spec_bw = 20000000;
|
||||
uint16_t spec_trigger = 63;
|
||||
|
||||
RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4}};
|
||||
{UI_POS_X(21), 0, UI_POS_WIDTH_REMAINING(21) - UI_POS_WIDTH(2), 4}};
|
||||
|
||||
Channel channel{
|
||||
{21 * 8, 5, 6 * 8, 4}};
|
||||
{UI_POS_X(21), 5, UI_POS_WIDTH_REMAINING(21) - UI_POS_WIDTH(2), 4}};
|
||||
|
||||
Audio audio{
|
||||
{21 * 8, 10, 6 * 8, 4}};
|
||||
{UI_POS_X(21), 10, UI_POS_WIDTH_REMAINING(21) - UI_POS_WIDTH(2), 4}};
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{5 * 8, 0 * 16},
|
||||
{UI_POS_X(5), UI_POS_Y(0)},
|
||||
nav_};
|
||||
|
||||
LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
{UI_POS_X(15), UI_POS_Y(0)}};
|
||||
|
||||
VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
{UI_POS_X(18), UI_POS_Y(0)}};
|
||||
|
||||
OptionsField options_modulation{
|
||||
{0 * 8, 0 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0)},
|
||||
4,
|
||||
{
|
||||
{" AM ", toUType(ReceiverModel::Mode::AMAudio)},
|
||||
|
|
@ -283,16 +283,16 @@ class AnalogAudioView : public View {
|
|||
}};
|
||||
|
||||
AudioVolumeField field_volume{
|
||||
{screen_width - 2 * 8, 0 * 16}};
|
||||
{screen_width - 2 * 8, UI_POS_Y(0)}};
|
||||
|
||||
Text text_ctcss{
|
||||
{16 * 8, 1 * 16, 14 * 8, 1 * 16},
|
||||
{UI_POS_X(16), UI_POS_Y(1), UI_POS_WIDTH(14), UI_POS_HEIGHT(1)},
|
||||
""};
|
||||
|
||||
std::unique_ptr<Widget> options_widget{};
|
||||
|
||||
RecordView record_view{
|
||||
{0 * 8, 2 * 16, screen_width, 1 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(2), UI_POS_MAXWIDTH, UI_POS_HEIGHT(1)},
|
||||
u"AUD",
|
||||
u"AUDIO",
|
||||
RecordView::FileType::WAV,
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ class BLECommView : public View {
|
|||
static constexpr auto header_height = 5 * 16;
|
||||
|
||||
OptionsField options_channel{
|
||||
{0 * 8, 0 * 8},
|
||||
{UI_POS_X(0), 0 * 8},
|
||||
5,
|
||||
{{"Ch.37 ", 37},
|
||||
{"Ch.38", 38},
|
||||
|
|
@ -139,17 +139,17 @@ class BLECommView : public View {
|
|||
{"Auto", 40}}};
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{6 * 8, 0 * 16},
|
||||
{6 * 8, UI_POS_Y(0)},
|
||||
nav_};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{16 * 8, 0 * 16}};
|
||||
{16 * 8, UI_POS_Y(0)}};
|
||||
|
||||
LNAGainField field_lna{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
|
||||
VGAGainField field_vga{
|
||||
{21 * 8, 0 * 16}};
|
||||
{21 * 8, UI_POS_Y(0)}};
|
||||
|
||||
RSSI rssi{
|
||||
{24 * 8, 0, 6 * 8, 4}};
|
||||
|
|
@ -164,7 +164,7 @@ class BLECommView : public View {
|
|||
true};
|
||||
|
||||
Labels label_packets_sent{
|
||||
{{0 * 8, 4 * 8}, "Packets Left:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 4 * 8}, "Packets Left:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Text text_packets_sent{
|
||||
{13 * 8, 2 * 16, 12 * 8, 16},
|
||||
|
|
|
|||
|
|
@ -181,21 +181,16 @@ void RecentEntriesTable<BleRecentEntries>::draw(
|
|||
const Entry& entry,
|
||||
const Rect& target_rect,
|
||||
Painter& painter,
|
||||
const Style& style) {
|
||||
const Style& style,
|
||||
RecentEntriesColumns& columns) {
|
||||
std::string line{};
|
||||
line.reserve(30);
|
||||
|
||||
line.reserve(40);
|
||||
if (!entry.nameString.empty() && entry.include_name) {
|
||||
line = entry.nameString;
|
||||
|
||||
if (line.length() < 17) {
|
||||
line += pad_string_with_spaces(17 - line.length());
|
||||
} else {
|
||||
line = truncate(line, 17);
|
||||
}
|
||||
} else {
|
||||
line = to_string_mac_address(entry.packetData.macAddress, 6, false);
|
||||
}
|
||||
line.resize(columns.at(0).second, ' ');
|
||||
|
||||
std::string hitsStr;
|
||||
|
||||
|
|
|
|||
|
|
@ -155,42 +155,42 @@ class BleRecentEntryDetailView : public View {
|
|||
static constexpr uint8_t total_data_lines{5};
|
||||
|
||||
Labels label_mac_address{
|
||||
{{0 * 8, 0 * 16}, "Mac Address:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), UI_POS_Y(0)}, "Mac Address:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Text text_mac_address{
|
||||
{12 * 8, 0 * 16, 17 * 8, 16},
|
||||
{UI_POS_X(12), UI_POS_Y(0), UI_POS_WIDTH(17), UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Labels label_pdu_type{
|
||||
{{0 * 8, 1 * 16}, "PDU Type:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), UI_POS_Y(1)}, "PDU Type:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Text text_pdu_type{
|
||||
{9 * 8, 1 * 16, 17 * 8, 16},
|
||||
{9 * 8, UI_POS_Y(1), 17 * 8, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Labels label_vendor{
|
||||
{{0 * 8, 2 * 16}, "Vendor:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), UI_POS_Y(2)}, "Vendor:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Text text_vendor{
|
||||
{7 * 8, 2 * 16, 23 * 8, 16},
|
||||
{7 * 8, UI_POS_Y(2), 23 * 8, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 3 * 16}, "Len", Theme::getInstance()->fg_light->foreground},
|
||||
{{5 * 8, 3 * 16}, "Type", Theme::getInstance()->fg_light->foreground},
|
||||
{{10 * 8, 3 * 16}, "Value", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), UI_POS_Y(3)}, "Len", Theme::getInstance()->fg_light->foreground},
|
||||
{{5 * 8, UI_POS_Y(3)}, "Type", Theme::getInstance()->fg_light->foreground},
|
||||
{{10 * 8, UI_POS_Y(3)}, "Value", Theme::getInstance()->fg_light->foreground},
|
||||
};
|
||||
|
||||
Button button_send{
|
||||
{19, 224, 96, 24},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), 224, 96, 24},
|
||||
"Send"};
|
||||
|
||||
Button button_done{
|
||||
{125, 224, 96, 24},
|
||||
{UI_POS_X_CENTER(12) + UI_POS_WIDTH(8), 224, 96, 24},
|
||||
"Done"};
|
||||
|
||||
Button button_save{
|
||||
{72, 264, 96, 24},
|
||||
{UI_POS_X_CENTER(12), 264, 96, 24},
|
||||
"Save"};
|
||||
|
||||
bool send_updates{false};
|
||||
|
|
@ -294,7 +294,7 @@ class BLERxView : public View {
|
|||
static constexpr auto switch_button_height = 3 * 16;
|
||||
|
||||
OptionsField options_channel{
|
||||
{0 * 8, 0 * 8},
|
||||
{UI_POS_X(0), UI_POS_Y(0)},
|
||||
5,
|
||||
{{"Ch.37", 37},
|
||||
{"Ch.38", 38},
|
||||
|
|
@ -302,29 +302,29 @@ class BLERxView : public View {
|
|||
{"Auto", 40}}};
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{6 * 8, 0 * 16},
|
||||
{UI_POS_X(6), UI_POS_Y(0)},
|
||||
nav_};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{16 * 8, 0 * 16}};
|
||||
{UI_POS_X(16), UI_POS_Y(0)}};
|
||||
|
||||
LNAGainField field_lna{
|
||||
{18 * 8, 0 * 16}};
|
||||
{UI_POS_X(18), UI_POS_Y(0)}};
|
||||
|
||||
VGAGainField field_vga{
|
||||
{21 * 8, 0 * 16}};
|
||||
{UI_POS_X(21), UI_POS_Y(0)}};
|
||||
|
||||
RSSI rssi{
|
||||
{24 * 8, 0, 6 * 8, 4}};
|
||||
{UI_POS_X(24), 0, UI_POS_WIDTH_REMAINING(6), 4}};
|
||||
|
||||
Channel channel{
|
||||
{24 * 8, 5, 6 * 8, 4}};
|
||||
{UI_POS_X(24), 5, UI_POS_WIDTH_REMAINING(6), 4}};
|
||||
|
||||
Labels label_sort{
|
||||
{{0 * 8, 2 * 8}, "Sort:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), UI_POS_Y(1)}, "Sort:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
OptionsField options_sort{
|
||||
{5 * 8, 2 * 8},
|
||||
{5 * 8, UI_POS_Y(1)},
|
||||
4,
|
||||
{{"MAC", 0},
|
||||
{"Hits", 1},
|
||||
|
|
@ -334,11 +334,11 @@ class BLERxView : public View {
|
|||
{"Info", 5}}};
|
||||
|
||||
Button button_filter{
|
||||
{11 * 8, 2 * 8, 7 * 8, 16},
|
||||
{11 * 8, UI_POS_Y(1), 7 * 8, 16},
|
||||
"Filter:"};
|
||||
|
||||
OptionsField options_filter{
|
||||
{18 * 8 + 2, 2 * 8},
|
||||
{18 * 8 + 2, UI_POS_Y(1)},
|
||||
7,
|
||||
{{"Data", 0},
|
||||
{"MAC", 1},
|
||||
|
|
@ -354,7 +354,7 @@ class BLERxView : public View {
|
|||
true};
|
||||
|
||||
Checkbox check_name{
|
||||
{0 * 8, 4 * 8 + 2},
|
||||
{UI_POS_X(0), 4 * 8 + 2},
|
||||
3,
|
||||
"Name",
|
||||
true};
|
||||
|
|
@ -378,7 +378,7 @@ class BLERxView : public View {
|
|||
true};
|
||||
|
||||
Button button_find{
|
||||
{0 * 8, 10 * 8 - 2, 4 * 8, 16},
|
||||
{UI_POS_X(0), 10 * 8 - 2, 4 * 8, 16},
|
||||
"Find"};
|
||||
|
||||
Labels label_found{
|
||||
|
|
@ -389,15 +389,15 @@ class BLERxView : public View {
|
|||
"0/0"};
|
||||
|
||||
Button button_clear_list{
|
||||
{2 * 8, 320 - (16 + 32), 7 * 8, 32},
|
||||
{2 * 8, screen_height - (16 + 32), 7 * 8, 32},
|
||||
"Clear"};
|
||||
|
||||
Button button_save_list{
|
||||
{11 * 8, 320 - (16 + 32), 11 * 8, 32},
|
||||
{UI_POS_X_CENTER(11), screen_height - (16 + 32), 11 * 8, 32},
|
||||
"Export CSV"};
|
||||
|
||||
Button button_switch{
|
||||
{240 - 6 * 8, 320 - (16 + 32), 4 * 8, 32},
|
||||
{UI_POS_X_RIGHT(6), screen_height - (16 + 32), 4 * 8, 32},
|
||||
"Tx"};
|
||||
|
||||
std::string str_log{""};
|
||||
|
|
@ -407,7 +407,7 @@ class BLERxView : public View {
|
|||
BleRecentEntries tempList{};
|
||||
|
||||
RecentEntriesColumns columns{{
|
||||
{"Name", 17},
|
||||
{"Name", 0},
|
||||
{"Hits", 7},
|
||||
{"dBm", 4},
|
||||
}};
|
||||
|
|
|
|||
|
|
@ -190,24 +190,24 @@ class BLETxView : public View {
|
|||
static constexpr auto switch_button_height = 6 * 16;
|
||||
|
||||
Button button_open{
|
||||
{0 * 8, 0 * 16, 10 * 8, 2 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0), 10 * 8, 2 * 16},
|
||||
"Open file"};
|
||||
|
||||
Text text_filename{
|
||||
{11 * 8, 0 * 16, 12 * 8, 16},
|
||||
{11 * 8, UI_POS_Y(0), UI_POS_WIDTH_REMAINING(11), 16},
|
||||
"-"};
|
||||
|
||||
ProgressBar progressbar{
|
||||
{11 * 8, 1 * 16, 9 * 8, 16}};
|
||||
{11 * 8, 1 * 16, UI_POS_WIDTH_REMAINING(11 + 10), 16}};
|
||||
|
||||
Checkbox check_rand_mac{
|
||||
{21 * 8, 1 * 16},
|
||||
{UI_POS_X_RIGHT(9), 1 * 16},
|
||||
6,
|
||||
"?? Mac",
|
||||
true};
|
||||
|
||||
TxFrequencyField field_frequency{
|
||||
{0 * 8, 2 * 16},
|
||||
{UI_POS_X(0), 2 * 16},
|
||||
nav_};
|
||||
|
||||
TransmitterView2 tx_view{
|
||||
|
|
@ -215,19 +215,19 @@ class BLETxView : public View {
|
|||
/*short_ui*/ true};
|
||||
|
||||
Checkbox check_loop{
|
||||
{21 * 8, 2 * 16},
|
||||
{UI_POS_X_RIGHT(9), 2 * 16},
|
||||
4,
|
||||
"Loop",
|
||||
true};
|
||||
|
||||
ImageButton button_play{
|
||||
{28 * 8, 2 * 16, 2 * 8, 1 * 16},
|
||||
{UI_POS_X_RIGHT(2), 2 * 16, 2 * 8, 1 * 16},
|
||||
&bitmap_play,
|
||||
Theme::getInstance()->fg_green->foreground,
|
||||
Theme::getInstance()->fg_green->background};
|
||||
|
||||
Labels label_speed{
|
||||
{{0 * 8, 6 * 8}, "Speed:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 6 * 8}, "Speed:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
OptionsField options_speed{
|
||||
{7 * 8, 6 * 8},
|
||||
|
|
@ -259,7 +259,7 @@ class BLETxView : public View {
|
|||
{"CONNECT_REQ", PKT_TYPE_CONNECT_REQ}}};
|
||||
|
||||
Labels label_marked_data{
|
||||
{{0 * 8, 4 * 16}, "Marked Data:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 4 * 16}, "Marked Data:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
OptionsField marked_data_sequence{
|
||||
{12 * 8, 8 * 8},
|
||||
|
|
@ -269,42 +269,42 @@ class BLETxView : public View {
|
|||
{"Random", 2}}};
|
||||
|
||||
Labels label_packet_index{
|
||||
{{0 * 8, 12 * 8}, "Packet Index:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 12 * 8}, "Packet Index:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Text text_packet_index{
|
||||
{13 * 8, 6 * 16, 12 * 8, 16},
|
||||
"-"};
|
||||
|
||||
Labels label_packets_sent{
|
||||
{{0 * 8, 14 * 8}, "Repeat Count:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 14 * 8}, "Repeat Count:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Text text_packets_sent{
|
||||
{13 * 8, 7 * 16, 12 * 8, 16},
|
||||
"-"};
|
||||
|
||||
Labels label_mac_address{
|
||||
{{0 * 8, 16 * 8}, "Mac Address:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 16 * 8}, "Mac Address:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Text text_mac_address{
|
||||
{12 * 8, 8 * 16, 20 * 8, 16},
|
||||
"-"};
|
||||
|
||||
Labels label_data_packet{
|
||||
{{0 * 8, 9 * 16}, "Packet Data:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 9 * 16}, "Packet Data:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
TextViewer dataEditView{
|
||||
{0, 9 * 18, 240, 240}};
|
||||
|
||||
Button button_clear_marked{
|
||||
{1 * 8, 14 * 16, 13 * 8, 3 * 8},
|
||||
{UI_POS_X(1), UI_POS_Y_BOTTOM(5), UI_POS_WIDTH(13), UI_POS_HEIGHT(1.5)},
|
||||
"Clear Marked"};
|
||||
|
||||
Button button_save_packet{
|
||||
{1 * 8, 16 * 16, 13 * 8, 2 * 16},
|
||||
{UI_POS_X(1), UI_POS_Y_BOTTOM(3), UI_POS_WIDTH(13), UI_POS_HEIGHT(2)},
|
||||
"Save Packet"};
|
||||
|
||||
Button button_switch{
|
||||
{16 * 8, 16 * 16, 13 * 8, 2 * 16},
|
||||
{UI_POS_X_RIGHT(14), UI_POS_Y_BOTTOM(3), UI_POS_WIDTH(13), UI_POS_HEIGHT(2)},
|
||||
"Switch to Rx"};
|
||||
|
||||
std::string str_log{""};
|
||||
|
|
|
|||
|
|
@ -65,31 +65,31 @@ class CaptureAppView : public View {
|
|||
}};
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 1 * 16}, "Rate:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 1 * 16}, "Rate:", Theme::getInstance()->fg_light->foreground},
|
||||
{{11 * 8, 1 * 16}, "Format:", Theme::getInstance()->fg_light->foreground},
|
||||
};
|
||||
|
||||
RSSI rssi{
|
||||
{24 * 8, 0, 6 * 8, 4}};
|
||||
{UI_POS_X(24), 0, UI_POS_WIDTH_REMAINING(24), 4}};
|
||||
|
||||
Channel channel{
|
||||
{24 * 8, 5, 6 * 8, 4}};
|
||||
{UI_POS_X(24), 5, UI_POS_WIDTH_REMAINING(24), 4}};
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{0 * 8, 0 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0)},
|
||||
nav_};
|
||||
|
||||
FrequencyStepView field_frequency_step{
|
||||
{10 * 8, 0 * 16}};
|
||||
{10 * 8, UI_POS_Y(0)}};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{16 * 8, 0 * 16}};
|
||||
{16 * 8, UI_POS_Y(0)}};
|
||||
|
||||
LNAGainField field_lna{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
|
||||
VGAGainField field_vga{
|
||||
{21 * 8, 0 * 16}};
|
||||
{21 * 8, UI_POS_Y(0)}};
|
||||
|
||||
OptionsField option_bandwidth{
|
||||
{5 * 8, 1 * 16},
|
||||
|
|
@ -109,7 +109,7 @@ class CaptureAppView : public View {
|
|||
/*small*/ true};
|
||||
|
||||
RecordView record_view{
|
||||
{0 * 8, 2 * 16, screen_width, 1 * 16},
|
||||
{UI_POS_X(0), 2 * 16, screen_width, 1 * 16},
|
||||
u"BBD_????.*",
|
||||
captures_dir,
|
||||
RecordView::FileType::RawS16,
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ class POCSAGSettingsView : public View {
|
|||
true /*explicit_edit*/};
|
||||
|
||||
Button button_save{
|
||||
{11 * 8, 16 * 16, 10 * 8, 2 * 16},
|
||||
{UI_POS_X_CENTER(10), UI_POS_Y(16), 10 * 8, 2 * 16},
|
||||
"Save"};
|
||||
};
|
||||
|
||||
|
|
@ -236,30 +236,30 @@ class POCSAGAppView : public View {
|
|||
uint16_t packet_count = 0;
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{0 * 8, 0 * 8},
|
||||
{UI_POS_X(0), 0 * 8},
|
||||
nav_};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{11 * 8, 0 * 16}};
|
||||
{11 * 8, UI_POS_Y(0)}};
|
||||
LNAGainField field_lna{
|
||||
{13 * 8, 0 * 16}};
|
||||
{13 * 8, UI_POS_Y(0)}};
|
||||
VGAGainField field_vga{
|
||||
{16 * 8, 0 * 16}};
|
||||
{16 * 8, UI_POS_Y(0)}};
|
||||
|
||||
RSSI rssi{
|
||||
{19 * 8 - 4, 3, 6 * 8, 4}};
|
||||
{19 * 8 - 4, 3, UI_POS_WIDTH_REMAINING(26), 4}};
|
||||
Audio audio{
|
||||
{19 * 8 - 4, 8, 6 * 8, 4}};
|
||||
{19 * 8 - 4, 8, UI_POS_WIDTH_REMAINING(26), 4}};
|
||||
|
||||
NumberField field_squelch{
|
||||
{25 * 8, 0 * 16},
|
||||
{UI_POS_X_RIGHT(6), UI_POS_Y(0)},
|
||||
2,
|
||||
{0, 99},
|
||||
1,
|
||||
' ',
|
||||
true /*wrap*/};
|
||||
AudioVolumeField field_volume{
|
||||
{screen_width - 2 * 8, 0 * 16}};
|
||||
{UI_POS_X_RIGHT(2), UI_POS_Y(0)}};
|
||||
|
||||
Image image_status{
|
||||
{0 * 8 + 4, 1 * 16 + 2, 16, 16},
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ void RecentEntriesTable<AircraftRecentEntries>::draw(
|
|||
const Entry& entry,
|
||||
const Rect& target_rect,
|
||||
Painter& painter,
|
||||
const Style& style) {
|
||||
const Style& style,
|
||||
RecentEntriesColumns& columns) {
|
||||
Color target_color;
|
||||
std::string entry_string;
|
||||
|
||||
|
|
@ -70,9 +71,11 @@ void RecentEntriesTable<AircraftRecentEntries>::draw(
|
|||
target_color = Theme::getInstance()->fg_medium->foreground;
|
||||
};
|
||||
|
||||
entry_string +=
|
||||
(entry.callsign.empty() ? entry.icao_str + " " : entry.callsign + " ") +
|
||||
to_string_dec_uint((unsigned int)(entry.pos.altitude / 100), 4);
|
||||
std::string ipc = (entry.callsign.empty() ? entry.icao_str + " " : entry.callsign + " ");
|
||||
uint8_t firstcolwidth = columns.at(0).second;
|
||||
ipc.resize(firstcolwidth, ' '); // Make sure this is always match the first column's width that is dynamic.
|
||||
|
||||
entry_string += ipc + to_string_dec_uint((unsigned int)(entry.pos.altitude / 100), 4);
|
||||
|
||||
if (entry.velo.type == SPD_IAS && entry.pos.alt_valid) { // IAS can be converted to TAS
|
||||
// It is generally accepted that for every thousand feet of altitude,
|
||||
|
|
@ -100,7 +103,7 @@ void RecentEntriesTable<AircraftRecentEntries>::draw(
|
|||
entry_string);
|
||||
|
||||
if (entry.pos.pos_valid)
|
||||
painter.draw_bitmap(target_rect.location() + Point(8 * 8, 0),
|
||||
painter.draw_bitmap(target_rect.location() + Point(firstcolwidth * 8 - 8, 0),
|
||||
bitmap_target, target_color, style.background);
|
||||
}
|
||||
|
||||
|
|
@ -409,7 +412,7 @@ ADSBRxView::ADSBRxView(NavigationView& nav) {
|
|||
&status_good_frame,
|
||||
&field_volume});
|
||||
|
||||
recent_entries_view.set_parent_rect({0, 16, screen_width, 272});
|
||||
recent_entries_view.set_parent_rect({0, 16, screen_width, UI_POS_HEIGHT_REMAINING(2)});
|
||||
recent_entries_view.on_select = [this, &nav](const AircraftRecentEntry& entry) {
|
||||
detail_key = entry.key();
|
||||
details_view = nav.push<ADSBRxDetailsView>(entry);
|
||||
|
|
|
|||
|
|
@ -208,54 +208,54 @@ class ADSBRxAircraftDetailsView : public View {
|
|||
|
||||
private:
|
||||
Labels labels{
|
||||
{{0 * 8, 1 * 16}, "ICAO:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 2 * 16}, "Registration:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 3 * 16}, "Manufacturer:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 5 * 16}, "Model:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 7 * 16}, "Type:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 8 * 16}, "Number of engines:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 9 * 16}, "Engine type:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 11 * 16}, "Owner:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 13 * 16}, "Operator:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 1 * 16}, "ICAO:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 2 * 16}, "Registration:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 3 * 16}, "Manufacturer:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 5 * 16}, "Model:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 7 * 16}, "Type:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 8 * 16}, "Number of engines:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 9 * 16}, "Engine type:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 11 * 16}, "Owner:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 13 * 16}, "Operator:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Text text_icao_address{
|
||||
{5 * 8, 1 * 16, 6 * 8, 16},
|
||||
{5 * 8, 1 * 16, 6 * 8, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Text text_registration{
|
||||
{13 * 8, 2 * 16, 8 * 8, 16},
|
||||
{13 * 8, 2 * 16, 8 * 8, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Text text_manufacturer{
|
||||
{0 * 8, 4 * 16, 19 * 8, 16},
|
||||
{UI_POS_X(0), 4 * 16, 19 * 8, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Text text_model{
|
||||
{0 * 8, 6 * 16, screen_width, 16},
|
||||
{UI_POS_X(0), 6 * 16, screen_width, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Text text_type{
|
||||
{5 * 8, 7 * 16, 22 * 8, 16},
|
||||
{5 * 8, 7 * 16, 22 * 8, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Text text_number_of_engines{
|
||||
{18 * 8, 8 * 16, screen_width, 16},
|
||||
{18 * 8, 8 * 16, screen_width, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Text text_engine_type{
|
||||
{0 * 8, 10 * 16, screen_width, 16},
|
||||
{UI_POS_X(0), 10 * 16, screen_width, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Text text_owner{
|
||||
{0 * 8, 12 * 16, screen_width, 16},
|
||||
{UI_POS_X(0), 12 * 16, screen_width, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Text text_operator{
|
||||
{0 * 8, 14 * 16, screen_width, 16},
|
||||
{UI_POS_X(0), 14 * 16, screen_width, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Button button_close{
|
||||
{9 * 8, 16 * 16, 12 * 8, 3 * 16},
|
||||
{UI_POS_X_CENTER(12), UI_POS_Y(16), UI_POS_WIDTH(12), UI_POS_HEIGHT(3)},
|
||||
"Back"};
|
||||
};
|
||||
|
||||
|
|
@ -299,55 +299,55 @@ class ADSBRxDetailsView : public View {
|
|||
bool airline_checked{false};
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 1 * 16}, "ICAO:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 1 * 16}, "ICAO:", Theme::getInstance()->fg_light->foreground},
|
||||
{{13 * 8, 1 * 16}, "Callsign:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 2 * 16}, "Last seen:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 3 * 16}, "Airline:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 5 * 16}, "Country:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 13 * 16}, "Even position frame:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 15 * 16}, "Odd position frame:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 2 * 16}, "Last seen:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 3 * 16}, "Airline:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 5 * 16}, "Country:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 13 * 16}, "Even position frame:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 15 * 16}, "Odd position frame:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Text text_icao_address{
|
||||
{5 * 8, 1 * 16, 6 * 8, 16},
|
||||
{5 * 8, 1 * 16, 6 * 8, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Text text_callsign{
|
||||
{22 * 8, 1 * 16, 8 * 8, 16},
|
||||
{22 * 8, 1 * 16, 8 * 8, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Text text_last_seen{
|
||||
{11 * 8, 2 * 16, 19 * 8, 16},
|
||||
{11 * 8, 2 * 16, 19 * 8, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Text text_airline{
|
||||
{0 * 8, 4 * 16, screen_width, 16},
|
||||
{UI_POS_X(0), 4 * 16, screen_width, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Text text_country{
|
||||
{8 * 8, 5 * 16, 22 * 8, 16},
|
||||
{8 * 8, 5 * 16, 22 * 8, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Text text_infos{
|
||||
{0 * 8, 6 * 16, screen_width, 16},
|
||||
{UI_POS_X(0), 6 * 16, screen_width, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Text text_info2{
|
||||
{0 * 8, 7 * 16, screen_width, 16},
|
||||
{UI_POS_X(0), 7 * 16, screen_width, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Text text_frame_pos_even{
|
||||
{0 * 8, 14 * 16, screen_width, 16},
|
||||
{UI_POS_X(0), 14 * 16, screen_width, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
Text text_frame_pos_odd{
|
||||
{0 * 8, 16 * 16, screen_width, 16},
|
||||
{UI_POS_X(0), 16 * 16, screen_width, UI_POS_HEIGHT(1)},
|
||||
"-"};
|
||||
|
||||
Button button_aircraft_details{
|
||||
{2 * 8, 9 * 16, 12 * 8, 3 * 16},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_X(8), UI_POS_Y(9), UI_POS_WIDTH(12), UI_POS_HEIGHT(3)},
|
||||
"A/C details"};
|
||||
|
||||
Button button_see_map{
|
||||
{16 * 8, 9 * 16, 12 * 8, 3 * 16},
|
||||
{UI_POS_X_CENTER(12) + UI_POS_X(8), UI_POS_Y(9), UI_POS_WIDTH(12), UI_POS_HEIGHT(3)},
|
||||
"See on map"};
|
||||
|
||||
MessageHandlerRegistration message_handler_gps{
|
||||
|
|
@ -403,8 +403,8 @@ class ADSBRxView : public View {
|
|||
static constexpr uint8_t max_update_entries = 16;
|
||||
|
||||
/* Recent Entries */
|
||||
const RecentEntriesColumns columns{
|
||||
{{"ICAO/Call", 9},
|
||||
RecentEntriesColumns columns{
|
||||
{{"ICAO/Call", 0},
|
||||
{"Lvl", 3},
|
||||
{"Spd", 3},
|
||||
{"Amp", 3},
|
||||
|
|
@ -424,33 +424,33 @@ class ADSBRxView : public View {
|
|||
ADSBRxDetailsView* details_view{nullptr};
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 0 * 8}, "LNA: VGA: AMP:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), UI_POS_Y(0)}, "LNA: VGA: AMP:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
LNAGainField field_lna{
|
||||
{4 * 8, 0 * 16}};
|
||||
{UI_POS_X(4), UI_POS_Y(0)}};
|
||||
|
||||
VGAGainField field_vga{
|
||||
{11 * 8, 0 * 16}};
|
||||
{UI_POS_X(11), UI_POS_Y(0)}};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{18 * 8, 0 * 16}};
|
||||
{UI_POS_X(18), UI_POS_Y(0)}};
|
||||
|
||||
RSSI rssi{
|
||||
{20 * 8, 4, 7 * 8, 8},
|
||||
{UI_POS_X(20), 4, UI_POS_WIDTH_REMAINING(23), 8},
|
||||
};
|
||||
|
||||
ActivityDot status_frame{
|
||||
{27 * 8 + 2, 5, 2, 2},
|
||||
{UI_POS_X_RIGHT(3) + 2, 5, 2, 2},
|
||||
Theme::getInstance()->bg_darkest->foreground,
|
||||
};
|
||||
|
||||
ActivityDot status_good_frame{
|
||||
{27 * 8 + 2, 9, 2, 2},
|
||||
{UI_POS_X_RIGHT(3) + 2, 9, 2, 2},
|
||||
Theme::getInstance()->fg_green->foreground,
|
||||
};
|
||||
|
||||
AudioVolumeField field_volume{
|
||||
{screen_width - 2 * 8, 0 * 16}};
|
||||
{UI_POS_X_RIGHT(2), UI_POS_Y(0)}};
|
||||
|
||||
MessageHandlerRegistration message_handler_frame{
|
||||
Message::ID::ADSBFrame,
|
||||
|
|
|
|||
|
|
@ -42,7 +42,8 @@ void RecentEntriesTable<APRSRecentEntries>::draw(
|
|||
const Entry& entry,
|
||||
const Rect& target_rect,
|
||||
Painter& painter,
|
||||
const Style& style) {
|
||||
const Style& style,
|
||||
RecentEntriesColumns& columns) {
|
||||
Color target_color;
|
||||
// auto entry_age = entry.age;
|
||||
|
||||
|
|
@ -51,8 +52,8 @@ void RecentEntriesTable<APRSRecentEntries>::draw(
|
|||
std::string entry_string = "";
|
||||
|
||||
entry_string += entry.source_formatted;
|
||||
entry_string.append(10 - entry.source_formatted.size(), ' ');
|
||||
entry_string += " ";
|
||||
entry_string.resize(columns.at(0).second, ' ');
|
||||
entry_string += " ";
|
||||
entry_string += (entry.hits <= 999 ? to_string_dec_uint(entry.hits, 4) : "999+");
|
||||
entry_string += " ";
|
||||
entry_string += entry.time_string;
|
||||
|
|
|
|||
|
|
@ -134,14 +134,14 @@ class APRSDetailsView : public View {
|
|||
bool send_updates{false};
|
||||
|
||||
Console console{
|
||||
{0, 0 * 16, screen_width, 224}};
|
||||
{UI_POS_X(0), UI_POS_Y(0), screen_width, screen_height - 80}};
|
||||
|
||||
Button button_done{
|
||||
{160, 14 * 16, 8 * 8, 3 * 16},
|
||||
{UI_POS_X_CENTER(4) - UI_POS_WIDTH(8), UI_POS_Y(14), UI_POS_WIDTH(8), UI_POS_HEIGHT(3)},
|
||||
"Close"};
|
||||
|
||||
Button button_see_map{
|
||||
{80, 14 * 16, 8 * 8, 3 * 16},
|
||||
{UI_POS_X_CENTER(4) + UI_POS_WIDTH(8), UI_POS_Y(14), UI_POS_WIDTH(8), UI_POS_HEIGHT(3)},
|
||||
"Map"};
|
||||
};
|
||||
|
||||
|
|
@ -161,10 +161,10 @@ class APRSTableView : public View {
|
|||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
const RecentEntriesColumns columns{{{"Source", 9},
|
||||
{"Loc", 6},
|
||||
{"Hits", 4},
|
||||
{"Time", 8}}};
|
||||
RecentEntriesColumns columns{{{"Source", 0},
|
||||
{"Loc", 6},
|
||||
{"Hits", 4},
|
||||
{"Time", 8}}};
|
||||
APRSRecentEntries recent{};
|
||||
RecentEntriesView<RecentEntries<APRSRecentEntry>> recent_entries_view{columns, recent};
|
||||
APRSDetailsView details_view{nav_};
|
||||
|
|
@ -209,21 +209,21 @@ class APRSRxView : public View {
|
|||
std::string str_log{""};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{13 * 8, 0 * 16}};
|
||||
{UI_POS_X(13), UI_POS_Y(0)}};
|
||||
LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
{UI_POS_X(15), UI_POS_Y(0)}};
|
||||
VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
{UI_POS_X(18), UI_POS_Y(0)}};
|
||||
RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4}};
|
||||
{UI_POS_X(21), 0, UI_POS_WIDTH_REMAINING(21) - UI_POS_WIDTH(2), 4}};
|
||||
Channel channel{
|
||||
{21 * 8, 5, 6 * 8, 4}};
|
||||
{UI_POS_X(21), 5, UI_POS_WIDTH_REMAINING(21) - UI_POS_WIDTH(2), 4}};
|
||||
|
||||
AudioVolumeField field_volume{
|
||||
{screen_width - 2 * 8, 0 * 16}};
|
||||
{UI_POS_X_RIGHT(2), UI_POS_Y(0)}};
|
||||
|
||||
OptionsField options_region{
|
||||
{0 * 8, 0 * 8},
|
||||
{UI_POS_X(0), UI_POS_Y(0)},
|
||||
3,
|
||||
{{"MAN", 0},
|
||||
{"NA ", 1},
|
||||
|
|
@ -237,11 +237,11 @@ class APRSRxView : public View {
|
|||
{"ISS", 9}}};
|
||||
|
||||
FrequencyField field_frequency{
|
||||
{3 * 8, 0 * 16}};
|
||||
{UI_POS_X(3), UI_POS_Y(0)}};
|
||||
|
||||
// DEBUG
|
||||
RecordView record_view{
|
||||
{0 * 8, 1 * 16, screen_width, 1 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(1), UI_POS_MAXWIDTH, UI_POS_HEIGHT(1)},
|
||||
u"AFS_????.WAV",
|
||||
aprs_dir,
|
||||
RecordView::FileType::WAV,
|
||||
|
|
@ -249,7 +249,7 @@ class APRSRxView : public View {
|
|||
4};
|
||||
|
||||
Console console{
|
||||
{0, 2 * 16, screen_width, screen_height - 80}};
|
||||
{UI_POS_X(0), UI_POS_Y(2), UI_POS_MAXWIDTH, screen_height - 80}};
|
||||
|
||||
std::unique_ptr<APRSLogger> logger{};
|
||||
};
|
||||
|
|
@ -265,7 +265,7 @@ class APRSRXView : public View {
|
|||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
Rect view_rect = {0, 3 * 8, screen_width, screen_height - 40};
|
||||
Rect view_rect = {UI_POS_X(0), 3 * 8, UI_POS_MAXWIDTH, screen_height - 40};
|
||||
|
||||
APRSRxView view_stream{nav_, view_rect};
|
||||
APRSTableView view_table{nav_, view_rect};
|
||||
|
|
|
|||
|
|
@ -61,9 +61,9 @@ class APRSTXView : public View {
|
|||
void on_tx_progress(const uint32_t progress, const bool done);
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 1 * 16}, "Source: SSID:", Theme::getInstance()->fg_light->foreground}, // 6 alphanum + SSID
|
||||
{{0 * 8, 2 * 16}, " Dest.: SSID:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 4 * 16}, "Info field:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 1 * 16}, "Source: SSID:", Theme::getInstance()->fg_light->foreground}, // 6 alphanum + SSID
|
||||
{{UI_POS_X(0), 2 * 16}, " Dest.: SSID:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 4 * 16}, "Info field:", Theme::getInstance()->fg_light->foreground},
|
||||
};
|
||||
|
||||
SymField sym_source{
|
||||
|
|
@ -91,14 +91,14 @@ class APRSTXView : public View {
|
|||
' '};
|
||||
|
||||
Text text_payload{
|
||||
{0 * 8, 5 * 16, screen_width, 16},
|
||||
{UI_POS_X(0), 5 * 16, screen_width, 16},
|
||||
"-"};
|
||||
Button button_set{
|
||||
{0 * 8, 6 * 16, 80, 32},
|
||||
{UI_POS_X(0), 6 * 16, 80, 32},
|
||||
"Set"};
|
||||
|
||||
TransmitterView tx_view{
|
||||
16 * 16,
|
||||
(int16_t)UI_POS_Y_BOTTOM(4),
|
||||
5000,
|
||||
0 // disable setting bandwith, since APRS used fixed 10k bandwidth
|
||||
};
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ class BattinfoView : public View {
|
|||
"Volt"};
|
||||
|
||||
Button button_exit{
|
||||
{72, 17 * 16, 96, 32},
|
||||
{UI_POS_X_CENTER(12), 17 * 16, UI_POS_WIDTH(12), UI_POS_HEIGHT(3)},
|
||||
"Back"};
|
||||
static msg_t static_fn(void* arg);
|
||||
Thread* thread{nullptr};
|
||||
|
|
|
|||
|
|
@ -63,22 +63,22 @@ class BTLERxView : public View {
|
|||
static constexpr uint8_t channel_number = 37;
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{13 * 8, 0 * 16}};
|
||||
{UI_POS_X(13), UI_POS_Y(0)}};
|
||||
LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
{UI_POS_X(15), UI_POS_Y(0)}};
|
||||
VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
{UI_POS_X(18), UI_POS_Y(0)}};
|
||||
RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4}};
|
||||
{UI_POS_X(21), UI_POS_Y(0), UI_POS_WIDTH_REMAINING(21), 4}};
|
||||
Channel channel{
|
||||
{21 * 8, 5, 6 * 8, 4}};
|
||||
{UI_POS_X(21), 5, UI_POS_WIDTH_REMAINING(21), 4}};
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{0 * 8, 0 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0)},
|
||||
nav_};
|
||||
|
||||
Button button_modem_setup{
|
||||
{screen_width - 12 * 8, 1 * 16, 96, 24},
|
||||
{screen_width - 12 * 8, UI_POS_Y(1), 96, 24},
|
||||
"Modem setup"};
|
||||
|
||||
Console console{
|
||||
|
|
|
|||
|
|
@ -242,9 +242,9 @@ class DebugControlsView : public View {
|
|||
|
||||
private:
|
||||
Labels labels{
|
||||
{{8 * 8, 1 * 16}, "Controls State", Theme::getInstance()->bg_darkest->foreground},
|
||||
{{0 * 8, 11 * 16}, "Dial:", Theme::getInstance()->fg_medium->foreground},
|
||||
{{0 * 8, 14 * 16}, "Long-Press Mode:", Theme::getInstance()->fg_medium->foreground}};
|
||||
{{UI_POS_X_CENTER(14), 1 * 16}, "Controls State", Theme::getInstance()->bg_darkest->foreground},
|
||||
{{UI_POS_X(0), 11 * 16}, "Dial:", Theme::getInstance()->fg_medium->foreground},
|
||||
{{UI_POS_X(0), 14 * 16}, "Long-Press Mode:", Theme::getInstance()->fg_medium->foreground}};
|
||||
|
||||
ControlsSwitchesWidget switches_widget{
|
||||
{80, 80, 80, 112},
|
||||
|
|
@ -259,7 +259,7 @@ class DebugControlsView : public View {
|
|||
}};
|
||||
|
||||
Button button_done{
|
||||
{72, 264, 96, 24},
|
||||
{UI_POS_X_CENTER(12), 264, 96, 24},
|
||||
"Done"};
|
||||
};
|
||||
|
||||
|
|
@ -271,28 +271,28 @@ class DebugMemoryDumpView : public View {
|
|||
|
||||
private:
|
||||
Button button_dump{
|
||||
{72, 4 * 16, 96, 24},
|
||||
{UI_POS_X_CENTER(12), 4 * 16, 96, 24},
|
||||
"Dump"};
|
||||
|
||||
Button button_read{
|
||||
{16, 11 * 16, 96, 24},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(10), 11 * 16, 96, 24},
|
||||
"Read"};
|
||||
|
||||
Button button_write{
|
||||
{128, 11 * 16, 96, 24},
|
||||
{UI_POS_X_CENTER(12) + UI_POS_WIDTH(10), 11 * 16, 96, 24},
|
||||
"Write"};
|
||||
|
||||
Button button_done{
|
||||
{128, screen_height - 80, 96, 24},
|
||||
{UI_POS_X_RIGHT(12), UI_POS_Y_BOTTOM(3), 96, 24},
|
||||
"Done"};
|
||||
|
||||
Labels labels{
|
||||
{{5 * 8, 1 * 16}, "Dump Range to File", Theme::getInstance()->fg_yellow->foreground},
|
||||
{{0 * 8, 2 * 16}, "Starting Address: 0x", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 3 * 16}, "Byte Count: 0x", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 2 * 16}, "Starting Address: 0x", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 3 * 16}, "Byte Count: 0x", Theme::getInstance()->fg_light->foreground},
|
||||
{{3 * 8, 8 * 16}, "Read/Write Single Word", Theme::getInstance()->fg_yellow->foreground},
|
||||
{{0 * 8, 9 * 16}, "Memory Address: 0x", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 10 * 16}, "Data Value: 0x", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 9 * 16}, "Memory Address: 0x", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 10 * 16}, "Data Value: 0x", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
SymField field_starting_address{
|
||||
{20 * 8, 2 * 16},
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ BatteryCapacityView::RegisterEntry BatteryCapacityView::get_entry(size_t index)
|
|||
|
||||
BatteryCapacityView::BatteryCapacityView(NavigationView& nav) {
|
||||
for (size_t i = 0; i < ENTRIES_PER_PAGE; ++i) {
|
||||
name_texts[i].set_parent_rect({0 * 8, static_cast<int>((i + 1) * 16), 8 * 8, 16});
|
||||
name_texts[i].set_parent_rect({UI_POS_X(0), static_cast<int>((i + 1) * 16), 8 * 8, 16});
|
||||
addr_texts[i].set_parent_rect({9 * 8, static_cast<int>((i + 1) * 16), 4 * 8, 16});
|
||||
hex_texts[i].set_parent_rect({14 * 8, static_cast<int>((i + 1) * 16), 6 * 8, 16});
|
||||
value_texts[i].set_parent_rect({21 * 8, static_cast<int>((i + 1) * 16), 10 * 8, 16});
|
||||
|
|
|
|||
|
|
@ -24,18 +24,18 @@ class BatteryCapacityView : public View {
|
|||
static RegisterEntry get_entry(size_t index);
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 0 * 16}, "Reg", Theme::getInstance()->fg_yellow->foreground},
|
||||
{{9 * 8, 0 * 16}, "Addr", Theme::getInstance()->fg_yellow->foreground},
|
||||
{{14 * 8, 0 * 16}, "Hex", Theme::getInstance()->fg_yellow->foreground},
|
||||
{{21 * 8, 0 * 16}, "Value", Theme::getInstance()->fg_yellow->foreground},
|
||||
{{UI_POS_X(0), UI_POS_Y(0)}, "Reg", Theme::getInstance()->fg_yellow->foreground},
|
||||
{{9 * 8, UI_POS_Y(0)}, "Addr", Theme::getInstance()->fg_yellow->foreground},
|
||||
{{14 * 8, UI_POS_Y(0)}, "Hex", Theme::getInstance()->fg_yellow->foreground},
|
||||
{{21 * 8, UI_POS_Y(0)}, "Value", Theme::getInstance()->fg_yellow->foreground},
|
||||
};
|
||||
std::array<Text, 16> name_texts = {};
|
||||
std::array<Text, 16> addr_texts = {};
|
||||
std::array<Text, 16> hex_texts = {};
|
||||
std::array<Text, 16> value_texts = {};
|
||||
|
||||
Text page_text{{144, 284, 80, 16}, "Page 1/1"};
|
||||
Button button_done{{16, 280, 96, 24}, "Done"};
|
||||
Text page_text{{144, UI_POS_Y_BOTTOM(3), 80, 16}, "Page 1/1"};
|
||||
Button button_done{{16, UI_POS_Y_BOTTOM(3), 96, 24}, "Done"};
|
||||
|
||||
void update_values();
|
||||
void populate_page(int start_index);
|
||||
|
|
|
|||
|
|
@ -216,10 +216,10 @@ class EncodersView : public View {
|
|||
"Ready"};
|
||||
|
||||
ProgressBar progressbar{
|
||||
{2 * 8, 13 * 16 + 20, 208, 16}};
|
||||
{2 * 8, 13 * 16 + 20, UI_POS_WIDTH_REMAINING(4), 16}};
|
||||
|
||||
TransmitterView tx_view{
|
||||
16 * 16,
|
||||
(int16_t)UI_POS_Y_BOTTOM(4),
|
||||
50000,
|
||||
9};
|
||||
|
||||
|
|
|
|||
|
|
@ -294,6 +294,7 @@ FileManBaseView::FileManBaseView(
|
|||
std::string filter)
|
||||
: nav_{nav},
|
||||
extension_filter{filter} {
|
||||
max_filename_length = screen_width / 8 - 10;
|
||||
add_children({&labels,
|
||||
&text_current,
|
||||
&button_exit});
|
||||
|
|
@ -403,7 +404,7 @@ void FileManBaseView::refresh_list() {
|
|||
menu_view.clear();
|
||||
|
||||
for (const auto& entry : entry_list) {
|
||||
auto entry_name = std::string{entry.path.length() <= 20 ? entry.path : entry.path.substr(0, 20)};
|
||||
auto entry_name = std::string{entry.path.length() <= max_filename_length ? entry.path : entry.path.substr(0, max_filename_length)};
|
||||
|
||||
if (entry.is_directory) {
|
||||
std::string size_str{};
|
||||
|
|
@ -414,7 +415,7 @@ void FileManBaseView::refresh_list() {
|
|||
}
|
||||
|
||||
menu_view.add_item(
|
||||
{entry_name.substr(0, max_filename_length) + std::string(21 - entry_name.length(), ' ') + size_str,
|
||||
{entry_name.substr(0, max_filename_length) + std::string((max_filename_length + 1) - entry_name.length(), ' ') + size_str,
|
||||
Theme::getInstance()->fg_yellow->foreground,
|
||||
&bitmap_icon_dir,
|
||||
[this](KeyEvent key) {
|
||||
|
|
@ -427,7 +428,7 @@ void FileManBaseView::refresh_list() {
|
|||
auto size_str = to_string_file_size(entry.size);
|
||||
|
||||
menu_view.add_item(
|
||||
{entry_name.substr(0, max_filename_length) + std::string(21 - entry_name.length(), ' ') + size_str,
|
||||
{entry_name.substr(0, max_filename_length) + std::string((max_filename_length + 1) - entry_name.length(), ' ') + size_str,
|
||||
assoc.color,
|
||||
assoc.icon,
|
||||
[this](KeyEvent key) {
|
||||
|
|
@ -486,7 +487,7 @@ FileLoadView::FileLoadView(
|
|||
add_children({&menu_view});
|
||||
|
||||
// Resize menu view to fill screen
|
||||
menu_view.set_parent_rect({0, 3 * 8, screen_width, 29 * 8});
|
||||
menu_view.set_parent_rect({0, 3 * 8, screen_width, UI_POS_HEIGHT_REMAINING(4.5)});
|
||||
|
||||
refresh_list();
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class FileManBaseView : public View {
|
|||
uint8_t pagination = 0;
|
||||
uint8_t nb_pages = 1;
|
||||
bool restoring_navigation = false;
|
||||
static constexpr size_t max_filename_length = 20;
|
||||
size_t max_filename_length = 20;
|
||||
static constexpr size_t max_items_loaded = 75; // too memory hungry, so won't sort it
|
||||
static constexpr size_t items_per_page = 20;
|
||||
|
||||
|
|
@ -122,16 +122,16 @@ class FileManBaseView : public View {
|
|||
{{0, 0}, "Path:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Text text_current{
|
||||
{6 * 8, 0 * 8, 24 * 8, 16},
|
||||
{UI_POS_X(6), UI_POS_Y(0), UI_POS_WIDTH_REMAINING(6), UI_POS_HEIGHT(1)},
|
||||
"",
|
||||
};
|
||||
|
||||
MenuView menu_view{
|
||||
{0, 2 * 8, screen_width, 26 * 8},
|
||||
{0, UI_POS_Y(1), UI_POS_MAXWIDTH, UI_POS_HEIGHT_REMAINING(7)},
|
||||
true};
|
||||
|
||||
Button button_exit{
|
||||
{22 * 8, 34 * 8, 8 * 8, 32},
|
||||
{UI_POS_X_RIGHT(8), UI_POS_Y_BOTTOM(3), 8 * 8, UI_POS_HEIGHT(2)},
|
||||
"Exit"};
|
||||
};
|
||||
|
||||
|
|
@ -230,66 +230,66 @@ class FileManagerView : public FileManBaseView {
|
|||
bool selected_is_valid() const;
|
||||
|
||||
Text text_date{
|
||||
{0 * 8, 26 * 8, 28 * 8, 16},
|
||||
{UI_POS_X(0), UI_POS_Y_BOTTOM(6), 28 * 8, UI_POS_HEIGHT(1)},
|
||||
""};
|
||||
|
||||
NewButton button_rename{
|
||||
{0 * 8, 29 * 8, 4 * 8, 32},
|
||||
{UI_POS_X(0), UI_POS_Y_BOTTOM(5), UI_POS_WIDTH(4), UI_POS_HEIGHT(2)},
|
||||
{},
|
||||
&bitmap_icon_rename,
|
||||
Theme::getInstance()->fg_blue->foreground};
|
||||
|
||||
NewButton button_delete{
|
||||
{9 * 8, 34 * 8, 4 * 8, 32},
|
||||
{UI_POS_X(9), UI_POS_Y_BOTTOM(3), UI_POS_WIDTH(4), UI_POS_HEIGHT(2)},
|
||||
{},
|
||||
&bitmap_icon_trash,
|
||||
Theme::getInstance()->fg_red->foreground};
|
||||
|
||||
NewButton button_clean{
|
||||
{13 * 8, 34 * 8, 4 * 8, 32},
|
||||
{UI_POS_X(13), UI_POS_Y_BOTTOM(3), UI_POS_WIDTH(4), UI_POS_HEIGHT(2)},
|
||||
{},
|
||||
&bitmap_icon_clean,
|
||||
Theme::getInstance()->fg_red->foreground};
|
||||
|
||||
NewButton button_cut{
|
||||
{9 * 8, 29 * 8, 4 * 8, 32},
|
||||
{UI_POS_X(9), UI_POS_Y_BOTTOM(5), UI_POS_WIDTH(4), UI_POS_HEIGHT(2)},
|
||||
{},
|
||||
&bitmap_icon_cut,
|
||||
Theme::getInstance()->fg_dark->foreground};
|
||||
|
||||
NewButton button_copy{
|
||||
{13 * 8, 29 * 8, 4 * 8, 32},
|
||||
{UI_POS_X(13), UI_POS_Y_BOTTOM(5), UI_POS_WIDTH(4), UI_POS_HEIGHT(2)},
|
||||
{},
|
||||
&bitmap_icon_copy,
|
||||
Theme::getInstance()->fg_dark->foreground};
|
||||
|
||||
NewButton button_paste{
|
||||
{17 * 8, 29 * 8, 4 * 8, 32},
|
||||
{UI_POS_X(17), UI_POS_Y_BOTTOM(5), UI_POS_WIDTH(4), UI_POS_HEIGHT(2)},
|
||||
{},
|
||||
&bitmap_icon_paste,
|
||||
Theme::getInstance()->fg_dark->foreground};
|
||||
|
||||
NewButton button_new_dir{
|
||||
{22 * 8, 29 * 8, 4 * 8, 32},
|
||||
{UI_POS_X(22), UI_POS_Y_BOTTOM(5), UI_POS_WIDTH(4), UI_POS_HEIGHT(2)},
|
||||
{},
|
||||
&bitmap_icon_new_dir,
|
||||
Theme::getInstance()->fg_green->foreground};
|
||||
|
||||
NewButton button_new_file{
|
||||
{26 * 8, 29 * 8, 4 * 8, 32},
|
||||
{UI_POS_X(26), UI_POS_Y_BOTTOM(5), UI_POS_WIDTH(4), UI_POS_HEIGHT(2)},
|
||||
{},
|
||||
&bitmap_icon_new_file,
|
||||
Theme::getInstance()->fg_green->foreground};
|
||||
|
||||
NewButton button_open_notepad{
|
||||
{0 * 8, 34 * 8, 4 * 8, 32},
|
||||
{UI_POS_X(0), UI_POS_Y_BOTTOM(3), UI_POS_WIDTH(4), UI_POS_HEIGHT(2)},
|
||||
{},
|
||||
&bitmap_icon_notepad,
|
||||
Theme::getInstance()->fg_orange->foreground};
|
||||
|
||||
NewButton button_rename_timestamp{
|
||||
|
||||
{4 * 8, 29 * 8, 4 * 8, 32},
|
||||
{UI_POS_X(4), UI_POS_Y_BOTTOM(5), UI_POS_WIDTH(4), UI_POS_HEIGHT(2)},
|
||||
{},
|
||||
&bitmap_icon_options_datetime,
|
||||
Theme::getInstance()->fg_blue->foreground,
|
||||
|
|
@ -297,13 +297,13 @@ class FileManagerView : public FileManBaseView {
|
|||
|
||||
NewButton button_open_iq_trim{
|
||||
|
||||
{4 * 8, 34 * 8, 4 * 8, 32},
|
||||
{UI_POS_X(4), UI_POS_Y_BOTTOM(3), UI_POS_WIDTH(4), UI_POS_HEIGHT(2)},
|
||||
{},
|
||||
&bitmap_icon_trim,
|
||||
Theme::getInstance()->fg_orange->foreground};
|
||||
|
||||
NewButton button_show_hidden_files{
|
||||
{17 * 8, 34 * 8, 4 * 8, 32},
|
||||
{UI_POS_X(17), UI_POS_Y_BOTTOM(3), UI_POS_WIDTH(4), UI_POS_HEIGHT(2)},
|
||||
{},
|
||||
&bitmap_icon_hide,
|
||||
Theme::getInstance()->fg_dark->foreground};
|
||||
|
|
|
|||
|
|
@ -130,6 +130,12 @@ bool FlashUtilityView::endsWith(const std::u16string& str, const std::u16string&
|
|||
}
|
||||
}
|
||||
|
||||
void FlashUtilityView::wait_till_loaded() {
|
||||
while (!isLoaded) {
|
||||
chThdSleepMilliseconds(50);
|
||||
}
|
||||
}
|
||||
|
||||
std::filesystem::path FlashUtilityView::extract_tar(std::filesystem::path::string_type path, ui::Painter& painter) {
|
||||
//
|
||||
painter.fill_rectangle(
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ class FlashUtilityView : public View {
|
|||
|
||||
std::string title() const override { return "Flash Utility"; };
|
||||
bool flash_firmware(std::filesystem::path::string_type path);
|
||||
void wait_till_loaded();
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
|
|
@ -60,13 +61,21 @@ class FlashUtilityView : public View {
|
|||
{{4, 4}, "Select firmware to flash:", Theme::getInstance()->bg_darkest->foreground}};
|
||||
|
||||
MenuView menu_view{
|
||||
{0, 2 * 8, screen_width, 26 * 8},
|
||||
{0, UI_POS_Y(1), screen_width, UI_POS_HEIGHT_REMAINING(2)},
|
||||
true};
|
||||
|
||||
std::filesystem::path extract_tar(std::filesystem::path::string_type path, ui::Painter& painter); // extracts the tar file, and returns the firmware.bin path from it. empty string if no fw
|
||||
void firmware_selected(std::filesystem::path::string_type path);
|
||||
|
||||
bool endsWith(const std::u16string& str, const std::u16string& suffix);
|
||||
bool isLoaded = false;
|
||||
uint8_t refreshcnt = 0;
|
||||
MessageHandlerRegistration message_handler_frame_sync{
|
||||
Message::ID::DisplayFrameSync,
|
||||
[this](const Message* const) {
|
||||
refreshcnt++;
|
||||
if (refreshcnt > 5) isLoaded = true;
|
||||
}};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ class FreqManBaseView : public View {
|
|||
{0, 3 * 8, screen_width, 12 * 16 + 2 /* 2 Keeps text out of border. */}};
|
||||
|
||||
Button button_exit{
|
||||
{15 * 8, 17 * 16, 15 * 8, 2 * 16},
|
||||
{UI_POS_X_RIGHT(14), UI_POS_Y_BOTTOM(3), UI_POS_WIDTH(14), UI_POS_HEIGHT(2)},
|
||||
"Exit"};
|
||||
|
||||
protected:
|
||||
|
|
@ -97,14 +97,14 @@ class FrequencySaveView : public FreqManBaseView {
|
|||
0};
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 6 * 16}, "Description:", Theme::getInstance()->bg_darkest->foreground}};
|
||||
{{UI_POS_X(0), 6 * 16}, "Description:", Theme::getInstance()->bg_darkest->foreground}};
|
||||
|
||||
TextField field_description{
|
||||
{0 * 8, 7 * 16, screen_width, 1 * 16},
|
||||
{UI_POS_X(0), 7 * 16, screen_width, 1 * 16},
|
||||
""};
|
||||
|
||||
Button button_save{
|
||||
{0 * 8, 17 * 16, 15 * 8, 2 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y_BOTTOM(3), UI_POS_WIDTH(14), UI_POS_HEIGHT(2)},
|
||||
"Save"};
|
||||
};
|
||||
|
||||
|
|
@ -134,44 +134,44 @@ class FrequencyManagerView : public FreqManBaseView {
|
|||
void on_del_entry();
|
||||
|
||||
NewButton button_add_category{
|
||||
{23 * 8, 0 * 16, 7 * 4, 20},
|
||||
{UI_POS_X_RIGHT(8), UI_POS_Y(0), 7 * 4, 20},
|
||||
{},
|
||||
&bitmap_icon_new_file,
|
||||
Theme::getInstance()->bg_darkest->foreground,
|
||||
true};
|
||||
|
||||
NewButton button_del_category{
|
||||
{26 * 8 + 4, 0 * 16, 7 * 4, 20},
|
||||
{UI_POS_X_RIGHT(4), UI_POS_Y(0), 7 * 4, 20},
|
||||
{},
|
||||
&bitmap_icon_trash,
|
||||
Theme::getInstance()->fg_red->foreground,
|
||||
true};
|
||||
|
||||
Button button_edit_entry{
|
||||
{0 * 8, 14 * 16 - 4, 15 * 8, 1 * 16 + 4},
|
||||
{UI_POS_X(0), UI_POS_Y_BOTTOM(6.5) + 4, 15 * 8, 1 * 16 + 4},
|
||||
"Edit"};
|
||||
|
||||
Rectangle rect_padding{
|
||||
{15 * 8, 14 * 16 - 4, 15 * 8, 1 * 16 + 4},
|
||||
{15 * 8, UI_POS_Y_BOTTOM(6.5), 15 * 8, 1 * 16 + 4},
|
||||
Theme::getInstance()->fg_medium->background};
|
||||
|
||||
Button button_edit_freq{
|
||||
{0 * 8, 15 * 16, 15 * 8, 2 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y_BOTTOM(5), 15 * 8, 2 * 16},
|
||||
"Frequency"};
|
||||
|
||||
Button button_edit_desc{
|
||||
{0 * 8, 17 * 16, 15 * 8, 2 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y_BOTTOM(3), 15 * 8, 2 * 16},
|
||||
"Description"};
|
||||
|
||||
NewButton button_add_entry{
|
||||
{15 * 8, 15 * 16, 7 * 8 + 4, 2 * 16},
|
||||
{15 * 8, UI_POS_Y_BOTTOM(5), 7 * 8 + 4, 2 * 16},
|
||||
{},
|
||||
&bitmap_icon_add,
|
||||
Theme::getInstance()->bg_darkest->foreground,
|
||||
true};
|
||||
|
||||
NewButton button_del_entry{
|
||||
{22 * 8 + 4, 15 * 16, 7 * 8 + 4, 2 * 16},
|
||||
{22 * 8 + 4, UI_POS_Y_BOTTOM(5), 7 * 8 + 4, 2 * 16},
|
||||
{},
|
||||
&bitmap_icon_delete,
|
||||
Theme::getInstance()->fg_red->foreground,
|
||||
|
|
@ -201,14 +201,14 @@ class FrequencyEditView : public View {
|
|||
|
||||
Labels labels{
|
||||
{{5 * 8, 1 * 16}, "Edit Frequency Entry", Theme::getInstance()->bg_darkest->foreground},
|
||||
{{0 * 8, 3 * 16}, "Entry Type :", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 4 * 16}, "Frequency A:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 5 * 16}, "Frequency B:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 6 * 16}, "Modulation :", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 7 * 16}, "Bandwidth :", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 8 * 16}, "Step :", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 9 * 16}, "Tone Freq :", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 10 * 16}, "Description:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 3 * 16}, "Entry Type :", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 4 * 16}, "Frequency A:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 5 * 16}, "Frequency B:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 6 * 16}, "Modulation :", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 7 * 16}, "Bandwidth :", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 8 * 16}, "Step :", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 9 * 16}, "Tone Freq :", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 10 * 16}, "Description:", Theme::getInstance()->fg_light->foreground},
|
||||
};
|
||||
|
||||
OptionsField field_type{
|
||||
|
|
@ -243,11 +243,11 @@ class FrequencyEditView : public View {
|
|||
{}};
|
||||
|
||||
Button button_save{
|
||||
{0 * 8, 17 * 16, 15 * 8, 2 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y_BOTTOM(3), 15 * 8, 2 * 16},
|
||||
"Save"};
|
||||
|
||||
Button button_cancel{
|
||||
{15 * 8, 17 * 16, 15 * 8, 2 * 16},
|
||||
{UI_POS_X_RIGHT(15), UI_POS_Y_BOTTOM(3), 15 * 8, 2 * 16},
|
||||
"Cancel"};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class TrimProgressUI {
|
|||
}
|
||||
|
||||
void clear() {
|
||||
p.fill_rectangle({0 * 8, 4 * 16, screen_width, 3 * 16}, Theme::getInstance()->bg_darkest->background);
|
||||
p.fill_rectangle({UI_POS_X(0), 4 * 16, screen_width, 3 * 16}, Theme::getInstance()->bg_darkest->background);
|
||||
}
|
||||
|
||||
auto get_callback() {
|
||||
|
|
@ -100,22 +100,22 @@ class IQTrimView : public View {
|
|||
TrimProgressUI progress_ui{};
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 0 * 16}, "Capture File:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 6 * 16}, "Start :", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 7 * 16}, "End :", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 8 * 16}, "Samples:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 9 * 16}, "Max Pwr:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 10 * 16}, "Cutoff :", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), UI_POS_Y(0)}, "Capture File:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 6 * 16}, "Start :", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 7 * 16}, "End :", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 8 * 16}, "Samples:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 9 * 16}, "Max Pwr:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 10 * 16}, "Cutoff :", Theme::getInstance()->fg_light->foreground},
|
||||
{{12 * 8, 10 * 16}, "%", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 12 * 16}, "Amplify:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 12 * 16}, "Amplify:", Theme::getInstance()->fg_light->foreground},
|
||||
{{10 * 8, 12 * 16}, "x", Theme::getInstance()->fg_light->foreground},
|
||||
};
|
||||
|
||||
TextField field_path{
|
||||
{0 * 8, 1 * 16, screen_width, 1 * 16},
|
||||
{UI_POS_X(0), 1 * 16, screen_width, 1 * 16},
|
||||
"Open File..."};
|
||||
|
||||
Point pos_lines{0 * 8, 4 * 16};
|
||||
Point pos_lines{UI_POS_X(0), 4 * 16};
|
||||
Dim height_lines{2 * 16};
|
||||
|
||||
NumberField field_start{
|
||||
|
|
@ -155,7 +155,7 @@ class IQTrimView : public View {
|
|||
' '};
|
||||
|
||||
Button button_trim{
|
||||
{20 * 8, 16 * 16, 8 * 8, 2 * 16},
|
||||
{UI_POS_X_CENTER(8), UI_POS_Y_BOTTOM(3), 8 * 8, 2 * 16},
|
||||
"Trim"};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ class GlassView : public View {
|
|||
uint8_t ignore_dc = 0;
|
||||
|
||||
Labels labels{
|
||||
{{0, 0 * 16}, "MIN: MAX: LNA VGA ", Theme::getInstance()->fg_light->foreground},
|
||||
{{0, UI_POS_Y(0)}, "MIN: MAX: LNA VGA ", Theme::getInstance()->fg_light->foreground},
|
||||
{{0, 1 * 16}, "RANGE: FILTER: AMP:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0, 2 * 16}, "P:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0, 3 * 16}, "MARKER: MHz RXIQCAL", Theme::getInstance()->fg_light->foreground},
|
||||
|
|
@ -178,24 +178,24 @@ class GlassView : public View {
|
|||
{{0, 4 * 16}, "RES: VOL:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
NumberField field_frequency_min{
|
||||
{4 * 8, 0 * 16},
|
||||
{4 * 8, UI_POS_Y(0)},
|
||||
4,
|
||||
{0, 7199},
|
||||
1, // number of steps by encoder delta
|
||||
' '};
|
||||
|
||||
NumberField field_frequency_max{
|
||||
{13 * 8, 0 * 16},
|
||||
{13 * 8, UI_POS_Y(0)},
|
||||
4,
|
||||
{1, 7200},
|
||||
1, // number of steps by encoder delta
|
||||
' '};
|
||||
|
||||
LNAGainField field_lna{
|
||||
{21 * 8, 0 * 16}};
|
||||
{21 * 8, UI_POS_Y(0)}};
|
||||
|
||||
VGAGainField field_vga{
|
||||
{27 * 8, 0 * 16}};
|
||||
{27 * 8, UI_POS_Y(0)}};
|
||||
|
||||
TextField field_range{
|
||||
{6 * 8, 1 * 16, 6 * 8, 16},
|
||||
|
|
@ -298,7 +298,7 @@ class GlassView : public View {
|
|||
"RST"};
|
||||
|
||||
Text freq_stats{
|
||||
{0 * 8, 5 * 16, screen_width - 10 * 8, 8},
|
||||
{UI_POS_X(0), 5 * 16, screen_width - 10 * 8, 8},
|
||||
""};
|
||||
|
||||
MessageHandlerRegistration message_handler_spectrum_config{
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ class MicTXView : public View {
|
|||
{{17 * 8, 1 * 8}, "ALC", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
VuMeter vumeter{
|
||||
{0 * 8, 1 * 8, 2 * 8, 33 * 8},
|
||||
{UI_POS_X(0), 1 * 8, 2 * 8, 33 * 8},
|
||||
12,
|
||||
true};
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ class ModemSetupView : public View {
|
|||
"SET"};
|
||||
|
||||
Button button_save{
|
||||
{9 * 8, 250, 96, 40},
|
||||
{UI_POS_X_CENTER(12), 250, UI_POS_WIDTH(12), 40},
|
||||
"Save"};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -387,7 +387,6 @@ PlaylistView::PlaylistView(
|
|||
&button_next,
|
||||
&waterfall,
|
||||
});
|
||||
|
||||
ensure_directory(playlist_dir);
|
||||
waterfall.show_audio_spectrum_view(false);
|
||||
|
||||
|
|
|
|||
|
|
@ -107,24 +107,24 @@ class PlaylistView : public View {
|
|||
void handle_replay_thread_done(uint32_t return_code);
|
||||
|
||||
Text text_filename{
|
||||
{0 * 8, 0 * 16, screen_width, 16}};
|
||||
{UI_POS_X(0), UI_POS_Y(0), screen_width, 16}};
|
||||
|
||||
FrequencyField field_frequency{
|
||||
{0 * 8, 1 * 16}};
|
||||
{UI_POS_X(0), 1 * 16}};
|
||||
|
||||
Text text_sample_rate{
|
||||
{10 * 8, 1 * 16, 7 * 8, 16}};
|
||||
|
||||
ProgressBar progressbar_track{
|
||||
{18 * 8, 1 * 16, 12 * 8, 8 + 1}};
|
||||
{18 * 8, 1 * 16, UI_POS_WIDTH_REMAINING(19), 8 + 1}};
|
||||
|
||||
// (-1) to overlap with progressbar_track so there's
|
||||
// only 1 pixel between them instead of 2.
|
||||
ProgressBar progressbar_transmit{
|
||||
{18 * 8, 3 * 8 - 1, 12 * 8, 8}};
|
||||
{18 * 8, 3 * 8 - 1, UI_POS_WIDTH_REMAINING(19), 8}};
|
||||
|
||||
Text text_duration{
|
||||
{0 * 8, 2 * 16, 5 * 8, 16}};
|
||||
{UI_POS_X(0), 2 * 16, 5 * 8, 16}};
|
||||
|
||||
// TODO: delay duration field.
|
||||
|
||||
|
|
@ -133,7 +133,7 @@ class PlaylistView : public View {
|
|||
/*short_ui*/ true};
|
||||
|
||||
Checkbox check_loop{
|
||||
{21 * 8, 2 * 16},
|
||||
{UI_POS_X_RIGHT(9), 2 * 16},
|
||||
4,
|
||||
"Loop",
|
||||
true};
|
||||
|
|
@ -145,7 +145,7 @@ class PlaylistView : public View {
|
|||
Theme::getInstance()->fg_green->background};
|
||||
|
||||
Text text_track{
|
||||
{0 * 8, 3 * 16, screen_width, 16}};
|
||||
{UI_POS_X(0), 3 * 16, screen_width, 16}};
|
||||
|
||||
NewButton button_prev{
|
||||
{2 * 8, 4 * 16, 4 * 8, 2 * 16},
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ class POCSAGTXView : public View {
|
|||
{{6 * 8, 8 * 8}, "Type:", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, 10 * 8}, "Function:", Theme::getInstance()->fg_light->foreground},
|
||||
{{5 * 8, 12 * 8}, "Phase:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 14 * 8}, "Message:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 14 * 8}, "Message:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
OptionsField options_bitrate{
|
||||
{11 * 8, 4 * 8},
|
||||
|
|
@ -122,21 +122,21 @@ class POCSAGTXView : public View {
|
|||
}};
|
||||
|
||||
Text text_message{
|
||||
{0 * 8, 16 * 8, screen_width, 16},
|
||||
{UI_POS_X(0), 16 * 8, screen_width, 16},
|
||||
""};
|
||||
Text text_message_l2{
|
||||
{0 * 8, 18 * 8, screen_width, 16},
|
||||
{UI_POS_X(0), 18 * 8, screen_width, 16},
|
||||
""};
|
||||
|
||||
Button button_message{
|
||||
{0 * 8, 20 * 8, 14 * 8, 32},
|
||||
{UI_POS_X(0), 20 * 8, 14 * 8, 32},
|
||||
"Set message"};
|
||||
|
||||
ProgressBar progressbar{
|
||||
{16, 210, 208, 16}};
|
||||
{16, 210, UI_POS_WIDTH_REMAINING(4), 16}};
|
||||
|
||||
TransmitterView tx_view{
|
||||
16 * 16,
|
||||
(int16_t)UI_POS_Y_BOTTOM(4),
|
||||
10000,
|
||||
9};
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ class RDSRadioTextView : public OptionTabView {
|
|||
{1 * 8, 4 * 16, 28 * 8, 16},
|
||||
"-"};
|
||||
Button button_set{
|
||||
{88, 6 * 16, 64, 32},
|
||||
{UI_POS_X_CENTER(8), 6 * 16, UI_POS_WIDTH(8), 32},
|
||||
"Set"};
|
||||
};
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ class RDSDateTimeView : public OptionTabView {
|
|||
|
||||
private:
|
||||
Labels labels{
|
||||
{{44, 5 * 16}, "Not yet implemented", Theme::getInstance()->error_dark->foreground}};
|
||||
{{UI_POS_X_CENTER(19), 5 * 16}, "Not yet implemented", Theme::getInstance()->error_dark->foreground}};
|
||||
};
|
||||
|
||||
class RDSAudioView : public OptionTabView {
|
||||
|
|
@ -101,7 +101,7 @@ class RDSAudioView : public OptionTabView {
|
|||
|
||||
private:
|
||||
Labels labels{
|
||||
{{44, 5 * 16}, "Not yet implemented", Theme::getInstance()->error_dark->foreground}};
|
||||
{{UI_POS_X_CENTER(19), 5 * 16}, "Not yet implemented", Theme::getInstance()->error_dark->foreground}};
|
||||
};
|
||||
|
||||
class RDSThread {
|
||||
|
|
@ -174,7 +174,7 @@ class RDSView : public View {
|
|||
{"Audio", Theme::getInstance()->fg_orange->foreground, &view_audio}};
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 28}, "Program type:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 28}, "Program type:", Theme::getInstance()->fg_light->foreground},
|
||||
//{ { 14 * 8, 16 + 8 }, "CC:", Theme::getInstance()->fg_light->foreground },
|
||||
{{2 * 8, 28 + 16}, "Program ID:", Theme::getInstance()->fg_light->foreground},
|
||||
//{ { 13 * 8, 32 + 8 }, "Cov:",Theme::getInstance()->fg_light->foreground },
|
||||
|
|
@ -319,7 +319,7 @@ class RDSView : public View {
|
|||
"TP"};
|
||||
|
||||
TransmitterView tx_view{
|
||||
16 * 16,
|
||||
(int16_t)UI_POS_Y_BOTTOM(4),
|
||||
50000,
|
||||
9};
|
||||
|
||||
|
|
|
|||
|
|
@ -217,23 +217,24 @@ class ReconView : public View {
|
|||
std::unique_ptr<RecordView> record_view{};
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 0 * 16}, "LNA: VGA: AMP: VOL: ", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), UI_POS_Y(0)}, "LNA: VGA: AMP: ", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X_RIGHT(6), UI_POS_Y(0)}, "VOL: ", Theme::getInstance()->fg_light->foreground},
|
||||
{{3 * 8, 8 * 16}, "START END", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, (22 * 8)}, " S: ", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, (24 * 8) + 4}, "NBLCKS:x W,L: , ", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, (26 * 8) + 4}, "MODE: , SQUELCH: ", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), (22 * 8)}, " S: ", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), (24 * 8) + 4}, "NBLCKS:x W,L: , ", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), (26 * 8) + 4}, "MODE: , SQUELCH: ", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
LNAGainField field_lna{
|
||||
{4 * 8, 0 * 16}};
|
||||
{4 * 8, UI_POS_Y(0)}};
|
||||
|
||||
VGAGainField field_vga{
|
||||
{11 * 8, 0 * 16}};
|
||||
{11 * 8, UI_POS_Y(0)}};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
|
||||
AudioVolumeField field_volume{
|
||||
{24 * 8, 0 * 16}};
|
||||
{UI_POS_X_RIGHT(2), UI_POS_Y(0)}};
|
||||
|
||||
Text file_name{
|
||||
// show file used
|
||||
|
|
@ -297,7 +298,7 @@ class ReconView : public View {
|
|||
"CONFIG"};
|
||||
|
||||
ButtonWithEncoder button_manual_start{
|
||||
{0 * 8, 9 * 16, 11 * 8, 28},
|
||||
{UI_POS_X(0), 9 * 16, 11 * 8, 28},
|
||||
""};
|
||||
|
||||
ButtonWithEncoder button_manual_end{
|
||||
|
|
@ -305,7 +306,7 @@ class ReconView : public View {
|
|||
""};
|
||||
|
||||
OptionsField field_recon_match_mode{
|
||||
{0 * 8, 11 * 16},
|
||||
{UI_POS_X(0), 11 * 16},
|
||||
16, // CONTINUOUS MATCH MODE / SPARSE TIMED MATCH MODE
|
||||
{
|
||||
{"MATCH:CONTINOUS", 0},
|
||||
|
|
@ -363,15 +364,15 @@ class ReconView : public View {
|
|||
};
|
||||
|
||||
ButtonWithEncoder button_pause{
|
||||
{0, (15 * 16) - 4, 72, 28},
|
||||
{0, (15 * 16) - 4, UI_POS_WIDTH(9), 28},
|
||||
"PAUSE"};
|
||||
|
||||
Button button_audio_app{
|
||||
{84, (15 * 16) - 4, 72, 28},
|
||||
{UI_POS_X_CENTER(9), (15 * 16) - 4, UI_POS_WIDTH(9), 28},
|
||||
"AUDIO"};
|
||||
|
||||
ButtonWithEncoder button_add{
|
||||
{168, (15 * 16) - 4, 72, 28},
|
||||
{UI_POS_X_RIGHT(9), (15 * 16) - 4, UI_POS_WIDTH(9), 28},
|
||||
"<STORE>"};
|
||||
|
||||
Button button_dir{
|
||||
|
|
@ -383,15 +384,15 @@ class ReconView : public View {
|
|||
"RST"};
|
||||
|
||||
Button button_mic_app{
|
||||
{84, (35 * 8) - 4, 72, 28},
|
||||
{UI_POS_X_CENTER(9), (35 * 8) - 4, UI_POS_WIDTH(9), 28},
|
||||
"MIC TX"};
|
||||
|
||||
ButtonWithEncoder button_remove{
|
||||
{168, (35 * 8) - 4, 72, 28},
|
||||
{UI_POS_X_RIGHT(9), (35 * 8) - 4, UI_POS_WIDTH(9), 28},
|
||||
"<REMOVE>"};
|
||||
|
||||
ProgressBar progressbar{
|
||||
{0 * 8, screen_height / 2 - 16, screen_width, 32}};
|
||||
{UI_POS_X(0), screen_height / 2 - 16, screen_width, 32}};
|
||||
|
||||
TransmitterView2 tx_view{
|
||||
{11 * 8, 2 * 16},
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ class ReconSetupView : public View {
|
|||
{"More", Theme::getInstance()->fg_green->foreground, &viewMore}};
|
||||
|
||||
Button button_save{
|
||||
{9 * 8, 255, 14 * 8, 40},
|
||||
{UI_POS_X_CENTER(18), 255, UI_POS_WIDTH(18), 40},
|
||||
"SAVE"};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -46,15 +46,15 @@ class SdOverUsbView : public View {
|
|||
NavigationView& nav_;
|
||||
|
||||
Labels labels{
|
||||
{{3 * 8, 2 * 16}, "Click Run to start the", Theme::getInstance()->bg_darkest->foreground},
|
||||
{{3 * 8, 3 * 16}, "USB Mass Storage Mode.", Theme::getInstance()->bg_darkest->foreground},
|
||||
{{3 * 8, 5 * 16}, "It can take up to 20s", Theme::getInstance()->bg_darkest->foreground},
|
||||
{{3 * 8, 6 * 16}, "for the drive to be", Theme::getInstance()->bg_darkest->foreground},
|
||||
{{3 * 8, 7 * 16}, "available.", Theme::getInstance()->bg_darkest->foreground},
|
||||
{{UI_POS_X_CENTER(22), 2 * 16}, "Click Run to start the", Theme::getInstance()->bg_darkest->foreground},
|
||||
{{UI_POS_X_CENTER(22), 3 * 16}, "USB Mass Storage Mode.", Theme::getInstance()->bg_darkest->foreground},
|
||||
{{UI_POS_X_CENTER(21), 5 * 16}, "It can take up to 20s", Theme::getInstance()->bg_darkest->foreground},
|
||||
{{UI_POS_X_CENTER(19), 6 * 16}, "for the drive to be", Theme::getInstance()->bg_darkest->foreground},
|
||||
{{UI_POS_X_CENTER(10), 7 * 16}, "available.", Theme::getInstance()->bg_darkest->foreground},
|
||||
};
|
||||
|
||||
Button button_run{
|
||||
{9 * 8, 15 * 16, 12 * 8, 3 * 16},
|
||||
{UI_POS_X_CENTER(12), 15 * 16, 12 * 8, 3 * 16},
|
||||
"Run"};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,8 @@ void RecentEntriesTable<SearchRecentEntries>::draw(
|
|||
const Entry& entry,
|
||||
const Rect& target_rect,
|
||||
Painter& painter,
|
||||
const Style& style) {
|
||||
const Style& style,
|
||||
RecentEntriesColumns& columns) {
|
||||
std::string str_duration = "";
|
||||
|
||||
if (entry.duration < 600)
|
||||
|
|
@ -50,9 +51,10 @@ void RecentEntriesTable<SearchRecentEntries>::draw(
|
|||
else
|
||||
str_duration = to_string_dec_uint(entry.duration / 600) + "m" + to_string_dec_uint((entry.duration / 10) % 60) + "s";
|
||||
|
||||
str_duration.resize(target_rect.width() / 8, ' ');
|
||||
|
||||
painter.draw_string(target_rect.location(), style, to_string_short_freq(entry.frequency) + " " + entry.time + " " + str_duration);
|
||||
str_duration.resize(11, ' ');
|
||||
std::string freq = to_string_short_freq(entry.frequency);
|
||||
freq.resize(columns.at(0).second, ' ');
|
||||
painter.draw_string(target_rect.location(), style, freq + " " + entry.time + " " + str_duration);
|
||||
}
|
||||
|
||||
/* SearchView ********************************************/
|
||||
|
|
@ -60,6 +62,7 @@ void RecentEntriesTable<SearchRecentEntries>::draw(
|
|||
SearchView::SearchView(
|
||||
NavigationView& nav)
|
||||
: nav_(nav) {
|
||||
spectrum_row.resize(240);
|
||||
baseband::run_image(portapack::spi_flash::image_tag_wideband_spectrum);
|
||||
|
||||
if (!gradient.load_file(default_gradient_file)) {
|
||||
|
|
@ -86,7 +89,7 @@ SearchView::SearchView(
|
|||
|
||||
baseband::set_spectrum(SEARCH_SLICE_WIDTH, 31);
|
||||
|
||||
recent_entries_view.set_parent_rect({0, 28 * 8, screen_width, 12 * 8});
|
||||
recent_entries_view.set_parent_rect({0, 28 * 8, screen_width, screen_height - 28 * 8});
|
||||
recent_entries_view.on_select = [this, &nav](const SearchRecentEntry& entry) {
|
||||
nav.push<FrequencySaveView>(entry.frequency);
|
||||
};
|
||||
|
|
@ -160,9 +163,8 @@ void SearchView::do_detection() {
|
|||
// Display spectrum
|
||||
bin_skip_acc = 0;
|
||||
pixel_index = 0;
|
||||
display.draw_pixels(
|
||||
{{0, 88}, {(Dim)spectrum_row.size(), 1}},
|
||||
spectrum_row);
|
||||
uint16_t center_align_start = (screen_width - spectrum_row.size()) / 2;
|
||||
display.draw_pixels({{center_align_start, 88}, {(Dim)spectrum_row.size(), 1}}, spectrum_row);
|
||||
|
||||
mean_power = mean_acc / (SEARCH_BIN_NB_NO_DC * slices_nb);
|
||||
mean_acc = 0;
|
||||
|
|
@ -249,7 +251,7 @@ void SearchView::do_detection() {
|
|||
// Refresh red tick
|
||||
portapack::display.fill_rectangle({last_tick_pos, 90, 1, 6}, Theme::getInstance()->fg_red->background);
|
||||
if (bin_max > -1) {
|
||||
last_tick_pos = (Coord)(bin_max / slices_nb);
|
||||
last_tick_pos = (Coord)(bin_max / slices_nb) + center_align_start;
|
||||
portapack::display.fill_rectangle({last_tick_pos, 90, 1, 6}, Theme::getInstance()->fg_red->foreground);
|
||||
}
|
||||
}
|
||||
|
|
@ -398,7 +400,7 @@ void SearchView::add_spectrum_pixel(Color color) {
|
|||
|
||||
bin_skip_acc -= 0x10000;
|
||||
|
||||
if (pixel_index < screen_width)
|
||||
if (pixel_index < spectrum_row.size())
|
||||
spectrum_row[pixel_index++] = color;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ class SearchView : public View {
|
|||
uint32_t bin_skip_acc = 0;
|
||||
uint32_t bin_skip_frac = 0;
|
||||
uint32_t pixel_index = 0;
|
||||
std::array<Color, 240> spectrum_row{};
|
||||
std::vector<Color> spectrum_row{};
|
||||
ChannelSpectrumFIFO* fifo = nullptr;
|
||||
|
||||
uint8_t detect_timer = 0;
|
||||
|
|
@ -174,81 +174,82 @@ class SearchView : public View {
|
|||
void on_range_changed();
|
||||
void add_spectrum_pixel(Color color);
|
||||
|
||||
const RecentEntriesColumns columns{{{"Frequency", 9},
|
||||
{"Time", 8},
|
||||
{"Duration", 11}}};
|
||||
RecentEntriesColumns columns{{{"Frequency", 0},
|
||||
{"Time", 8},
|
||||
{"Duration", 11}}};
|
||||
SearchRecentEntries recent{};
|
||||
RecentEntriesView<RecentEntries<SearchRecentEntry>> recent_entries_view{columns, recent};
|
||||
|
||||
Labels labels{
|
||||
{{1 * 8, 0}, "Min: Max: LNA VGA", Theme::getInstance()->fg_light->foreground},
|
||||
{{1 * 8, 4 * 8}, "Trig: /255 Mean: /255", Theme::getInstance()->fg_light->foreground},
|
||||
{{1 * 8, 6 * 8}, "Slices: /32 Rate: Hz", Theme::getInstance()->fg_light->foreground},
|
||||
{{6 * 8, 10 * 8}, "Timer Status", Theme::getInstance()->fg_light->foreground},
|
||||
{{1 * 8, 25 * 8}, "Accuracy +/-4.9kHz", Theme::getInstance()->fg_light->foreground},
|
||||
{{26 * 8, 25 * 8}, "MHz", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(1), UI_POS_Y(0)}, "Min: Max: ", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X_RIGHT(7), UI_POS_Y(0)}, "LNA VGA", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(1), UI_POS_Y(2)}, "Trig: /255", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X_RIGHT(12), UI_POS_Y(2)}, "Mean: /255", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(1), UI_POS_Y(3)}, "Slices: /32", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X_RIGHT(10), UI_POS_Y(3)}, "Rate: Hz", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(6), UI_POS_Y(5)}, "Timer Status", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(1), 25 * 8}, "Accuracy +/-4.9kHz", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X_RIGHT(4), 25 * 8}, "MHz", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Checkbox check_log{
|
||||
{24 * 8, 10 * 8},
|
||||
{UI_POS_X_RIGHT(6), UI_POS_Y(5)},
|
||||
3,
|
||||
"LOG",
|
||||
true};
|
||||
|
||||
FrequencyField field_frequency_min{
|
||||
{1 * 8, 1 * 16}};
|
||||
{UI_POS_X(1), UI_POS_Y(1)}};
|
||||
FrequencyField field_frequency_max{
|
||||
{11 * 8, 1 * 16}};
|
||||
{UI_POS_X(11), UI_POS_Y(1)}};
|
||||
|
||||
LNAGainField field_lna{
|
||||
{22 * 8, 1 * 16}};
|
||||
{UI_POS_X_RIGHT(7), UI_POS_Y(1)}};
|
||||
VGAGainField field_vga{
|
||||
{26 * 8, 1 * 16}};
|
||||
{UI_POS_X_RIGHT(3), UI_POS_Y(1)}};
|
||||
|
||||
NumberField field_threshold{
|
||||
{6 * 8, 2 * 16},
|
||||
{UI_POS_X(6), UI_POS_Y(2)},
|
||||
3,
|
||||
{5, 255},
|
||||
5,
|
||||
' '};
|
||||
Text text_mean{
|
||||
{22 * 8, 2 * 16, 3 * 8, 16},
|
||||
{UI_POS_X_RIGHT(7), UI_POS_Y(2), UI_POS_WIDTH(3), UI_POS_HEIGHT(1)},
|
||||
"---"};
|
||||
Text text_slices{
|
||||
{8 * 8, 3 * 16, 2 * 8, 16},
|
||||
{UI_POS_X(8), UI_POS_Y(3), UI_POS_WIDTH(2), UI_POS_HEIGHT(1)},
|
||||
"--"};
|
||||
Text text_rate{
|
||||
{24 * 8, 3 * 16, 3 * 8, 16},
|
||||
{UI_POS_X_RIGHT(5), UI_POS_Y(3), UI_POS_WIDTH(3), UI_POS_HEIGHT(1)},
|
||||
"---"};
|
||||
|
||||
VuMeter vu_max{
|
||||
{1 * 8, 11 * 8 - 4, 3 * 8, 48},
|
||||
{UI_POS_X(1), 11 * 8 - 4, 3 * 8, 48},
|
||||
18,
|
||||
false};
|
||||
|
||||
ProgressBar progress_timers{
|
||||
{6 * 8, 12 * 8, 6 * 8, 16}};
|
||||
{UI_POS_X(6), UI_POS_Y(6), UI_POS_WIDTH(6), UI_POS_HEIGHT(1)}};
|
||||
Text text_infos{
|
||||
{13 * 8, 12 * 8, 15 * 8, 16},
|
||||
{UI_POS_X(13), UI_POS_Y(6), UI_POS_WIDTH(15), UI_POS_HEIGHT(1)},
|
||||
"Listening"};
|
||||
|
||||
Checkbox check_snap{
|
||||
{6 * 8, 15 * 8},
|
||||
{UI_POS_X(6), 15 * 8},
|
||||
7,
|
||||
"Snap to:",
|
||||
true};
|
||||
OptionsField options_snap{
|
||||
{17 * 8, 15 * 8}, // Position
|
||||
7, // Length
|
||||
{ // Options
|
||||
{UI_POS_X(17), 15 * 8}, // Position
|
||||
7, // Length
|
||||
{ // Options
|
||||
{"25kHz ", 25'000},
|
||||
{"12.5kHz", 12'500},
|
||||
{"8.33kHz", 8'333},
|
||||
{"2.5kHz", 2'500},
|
||||
{"500Hz", 500}}};
|
||||
|
||||
BigFrequency big_display{
|
||||
{4, 9 * 16, 28 * 8, 52},
|
||||
0};
|
||||
BigFrequency big_display{{UI_POS_X_CENTER(28), UI_POS_Y(9), UI_POS_WIDTH(28), 52}, 0};
|
||||
|
||||
MessageHandlerRegistration message_handler_spectrum_config{
|
||||
Message::ID::ChannelSpectrumConfig,
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ using namespace lpc43xx;
|
|||
|
||||
#include "audio.hpp"
|
||||
#include "portapack.hpp"
|
||||
#include "portapack_io.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
#include "file.hpp"
|
||||
|
|
@ -759,7 +760,7 @@ AppSettingsView::AppSettingsView(
|
|||
add_children({&labels,
|
||||
&menu_view});
|
||||
|
||||
menu_view.set_parent_rect({0, 3 * 8, screen_width, 33 * 8});
|
||||
menu_view.set_parent_rect({0, 3 * 8, screen_width, UI_POS_HEIGHT_REMAINING(3)});
|
||||
|
||||
ensure_directory(settings_dir);
|
||||
|
||||
|
|
@ -810,9 +811,12 @@ SetDisplayView::SetDisplayView(NavigationView& nav) {
|
|||
&field_fake_brightness,
|
||||
&button_save,
|
||||
&button_cancel,
|
||||
&checkbox_ips_screen_switch,
|
||||
&checkbox_brightness_switch});
|
||||
|
||||
if (portapack::device_type == portapack::DeviceType::DEV_PORTAPACK) {
|
||||
add_child(&checkbox_ips_screen_switch);
|
||||
}
|
||||
|
||||
field_fake_brightness.set_by_value(pmem::fake_brightness_level());
|
||||
checkbox_brightness_switch.set_value(pmem::apply_fake_brightness());
|
||||
checkbox_ips_screen_switch.set_value(pmem::config_lcd_normally_black());
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@ class SetDateTimeView : public View {
|
|||
{{1 * 8, 5 * 16 - 2}, "YYYY-MM-DD HH:MM:SS DoW DoY", Theme::getInstance()->fg_medium->foreground},
|
||||
{{5 * 8, 6 * 16}, "- - : :", Theme::getInstance()->fg_light->foreground},
|
||||
{{1 * 8, 11 * 16}, "DST adds 1 hour to RTC time.", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 12 * 16}, "Start: 0:00 on Nth DDD in", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 13 * 16}, "End: 1:00 on Nth DDD in", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 12 * 16}, "Start: 0:00 on Nth DDD in", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 13 * 16}, "End: 1:00 on Nth DDD in", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
NumberField field_year{
|
||||
{1 * 8, 6 * 16},
|
||||
|
|
@ -170,10 +170,10 @@ class SetDateTimeView : public View {
|
|||
{}};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), 12 * 8, 32},
|
||||
"Save"};
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) + UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), 12 * 8, 32},
|
||||
"Cancel"};
|
||||
|
||||
void form_init(const SetDateTimeModel& model);
|
||||
|
|
@ -253,10 +253,10 @@ class SetRadioView : public View {
|
|||
"Disable external TCXO"};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), 12 * 8, 32},
|
||||
"Save"};
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) + UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), 12 * 8, 32},
|
||||
"Cancel",
|
||||
};
|
||||
|
||||
|
|
@ -372,11 +372,11 @@ class SetUIView : public View {
|
|||
&bitmap_sd_card_ok};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
|
||||
"Save"};
|
||||
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(16) + UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
|
||||
"Cancel"};
|
||||
};
|
||||
|
||||
|
|
@ -391,28 +391,28 @@ class SetSDCardView : public View {
|
|||
private:
|
||||
Labels labels{
|
||||
// 01234567890123456789012345678
|
||||
{{1 * 8, 120 - 48}, " HIGH SPEED SDCARD IO ", Theme::getInstance()->fg_light->foreground},
|
||||
{{1 * 8, 120 - 32}, " May or may not work !! ", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X_CENTER(26), 120 - 48}, " HIGH SPEED SDCARD IO ", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X_CENTER(26), 120 - 32}, " May or may not work !! ", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Checkbox checkbox_sdcard_speed{
|
||||
{2 * 8, 120},
|
||||
{UI_POS_X_CENTER(26), 120},
|
||||
20,
|
||||
"enable high speed IO"};
|
||||
|
||||
Button button_test_sdcard_high_speed{
|
||||
{2 * 8, 152, 27 * 8, 32},
|
||||
{UI_POS_X_CENTER(27), 152, UI_POS_WIDTH(27), UI_POS_HEIGHT(2)},
|
||||
"TEST BUTTON (NO PMEM SAVE)"};
|
||||
|
||||
Text text_sdcard_test_status{
|
||||
{2 * 8, 198, 28 * 8, 16},
|
||||
{UI_POS_X_CENTER(28), 198, UI_POS_WIDTH(28), UI_POS_HEIGHT(1)},
|
||||
""};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
|
||||
"Save"};
|
||||
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(16) + UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
|
||||
"Cancel"};
|
||||
};
|
||||
|
||||
|
|
@ -455,7 +455,7 @@ class SetConverterSettingsView : public View {
|
|||
{8 * 8, 10 * 16}};
|
||||
|
||||
Button button_return{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12), UI_POS_Y_BOTTOM(4), 12 * 8, 32},
|
||||
"Return",
|
||||
};
|
||||
};
|
||||
|
|
@ -498,7 +498,7 @@ class SetFrequencyCorrectionView : public View {
|
|||
{8 * 8, 10 * 16}};
|
||||
|
||||
Button button_return{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12), UI_POS_Y_BOTTOM(4), 12 * 8, UI_POS_HEIGHT(2)},
|
||||
"Return",
|
||||
};
|
||||
};
|
||||
|
|
@ -536,11 +536,11 @@ class SetAudioView : public View {
|
|||
"Beep on RX packets"};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), 12 * 8, 32},
|
||||
"Save"};
|
||||
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) + UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), 12 * 8, 32},
|
||||
"Cancel",
|
||||
};
|
||||
};
|
||||
|
|
@ -559,11 +559,11 @@ class SetEncoderDialView : public View {
|
|||
|
||||
private:
|
||||
Labels labels{
|
||||
{{0 * 8, 0 * 16}, "Sensitivity to dial rotation", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 1 * 16}, "position (x steps per 360):", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), UI_POS_Y(0)}, "Sensitivity to dial rotation", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 1 * 16}, "position (x steps per 360):", Theme::getInstance()->fg_light->foreground},
|
||||
{{1 * 8, 3 * 16}, "Sensitivity:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 7 * 16}, "Rotation rate (default 1", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 8 * 16}, "means no rate dependency):", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 7 * 16}, "Rotation rate (default 1", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 8 * 16}, "means no rate dependency):", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, 10 * 16}, "Rate multiplier:", Theme::getInstance()->fg_light->foreground},
|
||||
{{4 * 8, 14 * 16}, "Direction:", Theme::getInstance()->fg_light->foreground},
|
||||
|
||||
|
|
@ -606,11 +606,11 @@ class SetEncoderDialView : public View {
|
|||
"-"};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), 12 * 8, 32},
|
||||
"Save"};
|
||||
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) + UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), 12 * 8, 32},
|
||||
"Cancel",
|
||||
};
|
||||
};
|
||||
|
|
@ -649,11 +649,11 @@ class SetButtonsView : public View {
|
|||
{"FAST", true}}};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), 12 * 8, 32},
|
||||
"Save"};
|
||||
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) + UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), 12 * 8, 32},
|
||||
"Cancel",
|
||||
};
|
||||
};
|
||||
|
|
@ -674,7 +674,7 @@ class SetPersistentMemoryView : public View {
|
|||
};
|
||||
|
||||
Text text_pmem_status{
|
||||
{1 * 8, 4 * 16 + 8, 28 * 8, 16},
|
||||
{UI_POS_X_CENTER(28), 4 * 16 + 8, 28 * 8, 16},
|
||||
""};
|
||||
|
||||
Checkbox check_use_sdcard_for_pmem{
|
||||
|
|
@ -683,19 +683,19 @@ class SetPersistentMemoryView : public View {
|
|||
"Use SD card for P.Mem"};
|
||||
|
||||
Button button_save_mem_to_file{
|
||||
{1 * 8, 8 * 16, 28 * 8, 2 * 16},
|
||||
{UI_POS_X_CENTER(28), 8 * 16, 28 * 8, 2 * 16},
|
||||
"Save P.Mem to SD card"};
|
||||
|
||||
Button button_load_mem_from_file{
|
||||
{1 * 8, 10 * 16 + 2, 28 * 8, 2 * 16},
|
||||
{UI_POS_X_CENTER(28), 10 * 16 + 2, 28 * 8, 2 * 16},
|
||||
"Load P.Mem from SD Card"};
|
||||
|
||||
Button button_load_mem_defaults{
|
||||
{1 * 8, 12 * 16 + 4, 28 * 8, 2 * 16},
|
||||
{UI_POS_X_CENTER(28), 12 * 16 + 4, 28 * 8, 2 * 16},
|
||||
"Reset P.Mem to defaults"};
|
||||
|
||||
Button button_return{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12), UI_POS_Y_BOTTOM(4), 12 * 8, 32},
|
||||
"Return",
|
||||
};
|
||||
};
|
||||
|
|
@ -713,7 +713,7 @@ class AppSettingsView : public View {
|
|||
{{0, 4}, "Select file to edit:", Theme::getInstance()->bg_darkest->foreground}};
|
||||
|
||||
MenuView menu_view{
|
||||
{0, 2 * 8, screen_width, 26 * 8},
|
||||
{0, 2 * 8, screen_width, UI_POS_HEIGHT_REMAINING(3)},
|
||||
true};
|
||||
};
|
||||
|
||||
|
|
@ -738,11 +738,11 @@ class SetConfigModeView : public View {
|
|||
"Config Mode enable"};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), 12 * 8, 32},
|
||||
"Save"};
|
||||
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) + UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), 12 * 8, 32},
|
||||
"Cancel",
|
||||
};
|
||||
};
|
||||
|
|
@ -784,11 +784,11 @@ class SetDisplayView : public View {
|
|||
"IPS Screen"};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
|
||||
"Save"};
|
||||
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(16) + UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
|
||||
"Cancel",
|
||||
};
|
||||
};
|
||||
|
|
@ -841,19 +841,19 @@ class SetTouchscreenThresholdView : public View {
|
|||
};
|
||||
|
||||
Button button_autodetect{
|
||||
{2 * 8, 13 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), 13 * 16, 12 * 8, 32},
|
||||
"Auto Detect"};
|
||||
Button button_reset{
|
||||
{16 * 8, 13 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) + UI_POS_WIDTH(8), 13 * 16, 12 * 8, 32},
|
||||
"Reset",
|
||||
};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), 16 * 16, 12 * 8, 32},
|
||||
"Save"};
|
||||
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) + UI_POS_WIDTH(8), 16 * 16, 12 * 8, 32},
|
||||
"Cancel",
|
||||
};
|
||||
|
||||
|
|
@ -876,14 +876,14 @@ class SetMenuColorView : public View {
|
|||
void paint_sample();
|
||||
|
||||
Labels labels{
|
||||
{{3 * 8, 1 * 16}, "Menu Button Color Scheme", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X_CENTER(25), 1 * 16}, "Menu Button Color Scheme", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, 8 * 16}, "Red Level:", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, 9 * 16}, "Green Level:", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, 10 * 16}, "Blue Level:", Theme::getInstance()->fg_light->foreground},
|
||||
};
|
||||
|
||||
NewButton button_sample{
|
||||
{8 * 8, 4 * 16, 14 * 8, 3 * 16},
|
||||
{UI_POS_X_CENTER(14), 4 * 16, 14 * 8, 3 * 16},
|
||||
"New Color",
|
||||
&bitmap_icon_brightness,
|
||||
};
|
||||
|
|
@ -913,16 +913,16 @@ class SetMenuColorView : public View {
|
|||
};
|
||||
|
||||
Button button_reset{
|
||||
{2 * 8, 13 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(7), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
|
||||
"Reset",
|
||||
};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
|
||||
"Save"};
|
||||
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) + UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
|
||||
"Cancel",
|
||||
};
|
||||
};
|
||||
|
|
@ -941,12 +941,8 @@ class SetThemeView : public View {
|
|||
{{1 * 8, 1 * 16}, "Select a theme.", Theme::getInstance()->fg_light->foreground},
|
||||
{{1 * 8, 2 * 16}, "Restart PP to fully apply!", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
"Save"};
|
||||
|
||||
OptionsField options{
|
||||
{0 * 8, 4 * 16},
|
||||
{UI_POS_X(0), 4 * 16},
|
||||
(size_t)(screen_width / 8),
|
||||
{
|
||||
{"Default - Grey", 0},
|
||||
|
|
@ -963,8 +959,12 @@ class SetThemeView : public View {
|
|||
23,
|
||||
"Set Menu color too"};
|
||||
|
||||
Button button_save{
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
|
||||
"Save"};
|
||||
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) + UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
|
||||
"Cancel",
|
||||
};
|
||||
};
|
||||
|
|
@ -988,10 +988,6 @@ class SetBatteryView : public View {
|
|||
|
||||
Labels labels2{{{1 * 8, 11 * 16}, "Reset IC's learned params.", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Button button_save{
|
||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||
"Save"};
|
||||
|
||||
Checkbox checkbox_overridebatt{
|
||||
{2 * 8, 4 * 16},
|
||||
23,
|
||||
|
|
@ -1003,12 +999,16 @@ class SetBatteryView : public View {
|
|||
"Charge hint"};
|
||||
|
||||
Button button_cancel{
|
||||
{16 * 8, 16 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) + UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
|
||||
"Cancel",
|
||||
};
|
||||
|
||||
Button button_save{
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
|
||||
"Save"};
|
||||
|
||||
Button button_reset{
|
||||
{2 * 8, 13 * 16, 12 * 8, 32},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(7), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
|
||||
"Reset",
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ class SigGenView : public View {
|
|||
{"Pulse CW 25%", 7}}};
|
||||
|
||||
TransmitterView tx_view{
|
||||
16 * 16,
|
||||
(int16_t)UI_POS_Y_BOTTOM(4),
|
||||
10000,
|
||||
12};
|
||||
|
||||
|
|
|
|||
|
|
@ -96,42 +96,42 @@ class SondeView : public View {
|
|||
Labels labels{
|
||||
{{4 * 8, 2 * 16}, "Type:", Theme::getInstance()->fg_light->foreground},
|
||||
{{6 * 8, 3 * 16}, "ID:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 4 * 16}, "DateTime:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 4 * 16}, "DateTime:", Theme::getInstance()->fg_light->foreground},
|
||||
|
||||
{{3 * 8, 5 * 16}, "Vbatt:", Theme::getInstance()->fg_light->foreground},
|
||||
{{3 * 8, 6 * 16}, "Frame:", Theme::getInstance()->fg_light->foreground},
|
||||
{{4 * 8, 7 * 16}, "Temp:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 8 * 16}, "Humidity:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 8 * 16}, "Humidity:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{0 * 8, 0 * 8},
|
||||
{UI_POS_X(0), 0 * 8},
|
||||
nav_};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{13 * 8, 0 * 16}};
|
||||
{13 * 8, UI_POS_Y(0)}};
|
||||
|
||||
LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
{15 * 8, UI_POS_Y(0)}};
|
||||
|
||||
VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
|
||||
RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4}};
|
||||
{21 * 8, 0, UI_POS_WIDTH_REMAINING(24), 4}};
|
||||
Channel channel{
|
||||
{21 * 8, 5, 6 * 8, 4},
|
||||
{21 * 8, 5, UI_POS_WIDTH_REMAINING(24), 4},
|
||||
};
|
||||
|
||||
AudioVolumeField field_volume{
|
||||
{screen_width - 2 * 8, 0 * 16}};
|
||||
{UI_POS_X_RIGHT(2), UI_POS_Y(0)}};
|
||||
|
||||
Checkbox check_log{
|
||||
{22 * 8, 8 * 16},
|
||||
{UI_POS_X_RIGHT(8), UI_POS_Y(8)},
|
||||
3,
|
||||
"Log"};
|
||||
|
||||
Checkbox check_crc{
|
||||
{22 * 8, 10 * 16},
|
||||
{UI_POS_X_RIGHT(8), UI_POS_Y(10)},
|
||||
3,
|
||||
"CRC"};
|
||||
|
||||
|
|
@ -169,11 +169,11 @@ class SondeView : public View {
|
|||
GeoPos::spd_unit::HIDDEN};
|
||||
|
||||
Button button_see_qr{
|
||||
{2 * 8, 15 * 16, 12 * 8, 3 * 16},
|
||||
{UI_POS_X_CENTER(12) - UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), 12 * 8, 3 * 16},
|
||||
"See QR"};
|
||||
|
||||
Button button_see_map{
|
||||
{16 * 8, 15 * 16, 12 * 8, 3 * 16},
|
||||
{UI_POS_X_CENTER(12) + UI_POS_WIDTH(8), UI_POS_Y_BOTTOM(4), 12 * 8, 3 * 16},
|
||||
"See on map"};
|
||||
|
||||
GeoMapView* geomap_view_{nullptr};
|
||||
|
|
|
|||
|
|
@ -262,17 +262,14 @@ void RecentEntriesTable<ui::SubGhzDRecentEntries>::draw(
|
|||
const Entry& entry,
|
||||
const Rect& target_rect,
|
||||
Painter& painter,
|
||||
const Style& style) {
|
||||
const Style& style,
|
||||
RecentEntriesColumns& columns) {
|
||||
std::string line{};
|
||||
line.reserve(30);
|
||||
|
||||
line = SubGhzDView::getSensorTypeName((FPROTO_SUBGHZD_SENSOR)entry.sensorType);
|
||||
line = line + " " + to_string_hex(entry.data << 32);
|
||||
if (line.length() < 19) {
|
||||
line += SubGhzDView::pad_string_with_spaces(19 - line.length());
|
||||
} else {
|
||||
line = truncate(line, 19);
|
||||
}
|
||||
line.resize(columns.at(0).second, ' ');
|
||||
std::string ageStr = to_string_dec_uint(entry.age);
|
||||
std::string bitsStr = to_string_dec_uint(entry.bits);
|
||||
line += SubGhzDView::pad_string_with_spaces(5 - bitsStr.length()) + bitsStr;
|
||||
|
|
|
|||
|
|
@ -122,18 +122,18 @@ class SubGhzDView : public View {
|
|||
SubGhzDRecentEntries recent{};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{13 * 8, 0 * 16}};
|
||||
{13 * 8, UI_POS_Y(0)}};
|
||||
LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
{15 * 8, UI_POS_Y(0)}};
|
||||
VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4}};
|
||||
{21 * 8, 0, UI_POS_WIDTH_REMAINING(24), 4}};
|
||||
Channel channel{
|
||||
{21 * 8, 5, 6 * 8, 4},
|
||||
{21 * 8, 5, UI_POS_WIDTH_REMAINING(24), 4},
|
||||
};
|
||||
RxFrequencyField field_frequency{
|
||||
{0 * 8, 0 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0)},
|
||||
nav_};
|
||||
|
||||
SignalToken signal_token_tick_second{};
|
||||
|
|
@ -152,8 +152,8 @@ class SubGhzDView : public View {
|
|||
|
||||
std::unique_ptr<SubGhzDLogger> logger{};
|
||||
|
||||
const RecentEntriesColumns columns{{
|
||||
{"Type", 19},
|
||||
RecentEntriesColumns columns{{
|
||||
{"Type", 0},
|
||||
{"Bits", 4},
|
||||
{"Age", 3},
|
||||
}};
|
||||
|
|
@ -191,16 +191,16 @@ class SubGhzDRecentEntryDetailView : public View {
|
|||
uint32_t cnt = SD_NO_CNT;
|
||||
uint32_t seed = 0;
|
||||
|
||||
Text text_type{{0 * 8, 1 * 16, 15 * 8, 16}, "?"};
|
||||
Text text_type{{UI_POS_X(0), 1 * 16, 15 * 8, 16}, "?"};
|
||||
Text text_id{{6 * 8, 2 * 16, 10 * 8, 16}, "?"};
|
||||
|
||||
Console console{
|
||||
{0, 4 * 16, screen_width, screen_height - (4 * 16) - 36}};
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 0 * 16}, "Type:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 2 * 16}, "Serial: ", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 3 * 16}, "Data:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), UI_POS_Y(0)}, "Type:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 2 * 16}, "Serial: ", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 3 * 16}, "Data:", Theme::getInstance()->fg_light->foreground},
|
||||
};
|
||||
|
||||
Button button_done{
|
||||
|
|
|
|||
|
|
@ -76,29 +76,29 @@ class TestView : public View {
|
|||
bool logging{false};
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 1 * 16}, "Data:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 1 * 16}, "Data:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{0 * 8, 0 * 8},
|
||||
{UI_POS_X(0), 0 * 8},
|
||||
nav_};
|
||||
RFAmpField field_rf_amp{
|
||||
{13 * 8, 0 * 16}};
|
||||
{13 * 8, UI_POS_Y(0)}};
|
||||
|
||||
LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
{15 * 8, UI_POS_Y(0)}};
|
||||
|
||||
VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
|
||||
RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4},
|
||||
};
|
||||
|
||||
Text text_debug_a{
|
||||
{0 * 8, 4 * 16, screen_width, 16},
|
||||
{UI_POS_X(0), 4 * 16, screen_width, 16},
|
||||
"..."};
|
||||
Text text_debug_b{
|
||||
{0 * 8, 5 * 16, screen_width, 16},
|
||||
{UI_POS_X(0), 5 * 16, screen_width, 16},
|
||||
"..."};
|
||||
|
||||
Button button_cal{
|
||||
|
|
|
|||
|
|
@ -427,7 +427,7 @@ void TextViewer::set_font_zoom(bool zoom) {
|
|||
/* TextEditorMenu ***************************************************/
|
||||
|
||||
TextEditorMenu::TextEditorMenu()
|
||||
: View{{7 * 4, 9 * 4, 25 * 8, 25 * 8}} {
|
||||
: View{{UI_POS_X_CENTER(25), 9 * 4, 25 * 8, 25 * 8}} {
|
||||
add_children(
|
||||
{
|
||||
&rect_frame,
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ class TextEditorMenu : public View {
|
|||
void hide_children(bool hidden);
|
||||
|
||||
Rectangle rect_frame{
|
||||
{0 * 8, 0 * 8, 23 * 8, 23 * 8},
|
||||
{UI_POS_X(0), 0 * 8, 23 * 8, 23 * 8},
|
||||
Theme::getInstance()->fg_dark->foreground};
|
||||
|
||||
NewButton button_home{
|
||||
|
|
@ -267,23 +267,23 @@ class TextEditorView : public View {
|
|||
|
||||
TextViewer viewer{
|
||||
/* 272 = screen_height - 16 (top bar) - 32 (bottom controls) */
|
||||
{0, 0, screen_width, 272}};
|
||||
{0, 0, screen_width, UI_POS_HEIGHT_REMAINING(4)}};
|
||||
|
||||
TextEditorMenu menu{};
|
||||
|
||||
NewButton button_menu{
|
||||
{26 * 8, 34 * 8, 4 * 8, 4 * 8},
|
||||
{UI_POS_X_RIGHT(4), UI_POS_Y_BOTTOM(3), UI_POS_WIDTH(4), UI_POS_HEIGHT(2)},
|
||||
{},
|
||||
&bitmap_icon_controls,
|
||||
Theme::getInstance()->bg_dark->background,
|
||||
/*vcenter*/ true};
|
||||
|
||||
Text text_position{
|
||||
{0 * 8, 34 * 8, 26 * 8, 2 * 8},
|
||||
{UI_POS_X(0), UI_POS_Y_BOTTOM(3), UI_POS_WIDTH_REMAINING(5), UI_POS_HEIGHT(1)},
|
||||
""};
|
||||
|
||||
Text text_size{
|
||||
{0 * 8, 36 * 8, 26 * 8, 2 * 8},
|
||||
{UI_POS_X(0), UI_POS_Y_BOTTOM(2), UI_POS_WIDTH_REMAINING(5), UI_POS_HEIGHT(1)},
|
||||
""};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -162,16 +162,16 @@ class TouchTunesView : public View {
|
|||
{{18 * 8 + 4, 18 * 8}, "V"},
|
||||
{{22 * 8, 18 * 8}, "F4"},
|
||||
|
||||
{{0 * 8, 5 * 8}, "1"},
|
||||
{{UI_POS_X(0), 5 * 8}, "1"},
|
||||
{{4 * 8, 5 * 8}, "2"},
|
||||
{{8 * 8, 5 * 8}, "3"},
|
||||
{{0 * 8, 10 * 8}, "4"},
|
||||
{{UI_POS_X(0), 10 * 8}, "4"},
|
||||
{{4 * 8, 10 * 8}, "5"},
|
||||
{{8 * 8, 10 * 8}, "6"},
|
||||
{{0 * 8, 15 * 8}, "7"},
|
||||
{{UI_POS_X(0), 15 * 8}, "7"},
|
||||
{{4 * 8, 15 * 8}, "8"},
|
||||
{{8 * 8, 15 * 8}, "9"},
|
||||
{{0 * 8, 20 * 8}, "*"},
|
||||
{{UI_POS_X(0), 20 * 8}, "*"},
|
||||
{{4 * 8, 20 * 8}, "0"},
|
||||
{{8 * 8, 20 * 8}, "#"},
|
||||
|
||||
|
|
|
|||
|
|
@ -270,16 +270,13 @@ void RecentEntriesTable<ui::WeatherRecentEntries>::draw(
|
|||
const Entry& entry,
|
||||
const Rect& target_rect,
|
||||
Painter& painter,
|
||||
const Style& style) {
|
||||
const Style& style,
|
||||
RecentEntriesColumns& columns) {
|
||||
std::string line{};
|
||||
line.reserve(30);
|
||||
|
||||
line = WeatherView::getWeatherSensorTypeName((FPROTO_WEATHER_SENSOR)entry.sensorType);
|
||||
if (line.length() < 10) {
|
||||
line += WeatherView::pad_string_with_spaces(10 - line.length());
|
||||
} else {
|
||||
line = truncate(line, 10);
|
||||
}
|
||||
line.resize(columns.at(0).second, ' ');
|
||||
|
||||
std::string temp = (weather_units_fahr ? to_string_decimal((entry.temp * 9 / 5) + 32, 1) : to_string_decimal(entry.temp, 1));
|
||||
std::string humStr = (entry.humidity != WS_NO_HUMIDITY) ? to_string_dec_uint(entry.humidity) + "%" : "-";
|
||||
|
|
|
|||
|
|
@ -134,28 +134,28 @@ class WeatherView : public View {
|
|||
WeatherRecentEntries recent{};
|
||||
|
||||
OptionsField options_temperature{
|
||||
{10 * 8, 0 * 16},
|
||||
{10 * 8, UI_POS_Y(0)},
|
||||
2,
|
||||
{{STR_DEGREES_C, 0},
|
||||
{STR_DEGREES_F, 1}}};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{13 * 8, 0 * 16}};
|
||||
{13 * 8, UI_POS_Y(0)}};
|
||||
LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
{15 * 8, UI_POS_Y(0)}};
|
||||
VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4}};
|
||||
{21 * 8, 0, UI_POS_WIDTH_REMAINING(24), 4}};
|
||||
Channel channel{
|
||||
{21 * 8, 5, 6 * 8, 4},
|
||||
{21 * 8, 5, UI_POS_WIDTH_REMAINING(24), 4},
|
||||
};
|
||||
|
||||
AudioVolumeField field_volume{
|
||||
{screen_width - 2 * 8, 0 * 16}};
|
||||
{UI_POS_X_RIGHT(2), UI_POS_Y(0)}};
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{0 * 8, 0 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0)},
|
||||
nav_};
|
||||
|
||||
SignalToken signal_token_tick_second{};
|
||||
|
|
@ -174,8 +174,8 @@ class WeatherView : public View {
|
|||
|
||||
std::unique_ptr<WeatherLogger> logger{};
|
||||
|
||||
const RecentEntriesColumns columns{{
|
||||
{"Type", 10},
|
||||
RecentEntriesColumns columns{{
|
||||
{"Type", 0},
|
||||
{"Temp", 5},
|
||||
{"Hum", 4},
|
||||
{"Ch", 3},
|
||||
|
|
@ -218,14 +218,14 @@ class WeatherRecentEntryDetailView : public View {
|
|||
Text text_age{{10 * 8, 7 * 16, 10 * 8, 16}, "?"};
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 0 * 16}, "Weather Station", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 1 * 16}, "Type:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 2 * 16}, "Id: ", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 3 * 16}, "Temp:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 4 * 16}, "Humidity:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 5 * 16}, "Channel:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 6 * 16}, "Battery:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 7 * 16}, "Age:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), UI_POS_Y(0)}, "Weather Station", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 1 * 16}, "Type:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 2 * 16}, "Id: ", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 3 * 16}, "Temp:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 4 * 16}, "Humidity:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 5 * 16}, "Channel:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 6 * 16}, "Battery:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 7 * 16}, "Age:", Theme::getInstance()->fg_light->foreground},
|
||||
};
|
||||
|
||||
Button button_done{
|
||||
|
|
|
|||
|
|
@ -67,18 +67,18 @@ class ACARSAppView : public View {
|
|||
uint32_t packet_counter{0};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{13 * 8, 0 * 16}};
|
||||
{13 * 8, UI_POS_Y(0)}};
|
||||
LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
{15 * 8, UI_POS_Y(0)}};
|
||||
VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4}};
|
||||
{UI_POS_X(21), 0, UI_POS_WIDTH_REMAINING(24), 4}};
|
||||
Channel channel{
|
||||
{21 * 8, 5, 6 * 8, 4}};
|
||||
{UI_POS_X(21), 5, UI_POS_WIDTH_REMAINING(24), 4}};
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{0 * 8, 0 * 8},
|
||||
{UI_POS_X(0), 0 * 8},
|
||||
nav_};
|
||||
Checkbox check_log{
|
||||
{16 * 8, 1 * 16},
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class ADSBPositionView : public OptionTabView {
|
|||
GeoPos::HIDDEN};
|
||||
|
||||
Button button_set_map{
|
||||
{8 * 8, 6 * 16, 14 * 8, 2 * 16},
|
||||
{UI_POS_X_CENTER(14), 6 * 16, 14 * 8, 2 * 16},
|
||||
"Set from map"};
|
||||
};
|
||||
|
||||
|
|
@ -244,7 +244,7 @@ class ADSBTxView : public View {
|
|||
"-"};
|
||||
|
||||
TransmitterView tx_view{
|
||||
16 * 16,
|
||||
(int16_t)UI_POS_Y_BOTTOM(4),
|
||||
1000000,
|
||||
0};
|
||||
|
||||
|
|
|
|||
|
|
@ -73,31 +73,31 @@ class AFSKRxView : public View {
|
|||
bool logging{false};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{13 * 8, 0 * 16}};
|
||||
{13 * 8, UI_POS_Y(0)}};
|
||||
LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
{15 * 8, UI_POS_Y(0)}};
|
||||
VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4}};
|
||||
{UI_POS_X(21), 0, UI_POS_WIDTH_REMAINING(24), 4}};
|
||||
Channel channel{
|
||||
{21 * 8, 5, 6 * 8, 4}};
|
||||
{UI_POS_X(21), 5, UI_POS_WIDTH_REMAINING(24), 4}};
|
||||
|
||||
AudioVolumeField field_volume{
|
||||
{screen_width - 2 * 8, 0 * 16}};
|
||||
{screen_width - 2 * 8, UI_POS_Y(0)}};
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{0 * 8, 0 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0)},
|
||||
nav_};
|
||||
|
||||
Checkbox check_log{
|
||||
{0 * 8, 1 * 16},
|
||||
{UI_POS_X(0), 1 * 16},
|
||||
3,
|
||||
LanguageHelper::currentMessages[LANG_LOG],
|
||||
false};
|
||||
|
||||
Text text_debug{
|
||||
{0 * 8, 12 + 2 * 16, screen_width, 16},
|
||||
{UI_POS_X(0), 12 + 2 * 16, screen_width, 16},
|
||||
LanguageHelper::currentMessages[LANG_DEBUG]};
|
||||
|
||||
Button button_modem_setup{
|
||||
|
|
|
|||
|
|
@ -58,8 +58,8 @@ class AnalogTvView : public View {
|
|||
app_settings::SettingsManager settings_{
|
||||
"rx_tv", app_settings::Mode::RX};
|
||||
|
||||
const Rect options_view_rect{0 * 8, 1 * 16, screen_width, 1 * 16};
|
||||
const Rect nbfm_view_rect{0 * 8, 1 * 16, 18 * 8, 1 * 16};
|
||||
const Rect options_view_rect{UI_POS_X(0), 1 * 16, screen_width, 1 * 16};
|
||||
const Rect nbfm_view_rect{UI_POS_X(0), 1 * 16, 18 * 8, 1 * 16};
|
||||
|
||||
RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4}};
|
||||
|
|
@ -71,17 +71,17 @@ class AnalogTvView : public View {
|
|||
{21 * 8, 10, 6 * 8, 4}};
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{5 * 8, 0 * 16},
|
||||
{5 * 8, UI_POS_Y(0)},
|
||||
nav_};
|
||||
|
||||
LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
{15 * 8, UI_POS_Y(0)}};
|
||||
|
||||
VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
|
||||
OptionsField options_modulation{
|
||||
{0 * 8, 0 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0)},
|
||||
4,
|
||||
{
|
||||
{"TV ", toUType(ReceiverModel::Mode::WidebandFMAudio)},
|
||||
|
|
@ -90,7 +90,7 @@ class AnalogTvView : public View {
|
|||
}};
|
||||
|
||||
AudioVolumeField field_volume{
|
||||
{27 * 8, 0 * 16}};
|
||||
{27 * 8, UI_POS_Y(0)}};
|
||||
|
||||
std::unique_ptr<Widget> options_widget{};
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ class WhipCalcView : public View {
|
|||
{0, 6 * 16, screen_width, 160}};
|
||||
|
||||
Button button_exit{
|
||||
{72, 17 * 16, 96, 32},
|
||||
{UI_POS_X_RIGHT(12), UI_POS_Y_BOTTOM(3), 96, 32},
|
||||
"Back"};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ AppManagerView::AppManagerView(NavigationView& nav)
|
|||
&button_set_cancel_autostart,
|
||||
&button_clean_autostart});
|
||||
|
||||
menu_view.set_parent_rect({0, 2 * 8, screen_width, 24 * 8});
|
||||
menu_view.set_parent_rect({0, 2 * 8, screen_width, UI_POS_HEIGHT_REMAINING(7)});
|
||||
|
||||
menu_view.on_highlight = [this]() {
|
||||
if (menu_view.highlighted_index() >= app_list_index) {
|
||||
|
|
|
|||
|
|
@ -43,28 +43,28 @@ class AppManagerView : public View {
|
|||
uint16_t app_list_index{0};
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 0 * 16}, "App list:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), UI_POS_Y(0)}, "App list:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
MenuView menu_view{};
|
||||
|
||||
Text text_app_info{
|
||||
{0, 27 * 8, screen_width, 16},
|
||||
{0, UI_POS_Y_BOTTOM(6), screen_width, UI_POS_HEIGHT(1)},
|
||||
"Highlight an app"};
|
||||
|
||||
Button button_hide_unhide{
|
||||
{0, 29 * 8, screen_width / 2 - 1, 32},
|
||||
{0, UI_POS_Y_BOTTOM(5), screen_width / 2 - 1, UI_POS_HEIGHT(2)},
|
||||
"Hide/Show"};
|
||||
|
||||
Button button_clean_hide{
|
||||
{screen_width / 2 + 2, 29 * 8, screen_width / 2 - 2, 32},
|
||||
{screen_width / 2 + 2, UI_POS_Y_BOTTOM(5), screen_width / 2 - 2, UI_POS_HEIGHT(2)},
|
||||
"Clean Hidden"};
|
||||
|
||||
Button button_set_cancel_autostart{
|
||||
{0, screen_height - 32 - 16, screen_width / 2 - 1, 32},
|
||||
{0, screen_height - 32 - 16, screen_width / 2 - 1, UI_POS_HEIGHT(2)},
|
||||
"Set Autostart"};
|
||||
|
||||
Button button_clean_autostart{
|
||||
{screen_width / 2 + 2, screen_height - 32 - 16, screen_width / 2 - 2, 32},
|
||||
{screen_width / 2 + 2, screen_height - 32 - 16, screen_width / 2 - 2, UI_POS_HEIGHT(2)},
|
||||
"Del Autostart"};
|
||||
|
||||
std::string get_app_info(uint16_t index, bool is_display_name);
|
||||
|
|
|
|||
|
|
@ -44,13 +44,13 @@ class AudioTestView : public View {
|
|||
bool beep{false};
|
||||
|
||||
Labels labels{
|
||||
{{7 * 8, 3 * 16}, "Audio Beep Test", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 6 * 16}, "Sample Rate (Hz):", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X_CENTER(16), 3 * 16}, "Audio Beep Test", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 6 * 16}, "Sample Rate (Hz):", Theme::getInstance()->fg_light->foreground},
|
||||
{{25 * 8, 7 * 16}, "Step:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 8 * 16}, "Frequency (Hz):", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 10 * 16}, "Duration (ms):", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 8 * 16}, "Frequency (Hz):", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 10 * 16}, "Duration (ms):", Theme::getInstance()->fg_light->foreground},
|
||||
{{25 * 8, 10 * 16}, "0=con", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 12 * 16}, "Volume:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 12 * 16}, "Volume:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
OptionsField options_sample_rate{
|
||||
{18 * 8, 6 * 16},
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
#include "bht.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
|
||||
namespace ui::external_app::bht_tx {
|
||||
|
||||
size_t gen_message_ep(uint8_t city_code, size_t family_code_ep, uint32_t relay_number, uint32_t relay_state) {
|
||||
size_t c;
|
||||
const encoder_def_t* um3750_def;
|
||||
|
|
@ -152,3 +154,5 @@ std::string ccir_to_ascii(uint8_t* ccir) {
|
|||
|
||||
return ascii;
|
||||
}
|
||||
|
||||
} // namespace ui::external_app::bht_tx
|
||||
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
using namespace encoders;
|
||||
|
||||
namespace ui::external_app::bht_tx {
|
||||
|
||||
#define XY_TONE_DURATION ((TONES_SAMPLERATE * 0.1) - 1) // 100ms
|
||||
#define XY_SILENCE (TONES_SAMPLERATE * 0.4) // 400ms
|
||||
#define XY_TONE_COUNT 20
|
||||
|
|
@ -47,3 +49,5 @@ size_t gen_message_ep(uint8_t city_code, size_t family_code_ep, uint32_t relay_s
|
|||
std::string gen_message_xy(const std::string& code);
|
||||
std::string gen_message_xy(size_t header_code_a, size_t header_code_b, size_t city_code, size_t family_code, bool subfamily_wc, size_t subfamily_code, bool id_wc, size_t receiver_code, size_t relay_state_A, size_t relay_state_B, size_t relay_state_C, size_t relay_state_D);
|
||||
std::string ccir_to_ascii(uint8_t* ccir);
|
||||
|
||||
} // namespace ui::external_app::bht_tx
|
||||
83
firmware/application/external/bht_tx/main.cpp
vendored
Normal file
83
firmware/application/external/bht_tx/main.cpp
vendored
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (C) 2024 EPIRB Decoder Implementation
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* 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 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "ui.hpp"
|
||||
#include "ui_bht_tx.hpp"
|
||||
#include "ui_navigation.hpp"
|
||||
#include "external_app.hpp"
|
||||
|
||||
namespace ui::external_app::bht_tx {
|
||||
void initialize_app(ui::NavigationView& nav) {
|
||||
nav.push<BHTView>();
|
||||
}
|
||||
} // namespace ui::external_app::bht_tx
|
||||
|
||||
extern "C" {
|
||||
|
||||
__attribute__((section(".external_app.app_bht_tx.application_information"), used)) application_information_t _application_information_bht_tx = {
|
||||
/*.memory_location = */ (uint8_t*)0x00000000,
|
||||
/*.externalAppEntry = */ ui::external_app::bht_tx::initialize_app,
|
||||
/*.header_version = */ CURRENT_HEADER_VERSION,
|
||||
/*.app_version = */ VERSION_MD5,
|
||||
|
||||
/*.app_name = */ "BHT TX",
|
||||
/*.bitmap_data = */ {
|
||||
0x00,
|
||||
0x00,
|
||||
0xE0,
|
||||
0x07,
|
||||
0xF8,
|
||||
0x08,
|
||||
0x9C,
|
||||
0x07,
|
||||
0x0C,
|
||||
0x00,
|
||||
0x8E,
|
||||
0x0A,
|
||||
0x46,
|
||||
0x12,
|
||||
0x26,
|
||||
0x22,
|
||||
0x06,
|
||||
0x02,
|
||||
0x06,
|
||||
0x00,
|
||||
0x06,
|
||||
0x00,
|
||||
0x06,
|
||||
0x00,
|
||||
0x06,
|
||||
0x00,
|
||||
0x06,
|
||||
0x00,
|
||||
0x06,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
},
|
||||
/*.icon_color = */ ui::Color::green().v,
|
||||
/*.menu_location = */ app_location_t::TX,
|
||||
/*.desired_menu_position = */ -1,
|
||||
|
||||
/*.m4_app_tag = portapack::spi_flash::image_tag_tones */ {'P', 'T', 'O', 'N'},
|
||||
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
|
||||
};
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
using namespace portapack;
|
||||
|
||||
namespace ui {
|
||||
namespace ui::external_app::bht_tx {
|
||||
|
||||
void BHTView::focus() {
|
||||
tx_view.focus();
|
||||
|
|
@ -40,8 +40,7 @@ void BHTView::start_tx() {
|
|||
transmitter_model.set_baseband_bandwidth(1750000);
|
||||
|
||||
if (target_system == XYLOS) {
|
||||
baseband::run_image(portapack::spi_flash::image_tag_tones);
|
||||
|
||||
baseband::run_prepared_image(portapack::memory::map::m4_code.base());
|
||||
view_xylos.generate_message();
|
||||
|
||||
// if (tx_mode == SINGLE) {
|
||||
|
|
@ -339,4 +338,4 @@ void XylosView::focus() {
|
|||
field_city.focus();
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
} // namespace ui::external_app::bht_tx
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
#include "radio_state.hpp"
|
||||
#include "portapack.hpp"
|
||||
|
||||
namespace ui {
|
||||
namespace ui::external_app::bht_tx {
|
||||
|
||||
class XylosView : public View {
|
||||
public:
|
||||
|
|
@ -218,11 +218,11 @@ class BHTView : public View {
|
|||
' '};
|
||||
|
||||
ProgressBar progressbar{
|
||||
{0 * 8, 29 * 8, screen_width, 16},
|
||||
{UI_POS_X(0), UI_POS_Y_BOTTOM(5), screen_width, 16},
|
||||
};
|
||||
|
||||
TransmitterView tx_view{
|
||||
16 * 16,
|
||||
(int16_t)UI_POS_Y_BOTTOM(4),
|
||||
10000,
|
||||
12};
|
||||
|
||||
|
|
@ -234,4 +234,4 @@ class BHTView : public View {
|
|||
}};
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
} // namespace ui::external_app::bht_tx
|
||||
|
|
@ -70,7 +70,7 @@ void BlackjackView::frame_sync() {
|
|||
}
|
||||
|
||||
void BlackjackView::clear_screen() {
|
||||
painter.fill_rectangle({0, 0, 240, 320}, Color::black());
|
||||
painter.fill_rectangle({0, 0, screen_width, screen_height}, Color::black());
|
||||
}
|
||||
|
||||
void BlackjackView::init_deck() {
|
||||
|
|
@ -265,24 +265,24 @@ void BlackjackView::draw_menu_static() {
|
|||
auto style_text = *ui::Theme::getInstance()->fg_light;
|
||||
auto style_rules = *ui::Theme::getInstance()->fg_cyan;
|
||||
|
||||
painter.draw_string({84, 20}, style_title, "BLACKJACK");
|
||||
painter.draw_string({UI_POS_X_CENTER(10), 20}, style_title, "BLACKJACK");
|
||||
|
||||
// Draw rules
|
||||
painter.draw_string({70, 55}, style_rules, "-- RULES --");
|
||||
painter.draw_string({61, 75}, style_text, "Get close to 21");
|
||||
painter.draw_string({61, 90}, style_text, "without going over");
|
||||
painter.draw_string({61, 110}, style_text, "Dealer hits on 16");
|
||||
painter.draw_string({61, 125}, style_text, "Dealer stays on 17");
|
||||
painter.draw_string({61, 145}, style_text, "Blackjack pays 1:1");
|
||||
painter.draw_string({UI_POS_X_CENTER(12), 55}, style_rules, "-- RULES --");
|
||||
painter.draw_string({UI_POS_X_CENTER(16), 75}, style_text, "Get close to 21");
|
||||
painter.draw_string({UI_POS_X_CENTER(19), 90}, style_text, "without going over");
|
||||
painter.draw_string({UI_POS_X_CENTER(18), 110}, style_text, "Dealer hits on 16");
|
||||
painter.draw_string({UI_POS_X_CENTER(19), 125}, style_text, "Dealer stays on 17");
|
||||
painter.draw_string({UI_POS_X_CENTER(19), 145}, style_text, "Blackjack pays 1:1");
|
||||
|
||||
// Controls
|
||||
painter.draw_string({65, 175}, style_rules, "-- CONTROLS --");
|
||||
painter.draw_string({61, 195}, style_text, "SELECT: Start/Hit");
|
||||
painter.draw_string({61, 210}, style_text, "LEFT: Stats");
|
||||
painter.draw_string({61, 225}, style_text, "RIGHT: Exit/Stay");
|
||||
painter.draw_string({UI_POS_X_CENTER(15), 175}, style_rules, "-- CONTROLS --");
|
||||
painter.draw_string({UI_POS_X_CENTER(18), 195}, style_text, "SELECT: Start/Hit");
|
||||
painter.draw_string({UI_POS_X_CENTER(12), 210}, style_text, "LEFT: Stats");
|
||||
painter.draw_string({UI_POS_X_CENTER(17), 225}, style_text, "RIGHT: Exit/Stay");
|
||||
|
||||
// Draw high score
|
||||
painter.draw_string({61, 250}, style_text, "High Score: $" + std::to_string(high_score));
|
||||
painter.draw_string({UI_POS_X_CENTER(17), 250}, style_text, "High Score: $" + std::to_string(high_score));
|
||||
}
|
||||
|
||||
void BlackjackView::draw_menu() {
|
||||
|
|
@ -293,10 +293,10 @@ void BlackjackView::draw_menu() {
|
|||
|
||||
if (blink_state) {
|
||||
auto style = *ui::Theme::getInstance()->fg_yellow;
|
||||
painter.draw_string({55, 280}, style, "* PRESS SELECT *");
|
||||
painter.draw_string({UI_POS_X_CENTER(17), 280}, style, "* PRESS SELECT *");
|
||||
} else {
|
||||
// Clear just the text area
|
||||
painter.fill_rectangle({55, 278, 130, 20}, Color::black());
|
||||
painter.fill_rectangle({UI_POS_X_CENTER(17), 278, 130, 20}, Color::black());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -308,27 +308,27 @@ void BlackjackView::draw_stats() {
|
|||
auto style_text = *ui::Theme::getInstance()->fg_light;
|
||||
auto style_value = *ui::Theme::getInstance()->fg_yellow;
|
||||
|
||||
painter.draw_string({75, 30}, style_title, "STATISTICS");
|
||||
painter.draw_string({UI_POS_X_CENTER(11), 30}, style_title, "STATISTICS");
|
||||
|
||||
painter.draw_string({30, 80}, style_text, "Wins:");
|
||||
painter.draw_string({150, 80}, style_value, std::to_string(wins));
|
||||
painter.draw_string({UI_POS_X_CENTER(5), 80}, style_value, std::to_string(wins));
|
||||
|
||||
painter.draw_string({30, 100}, style_text, "Losses:");
|
||||
painter.draw_string({150, 100}, style_value, std::to_string(losses));
|
||||
painter.draw_string({UI_POS_X_CENTER(5), 100}, style_value, std::to_string(losses));
|
||||
|
||||
// Win percentage
|
||||
uint32_t total = wins + losses;
|
||||
if (total > 0) {
|
||||
uint32_t win_pct = (wins * 100) / total;
|
||||
painter.draw_string({30, 120}, style_text, "Win %:");
|
||||
painter.draw_string({150, 120}, style_value, std::to_string(win_pct) + "%");
|
||||
painter.draw_string({UI_POS_X_CENTER(5), 120}, style_value, std::to_string(win_pct) + "%");
|
||||
}
|
||||
|
||||
painter.draw_string({30, 160}, style_text, "High Score:");
|
||||
painter.draw_string({150, 160}, style_value, "$" + std::to_string(high_score));
|
||||
painter.draw_string({UI_POS_X_CENTER(5), 160}, style_value, "$" + std::to_string(high_score));
|
||||
|
||||
painter.draw_string({30, 180}, style_text, "Cash:");
|
||||
painter.draw_string({150, 180}, style_value, "$" + std::to_string(cash));
|
||||
painter.draw_string({UI_POS_X_CENTER(5), 180}, style_value, "$" + std::to_string(cash));
|
||||
|
||||
painter.draw_string({40, 250}, style_text, "SELECT: Back");
|
||||
}
|
||||
|
|
@ -416,7 +416,7 @@ void BlackjackView::draw_game() {
|
|||
}
|
||||
|
||||
// Draw result
|
||||
painter.draw_string({60, 270}, *style_result, result);
|
||||
painter.draw_string({UI_POS_X_CENTER(result.length()), 270}, *style_result, result);
|
||||
|
||||
// Draw compact bet selector in top right area
|
||||
auto style_bet = *ui::Theme::getInstance()->fg_cyan;
|
||||
|
|
@ -620,8 +620,8 @@ void BlackjackView::draw_card(int x, int y, uint8_t card, bool hidden) {
|
|||
void BlackjackView::draw_hand(int x, int y, uint8_t* cards, uint8_t count, bool is_dealer) {
|
||||
// Calculate total width needed
|
||||
const int card_width = 60;
|
||||
const int overlap = 40; // Amount of overlap when cards need to fit
|
||||
const int max_width = 230 - x; // Available width on screen
|
||||
const int overlap = 40; // Amount of overlap when cards need to fit
|
||||
const int max_width = screen_width - 10 - x; // Available width on screen
|
||||
|
||||
int spacing;
|
||||
if (count == 1) {
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ class BlackjackView : public View {
|
|||
{"highscore"sv, &high_score}}};
|
||||
|
||||
Button dummy{
|
||||
{240, 0, 0, 0},
|
||||
{screen_width, 0, 0, 0},
|
||||
""};
|
||||
|
||||
MessageHandlerRegistration message_handler_frame_sync{
|
||||
|
|
|
|||
|
|
@ -104,10 +104,10 @@ class BLESpamView : public View {
|
|||
4'000'000 /* sampling rate */
|
||||
};
|
||||
TxFrequencyField field_frequency{
|
||||
{0 * 8, 0 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0)},
|
||||
nav_};
|
||||
TransmitterView2 tx_view{
|
||||
{11 * 8, 0 * 16},
|
||||
{11 * 8, UI_POS_Y(0)},
|
||||
/*short_ui*/ true};
|
||||
app_settings::SettingsManager settings_{
|
||||
"tx_blespam", app_settings::Mode::TX};
|
||||
|
|
@ -122,7 +122,7 @@ class BLESpamView : public View {
|
|||
{0, 70, screen_width, 220}};
|
||||
#endif
|
||||
OptionsField options_atkmode{
|
||||
{0 * 8, 2 * 8},
|
||||
{UI_POS_X(0), 2 * 8},
|
||||
10,
|
||||
{{"Android", 0},
|
||||
{"iOs", 1},
|
||||
|
|
|
|||
|
|
@ -333,11 +333,11 @@ void BreakoutView::show_menu() {
|
|||
auto style_blue = *ui::Theme::getInstance()->fg_blue;
|
||||
auto style_cyan = *ui::Theme::getInstance()->fg_cyan;
|
||||
|
||||
painter.draw_string({50, 40}, style_yellow, "*** BREAKOUT ***");
|
||||
painter.draw_string({20, 100}, style_blue, "========================");
|
||||
painter.draw_string({30, 130}, style_cyan, "ROTARY: MOVE PADDLE");
|
||||
painter.draw_string({30, 160}, style_cyan, "SELECT: START/LAUNCH");
|
||||
painter.draw_string({20, 190}, style_blue, "========================");
|
||||
painter.draw_string({UI_POS_X_CENTER(17), 40}, style_yellow, "*** BREAKOUT ***");
|
||||
painter.draw_string({UI_POS_X_CENTER(25), 100}, style_blue, "========================");
|
||||
painter.draw_string({UI_POS_X_CENTER(20), 130}, style_cyan, "ROTARY: MOVE PADDLE");
|
||||
painter.draw_string({UI_POS_X_CENTER(21), 160}, style_cyan, "SELECT: START/LAUNCH");
|
||||
painter.draw_string({UI_POS_X_CENTER(25), 190}, style_blue, "========================");
|
||||
}
|
||||
|
||||
auto style_red = *ui::Theme::getInstance()->fg_red;
|
||||
|
|
@ -346,10 +346,10 @@ void BreakoutView::show_menu() {
|
|||
menu_blink_counter = 0;
|
||||
menu_blink_state = !menu_blink_state;
|
||||
|
||||
painter.fill_rectangle({56, 228, 128, 20}, Color::black());
|
||||
painter.fill_rectangle({UI_POS_X_CENTER(17), 228, 128, 20}, Color::black());
|
||||
|
||||
if (menu_blink_state) {
|
||||
painter.draw_string({56, 230}, style_red, "* PRESS SELECT *");
|
||||
painter.draw_string({UI_POS_X_CENTER(17), 230}, style_red, "* PRESS SELECT *");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -362,8 +362,8 @@ void BreakoutView::show_game_over() {
|
|||
auto style_red = *ui::Theme::getInstance()->fg_red;
|
||||
auto style_yellow = *ui::Theme::getInstance()->fg_yellow;
|
||||
|
||||
painter.draw_string({90, 100}, style_red, "GAME OVER");
|
||||
painter.draw_string({50, 150}, style_yellow, "SCORE: " + std::to_string(score));
|
||||
painter.draw_string({UI_POS_X_CENTER(10), 100}, style_red, "GAME OVER");
|
||||
painter.draw_string({UI_POS_X_CENTER(11), 150}, style_yellow, "SCORE: " + std::to_string(score));
|
||||
}
|
||||
|
||||
auto style_green = *ui::Theme::getInstance()->fg_green;
|
||||
|
|
@ -372,10 +372,10 @@ void BreakoutView::show_game_over() {
|
|||
gameover_blink_counter = 0;
|
||||
gameover_blink_state = !gameover_blink_state;
|
||||
|
||||
painter.fill_rectangle({72, 198, 96, 20}, Color::black());
|
||||
painter.fill_rectangle({UI_POS_X_CENTER(13), 198, 96, 20}, Color::black());
|
||||
|
||||
if (gameover_blink_state) {
|
||||
painter.draw_string({72, 200}, style_green, "PRESS SELECT");
|
||||
painter.draw_string({UI_POS_X_CENTER(13), 200}, style_green, "PRESS SELECT");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,25 +48,25 @@ class CalculatorView : public View {
|
|||
private:
|
||||
NavigationView& nav_;
|
||||
|
||||
Button button_F{{0 * 8, 11 * 16, 6 * 8, 16 + 8}, "F"};
|
||||
Button button_7{{8 * 8, 11 * 16, 6 * 8, 16 + 8}, "7"};
|
||||
Button button_8{{16 * 8, 11 * 16, 6 * 8, 16 + 8}, "8"};
|
||||
Button button_9{{24 * 8, 11 * 16, 6 * 8, 16 + 8}, "9"};
|
||||
Button button_E{{0 * 8, 13 * 16, 6 * 8, 16 + 8}, "E"};
|
||||
Button button_4{{8 * 8, 13 * 16, 6 * 8, 16 + 8}, "4"};
|
||||
Button button_5{{16 * 8, 13 * 16, 6 * 8, 16 + 8}, "5"};
|
||||
Button button_6{{24 * 8, 13 * 16, 6 * 8, 16 + 8}, "6"};
|
||||
Button button_N{{0 * 8, 15 * 16, 6 * 8, 16 + 8}, "N"};
|
||||
Button button_1{{8 * 8, 15 * 16, 6 * 8, 16 + 8}, "1"};
|
||||
Button button_2{{16 * 8, 15 * 16, 6 * 8, 16 + 8}, "2"};
|
||||
Button button_3{{24 * 8, 15 * 16, 6 * 8, 16 + 8}, "3"};
|
||||
Button button_C{{0 * 8, 17 * 16, 6 * 8, 16 + 8}, "C"};
|
||||
Button button_0{{8 * 8, 17 * 16, 6 * 8, 16 + 8}, "0"};
|
||||
Button button_P{{16 * 8, 17 * 16, 6 * 8, 16 + 8}, "."};
|
||||
Button button_D{{24 * 8, 17 * 16, 6 * 8, 16 + 8}, "D"};
|
||||
Button button_F{{UI_POS_X_TABLE(4, 0), UI_POS_Y_BOTTOM(9), UI_POS_WIDTH(6), UI_POS_HEIGHT(1.5)}, "F"};
|
||||
Button button_7{{UI_POS_X_TABLE(4, 1), UI_POS_Y_BOTTOM(9), UI_POS_WIDTH(6), UI_POS_HEIGHT(1.5)}, "7"};
|
||||
Button button_8{{UI_POS_X_TABLE(4, 2), UI_POS_Y_BOTTOM(9), UI_POS_WIDTH(6), UI_POS_HEIGHT(1.5)}, "8"};
|
||||
Button button_9{{UI_POS_X_TABLE(4, 3), UI_POS_Y_BOTTOM(9), UI_POS_WIDTH(6), UI_POS_HEIGHT(1.5)}, "9"};
|
||||
Button button_E{{UI_POS_X_TABLE(4, 0), UI_POS_Y_BOTTOM(7), UI_POS_WIDTH(6), UI_POS_HEIGHT(1.5)}, "E"};
|
||||
Button button_4{{UI_POS_X_TABLE(4, 1), UI_POS_Y_BOTTOM(7), UI_POS_WIDTH(6), UI_POS_HEIGHT(1.5)}, "4"};
|
||||
Button button_5{{UI_POS_X_TABLE(4, 2), UI_POS_Y_BOTTOM(7), UI_POS_WIDTH(6), UI_POS_HEIGHT(1.5)}, "5"};
|
||||
Button button_6{{UI_POS_X_TABLE(4, 3), UI_POS_Y_BOTTOM(7), UI_POS_WIDTH(6), UI_POS_HEIGHT(1.5)}, "6"};
|
||||
Button button_N{{UI_POS_X_TABLE(4, 0), UI_POS_Y_BOTTOM(5), UI_POS_WIDTH(6), UI_POS_HEIGHT(1.5)}, "N"};
|
||||
Button button_1{{UI_POS_X_TABLE(4, 1), UI_POS_Y_BOTTOM(5), UI_POS_WIDTH(6), UI_POS_HEIGHT(1.5)}, "1"};
|
||||
Button button_2{{UI_POS_X_TABLE(4, 2), UI_POS_Y_BOTTOM(5), UI_POS_WIDTH(6), UI_POS_HEIGHT(1.5)}, "2"};
|
||||
Button button_3{{UI_POS_X_TABLE(4, 3), UI_POS_Y_BOTTOM(5), UI_POS_WIDTH(6), UI_POS_HEIGHT(1.5)}, "3"};
|
||||
Button button_C{{UI_POS_X_TABLE(4, 0), UI_POS_Y_BOTTOM(3), UI_POS_WIDTH(6), UI_POS_HEIGHT(1.5)}, "C"};
|
||||
Button button_0{{UI_POS_X_TABLE(4, 1), UI_POS_Y_BOTTOM(3), UI_POS_WIDTH(6), UI_POS_HEIGHT(1.5)}, "0"};
|
||||
Button button_P{{UI_POS_X_TABLE(4, 2), UI_POS_Y_BOTTOM(3), UI_POS_WIDTH(6), UI_POS_HEIGHT(1.5)}, "."};
|
||||
Button button_D{{UI_POS_X_TABLE(4, 3), UI_POS_Y_BOTTOM(3), UI_POS_WIDTH(6), UI_POS_HEIGHT(1.5)}, "D"};
|
||||
|
||||
Console console{
|
||||
{0 * 8, 0 * 16, screen_width, 10 * 16}};
|
||||
{UI_POS_X(0), UI_POS_Y(0), screen_width, UI_POS_HEIGHT_REMAINING(10)}};
|
||||
|
||||
void on_button_press(uint8_t button);
|
||||
void update_button_labels();
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ class CoasterPagerView : public View {
|
|||
""};
|
||||
|
||||
TransmitterView tx_view{
|
||||
16 * 16,
|
||||
(int16_t)UI_POS_Y_BOTTOM(4),
|
||||
10000,
|
||||
12};
|
||||
|
||||
|
|
|
|||
|
|
@ -53,38 +53,38 @@ class CVSSpamView : public View {
|
|||
std::vector<std::filesystem::path> file_list{};
|
||||
|
||||
MenuView menu_view{
|
||||
{0, 0, screen_width, 180},
|
||||
{0, 0, screen_width, UI_POS_HEIGHT_REMAINING(12)},
|
||||
true};
|
||||
|
||||
Text text_empty{
|
||||
{7 * 8, 12 * 8, 16 * 8, 16},
|
||||
{UI_POS_X_CENTER(16), 12 * 8, UI_POS_WIDTH(16), UI_POS_HEIGHT(1)},
|
||||
"Empty directory!"};
|
||||
|
||||
Button button_prev_page{
|
||||
{0, 180, 50, 32},
|
||||
{0, UI_POS_Y_BOTTOM(10), UI_POS_WIDTH(4), UI_POS_HEIGHT(2)},
|
||||
"<"};
|
||||
|
||||
Button button_next_page{
|
||||
{190, 180, 50, 32},
|
||||
{UI_POS_X_RIGHT(3), UI_POS_Y_BOTTOM(10), UI_POS_WIDTH(4), UI_POS_HEIGHT(2)},
|
||||
">"};
|
||||
|
||||
Text page_info{
|
||||
{95, 188, 50, 16}};
|
||||
{UI_POS_X_CENTER(7), UI_POS_Y_BOTTOM(9.5), UI_POS_WIDTH(7), UI_POS_HEIGHT(1)}};
|
||||
|
||||
Button button_send{
|
||||
{0, 212, 75, 36},
|
||||
{0, UI_POS_Y_BOTTOM(8), UI_POS_WIDTH(9), UI_POS_HEIGHT(2)},
|
||||
"CALL"};
|
||||
|
||||
Button button_chaos{
|
||||
{82, 212, 75, 36},
|
||||
{UI_POS_X_CENTER(9), UI_POS_Y_BOTTOM(8), UI_POS_WIDTH(9), UI_POS_HEIGHT(2)},
|
||||
"CHAOS"};
|
||||
|
||||
Button button_stop{
|
||||
{165, 212, 75, 36},
|
||||
{UI_POS_X_RIGHT(9), UI_POS_Y_BOTTOM(8), UI_POS_WIDTH(9), UI_POS_HEIGHT(2)},
|
||||
LanguageHelper::currentMessages[LANG_STOP]};
|
||||
|
||||
ProgressBar progressbar{
|
||||
{0, 256, screen_width, 44}};
|
||||
{0, UI_POS_Y_BOTTOM(6), screen_width, UI_POS_HEIGHT(5)}};
|
||||
|
||||
MessageHandlerRegistration message_handler_fifo_signal{
|
||||
Message::ID::RequestSignal,
|
||||
|
|
|
|||
|
|
@ -44,11 +44,11 @@ class DebugDumpView : public View {
|
|||
NavigationView& nav_;
|
||||
|
||||
Text dump_output{
|
||||
{0 * 8, 19 * 8, screen_width, 16},
|
||||
{UI_POS_X(0), 19 * 8, screen_width, 16},
|
||||
""};
|
||||
|
||||
Button button_exit{
|
||||
{22 * 8, 34 * 8, 8 * 8, 32},
|
||||
{UI_POS_X_CENTER(8), UI_POS_Y_BOTTOM(4), 8 * 8, 32},
|
||||
"Exit"};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,9 @@ class DetectorRxView : public View {
|
|||
}};
|
||||
|
||||
Labels labels{
|
||||
{{UI_POS_X(0), UI_POS_Y(0)}, "LNA: VGA: AMP: VOL: ", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), UI_POS_Y(0)}, "LNA: VGA: AMP: ", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X_RIGHT(6), UI_POS_Y(0)}, "VOL: ", Theme::getInstance()->fg_light->foreground},
|
||||
};
|
||||
|
||||
LNAGainField field_lna{
|
||||
{UI_POS_X(4), UI_POS_Y(0)}};
|
||||
|
|
@ -89,7 +91,7 @@ class DetectorRxView : public View {
|
|||
{UI_POS_X(18), UI_POS_Y(0)}};
|
||||
|
||||
AudioVolumeField field_volume{
|
||||
{UI_POS_X(24), UI_POS_Y(0)}};
|
||||
{UI_POS_X_RIGHT(2), UI_POS_Y(0)}};
|
||||
|
||||
OptionsField field_mode{
|
||||
{UI_POS_X(0), UI_POS_Y(1)},
|
||||
|
|
|
|||
|
|
@ -178,12 +178,12 @@ void DinoGameView::show_menu() {
|
|||
auto style_title = *ui::Theme::getInstance()->fg_light;
|
||||
|
||||
// Draw title
|
||||
painter.draw_string({80, 60}, style_title, "DINO GAME");
|
||||
painter.draw_string({UI_POS_X_CENTER(10), 60}, style_title, "DINO GAME");
|
||||
|
||||
// Draw instructions
|
||||
painter.draw_string({45, 130}, style, "SELECT: Jump/Start");
|
||||
painter.draw_string({65, 150}, style, "DOWN: Duck");
|
||||
painter.draw_string({50, 170}, style, "Avoid obstacles!");
|
||||
painter.draw_string({UI_POS_X_CENTER(19), 130}, style, "SELECT: Jump/Start");
|
||||
painter.draw_string({UI_POS_X_CENTER(11), 150}, style, "DOWN: Duck");
|
||||
painter.draw_string({UI_POS_X_CENTER(17), 170}, style, "Avoid obstacles!");
|
||||
|
||||
// Draw high score
|
||||
draw_high_score();
|
||||
|
|
@ -209,9 +209,9 @@ void DinoGameView::show_menu() {
|
|||
blink_counter = 0;
|
||||
blink_state = !blink_state;
|
||||
|
||||
painter.fill_rectangle({55, 258, 130, 20}, Color::black());
|
||||
painter.fill_rectangle({UI_POS_X_CENTER(17), 258, 130, 20}, Color::black());
|
||||
if (blink_state) {
|
||||
painter.draw_string({55, 260}, style_prompt, "* PRESS SELECT *");
|
||||
painter.draw_string({UI_POS_X_CENTER(17), 260}, style_prompt, "* PRESS SELECT *");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -234,19 +234,19 @@ void DinoGameView::show_game_over() {
|
|||
auto style_score = *ui::Theme::getInstance()->fg_medium;
|
||||
|
||||
// Game over text
|
||||
painter.draw_string({85, 70}, style, "GAME OVER");
|
||||
painter.draw_string({UI_POS_X_CENTER(10), 70}, style, "GAME OVER");
|
||||
|
||||
// Show final score
|
||||
std::string score_text = "SCORE: " + score_to_string(score);
|
||||
int score_x = (240 - score_text.length() * 8) / 2;
|
||||
int score_x = (screen_width - score_text.length() * 8) / 2;
|
||||
painter.draw_string({score_x, 90}, style_score, score_text);
|
||||
|
||||
painter.draw_string({65, 110}, style, "SELECT TO RETRY");
|
||||
painter.draw_string({UI_POS_X_CENTER(16), 110}, style, "SELECT TO RETRY");
|
||||
|
||||
// Update high score
|
||||
if (score > highScore) {
|
||||
highScore = score;
|
||||
painter.draw_string({55, 130}, style, "NEW HIGH SCORE!");
|
||||
painter.draw_string({UI_POS_X_CENTER(16), 130}, style, "NEW HIGH SCORE!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -743,8 +743,8 @@ void DinoGameView::draw_current_score() {
|
|||
|
||||
void DinoGameView::draw_high_score() {
|
||||
auto style = *ui::Theme::getInstance()->fg_light;
|
||||
painter.fill_rectangle({152, 28, 100, 14}, Color::black());
|
||||
painter.draw_string({152, 30}, style, "HI " + score_to_string(highScore));
|
||||
painter.fill_rectangle({UI_POS_X_RIGHT(9), 28, UI_POS_WIDTH(9), 18}, Color::black());
|
||||
painter.draw_string({UI_POS_X_RIGHT(9), 30}, style, "HI " + score_to_string(highScore));
|
||||
}
|
||||
|
||||
void DinoGameView::jump() {
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ class DinoGameView : public View {
|
|||
bool easy_mode = false;
|
||||
|
||||
Button button_difficulty{
|
||||
{70, 195, 100, 20},
|
||||
{UI_POS_X_CENTER(13), 195, 13 * 8, 20},
|
||||
"Mode: HARD"};
|
||||
|
||||
app_settings::SettingsManager settings_{
|
||||
|
|
|
|||
|
|
@ -197,11 +197,11 @@ class EPIRBAppView : public ui::View {
|
|||
static constexpr auto header_height = 4 * 16;
|
||||
|
||||
ui::Text label_frequency{
|
||||
{0 * 8, 0 * 16, 4 * 8, 1 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0), 4 * 8, 1 * 16},
|
||||
"Freq"};
|
||||
|
||||
ui::OptionsField options_frequency{
|
||||
{5 * 8, 0 * 16},
|
||||
{5 * 8, UI_POS_Y(0)},
|
||||
7,
|
||||
{
|
||||
{"406.028", 406028000},
|
||||
|
|
@ -212,26 +212,26 @@ class EPIRBAppView : public ui::View {
|
|||
}};
|
||||
|
||||
ui::RFAmpField field_rf_amp{
|
||||
{13 * 8, 0 * 16}};
|
||||
{13 * 8, UI_POS_Y(0)}};
|
||||
|
||||
ui::LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
{15 * 8, UI_POS_Y(0)}};
|
||||
|
||||
ui::VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
|
||||
ui::RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4}};
|
||||
|
||||
ui::AudioVolumeField field_volume{
|
||||
{screen_width - 2 * 8, 0 * 16}};
|
||||
{UI_POS_X(21), 0, UI_POS_WIDTH_REMAINING(24), 4}};
|
||||
|
||||
ui::Channel channel{
|
||||
{21 * 8, 5, 6 * 8, 4}};
|
||||
{UI_POS_X(21), 5, UI_POS_WIDTH_REMAINING(24), 4}};
|
||||
|
||||
ui::AudioVolumeField field_volume{
|
||||
{screen_width - 2 * 8, UI_POS_Y(0)}};
|
||||
|
||||
// Status display
|
||||
ui::Text label_status{
|
||||
{0 * 8, 1 * 16, 15 * 8, 1 * 16},
|
||||
{UI_POS_X(0), 1 * 16, 15 * 8, 1 * 16},
|
||||
"Listening..."};
|
||||
|
||||
ui::Text label_beacons_count{
|
||||
|
|
@ -239,12 +239,12 @@ class EPIRBAppView : public ui::View {
|
|||
"Beacons: 0"};
|
||||
|
||||
ui::Text label_packet_stats{
|
||||
{0 * 8, 3 * 16, 29 * 8, 1 * 16},
|
||||
{UI_POS_X(0), 3 * 16, 29 * 8, 1 * 16},
|
||||
""};
|
||||
|
||||
// Latest beacon info display
|
||||
ui::Text label_latest{
|
||||
{0 * 8, 2 * 16, 8 * 8, 1 * 16},
|
||||
{UI_POS_X(0), 2 * 16, 8 * 8, 1 * 16},
|
||||
"Latest:"};
|
||||
|
||||
ui::Text text_latest_info{
|
||||
|
|
|
|||
|
|
@ -175,8 +175,11 @@ void RecentEntriesTable<ui::external_app::ert_app::ERTRecentEntries>::draw(
|
|||
const Entry& entry,
|
||||
const Rect& target_rect,
|
||||
Painter& painter,
|
||||
const Style& style) {
|
||||
std::string line = ert::format::id(entry.id) + " " + ert::format::commodity_type(entry.commodity_type) + " " + ert::format::consumption(entry.last_consumption) + " ";
|
||||
const Style& style,
|
||||
RecentEntriesColumns& columns) {
|
||||
std::string lid = ert::format::id(entry.id);
|
||||
lid.resize(columns.at(0).second, ' ');
|
||||
std::string line = lid + " " + ert::format::commodity_type(entry.commodity_type) + " " + ert::format::consumption(entry.last_consumption) + " ";
|
||||
|
||||
line += (entry.packet_type == ert::Packet::Type::SCM) ? ert::format::tamper_flags_scm(entry.last_tamper_flags) : ert::format::tamper_flags(entry.last_tamper_flags);
|
||||
line += (entry.received_count > 99) ? " ++" : to_string_dec_uint(entry.received_count, 3);
|
||||
|
|
|
|||
16
firmware/application/external/ert/ert_app.hpp
vendored
16
firmware/application/external/ert/ert_app.hpp
vendored
|
|
@ -136,8 +136,8 @@ class ERTAppView : public View {
|
|||
app_settings::SettingsManager settings_{
|
||||
"rx_ert", app_settings::Mode::RX};
|
||||
|
||||
const RecentEntriesColumns columns{{
|
||||
{"ID", 10},
|
||||
RecentEntriesColumns columns{{
|
||||
{"ID", 0},
|
||||
{"Ty", 2},
|
||||
{"Consumpt", 8},
|
||||
{"Tamp", 4},
|
||||
|
|
@ -148,24 +148,24 @@ class ERTAppView : public View {
|
|||
static constexpr auto header_height = 1 * 16;
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{0 * 8, 0 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0)},
|
||||
nav_};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{13 * 8, 0 * 16}};
|
||||
{13 * 8, UI_POS_Y(0)}};
|
||||
|
||||
LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
{15 * 8, UI_POS_Y(0)}};
|
||||
|
||||
VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
|
||||
RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4},
|
||||
{UI_POS_X(21), 0, UI_POS_WIDTH_REMAINING(24), 4},
|
||||
};
|
||||
|
||||
AudioVolumeField field_volume{
|
||||
{screen_width - 2 * 8, 0 * 16}};
|
||||
{screen_width - 2 * 8, UI_POS_Y(0)}};
|
||||
|
||||
MessageHandlerRegistration message_handler_packet{
|
||||
Message::ID::ERTPacket,
|
||||
|
|
|
|||
6
firmware/application/external/external.cmake
vendored
6
firmware/application/external/external.cmake
vendored
|
|
@ -249,6 +249,11 @@ set(EXTCPPSRC
|
|||
#game2048
|
||||
external/game2048/main.cpp
|
||||
external/game2048/ui_game2048.cpp
|
||||
|
||||
#bht_tx
|
||||
external/bht_tx/main.cpp
|
||||
external/bht_tx/ui_bht_tx.cpp
|
||||
external/bht_tx/bht.cpp
|
||||
)
|
||||
|
||||
set(EXTAPPLIST
|
||||
|
|
@ -312,4 +317,5 @@ set(EXTAPPLIST
|
|||
epirb_rx
|
||||
soundboard
|
||||
game2048
|
||||
bht_tx
|
||||
)
|
||||
|
|
|
|||
9
firmware/application/external/external.ld
vendored
9
firmware/application/external/external.ld
vendored
|
|
@ -83,6 +83,7 @@ MEMORY
|
|||
ram_external_app_epirb_rx (rwx) : org = 0xADEA0000, len = 32k
|
||||
ram_external_app_soundboard (rwx) : org = 0xADEB0000, len = 32k
|
||||
ram_external_app_game2048 (rwx) : org = 0xADEC0000, len = 32k
|
||||
ram_external_app_bht_tx (rwx) : org = 0xADED0000, len = 32k
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -449,5 +450,13 @@ SECTIONS
|
|||
*(*ui*external_app*game2048*);
|
||||
} > ram_external_app_game2048
|
||||
|
||||
|
||||
.external_app_bht_tx : ALIGN(4) SUBALIGN(4)
|
||||
{
|
||||
KEEP(*(.external_app.app_bht_tx.application_information));
|
||||
*(*ui*external_app*bht_tx*);
|
||||
} > ram_external_app_bht_tx
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,16 +56,16 @@ class ExtSensorsView : public View {
|
|||
uint16_t prev_scan_int = 0;
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 3 * 16}, "GPS:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 5 * 16}, "ORI:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 7 * 16}, "ENV:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 3 * 16}, "GPS:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 5 * 16}, "ORI:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 7 * 16}, "ENV:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
Text text_info{{0 * 8, 0 * 8, screen_width, 16 * 1}, "Connect a compatible module..."};
|
||||
Text text_gps{{5 * 8, 3 * 16, 24 * 8, 16}, "-"};
|
||||
Text text_orientation{{5 * 8, 5 * 16, 24 * 8, 16}, "-"};
|
||||
Text text_envl1{{5 * 8, 7 * 16, 24 * 8, 16}, "-"};
|
||||
Text text_envl2{{1 * 8, 9 * 16, 24 * 8, 16}, "-"};
|
||||
Text text_envl3{{1 * 8, 11 * 16, 24 * 8, 16}, "-"};
|
||||
Text text_info{{UI_POS_X(0), 0 * 8, screen_width, 16 * 1}, "Connect a compatible module..."};
|
||||
Text text_gps{{5 * 8, 3 * 16, UI_POS_WIDTH_REMAINING(6), UI_POS_HEIGHT(1)}, "-"};
|
||||
Text text_orientation{{5 * 8, 5 * 16, UI_POS_WIDTH_REMAINING(6), UI_POS_HEIGHT(1)}, "-"};
|
||||
Text text_envl1{{5 * 8, 7 * 16, UI_POS_WIDTH_REMAINING(6), UI_POS_HEIGHT(1)}, "-"};
|
||||
Text text_envl2{{1 * 8, 9 * 16, UI_POS_WIDTH_REMAINING(6), UI_POS_HEIGHT(1)}, "-"};
|
||||
Text text_envl3{{1 * 8, 11 * 16, UI_POS_WIDTH_REMAINING(6), UI_POS_HEIGHT(1)}, "-"};
|
||||
Console console{
|
||||
{1, 13 * 16, screen_width - 1, screen_height - 13 * 16}};
|
||||
|
||||
|
|
|
|||
|
|
@ -49,10 +49,10 @@ class FlipperTxView : public View {
|
|||
};
|
||||
|
||||
TxFrequencyField field_frequency{
|
||||
{0 * 8, 0 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0)},
|
||||
nav_};
|
||||
TransmitterView2 tx_view{
|
||||
{11 * 8, 0 * 16},
|
||||
{11 * 8, UI_POS_Y(0)},
|
||||
/*short_ui*/ true};
|
||||
|
||||
app_settings::SettingsManager settings_{
|
||||
|
|
|
|||
|
|
@ -121,18 +121,18 @@ class FmRadioView : public View {
|
|||
{"theme"sv, ¤t_theme}}};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{13 * 8, 0 * 16}};
|
||||
{13 * 8, UI_POS_Y(0)}};
|
||||
LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
{15 * 8, UI_POS_Y(0)}};
|
||||
VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4}};
|
||||
{UI_POS_X(21), 0, UI_POS_WIDTH_REMAINING(24), 4}};
|
||||
AudioVolumeField field_volume{
|
||||
{screen_width - 2 * 8, 0 * 16}};
|
||||
{screen_width - 2 * 8, UI_POS_Y(0)}};
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{0 * 8, 0 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0)},
|
||||
nav_};
|
||||
|
||||
OptionsField field_bw{
|
||||
|
|
@ -171,16 +171,16 @@ class FmRadioView : public View {
|
|||
|
||||
GraphEq gr{{2, FMR_BTNGRID_TOP, UI_POS_MAXWIDTH - 4, UI_POS_MAXHEIGHT - FMR_BTNGRID_TOP}, true};
|
||||
|
||||
Button btn_fav_0{{2, FMR_BTNGRID_TOP + 0 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_1{{2 + 15 * 8, FMR_BTNGRID_TOP + 0 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_2{{2, FMR_BTNGRID_TOP + 1 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_3{{2 + 15 * 8, FMR_BTNGRID_TOP + 1 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_4{{2, FMR_BTNGRID_TOP + 2 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_5{{2 + 15 * 8, FMR_BTNGRID_TOP + 2 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_6{{2, FMR_BTNGRID_TOP + 3 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_7{{2 + 15 * 8, FMR_BTNGRID_TOP + 3 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_8{{2, FMR_BTNGRID_TOP + 4 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_9{{2 + 15 * 8, FMR_BTNGRID_TOP + 4 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_0{{UI_POS_X_CENTER(10) - UI_POS_WIDTH(8), FMR_BTNGRID_TOP + 0 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_1{{UI_POS_X_CENTER(10) + UI_POS_WIDTH(8), FMR_BTNGRID_TOP + 0 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_2{{UI_POS_X_CENTER(10) - UI_POS_WIDTH(8), FMR_BTNGRID_TOP + 1 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_3{{UI_POS_X_CENTER(10) + UI_POS_WIDTH(8), FMR_BTNGRID_TOP + 1 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_4{{UI_POS_X_CENTER(10) - UI_POS_WIDTH(8), FMR_BTNGRID_TOP + 2 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_5{{UI_POS_X_CENTER(10) + UI_POS_WIDTH(8), FMR_BTNGRID_TOP + 2 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_6{{UI_POS_X_CENTER(10) - UI_POS_WIDTH(8), FMR_BTNGRID_TOP + 3 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_7{{UI_POS_X_CENTER(10) + UI_POS_WIDTH(8), FMR_BTNGRID_TOP + 3 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_8{{UI_POS_X_CENTER(10) - UI_POS_WIDTH(8), FMR_BTNGRID_TOP + 4 * 34, 10 * 8, 28}, "---"};
|
||||
Button btn_fav_9{{UI_POS_X_CENTER(10) + UI_POS_WIDTH(8), FMR_BTNGRID_TOP + 4 * 34, 10 * 8, 28}, "---"};
|
||||
|
||||
Button btn_fav_save{{2, FMR_BTNGRID_TOP + 6 * 34, 7 * 8, 1 * 28}, "Save"};
|
||||
bool save_fav = false;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class DebugFontsView : public View {
|
|||
void paint_zoomed_text(Painter& painter);
|
||||
|
||||
NumberField field_cursor{
|
||||
{0 * 8, 0 * 8},
|
||||
{UI_POS_X(0), 0 * 8},
|
||||
4,
|
||||
{0, 1000},
|
||||
1,
|
||||
|
|
@ -61,7 +61,7 @@ class DebugFontsView : public View {
|
|||
1,
|
||||
' '};
|
||||
Text text_address{
|
||||
{screen_width / 2, 0 * 16, screen_width / 2, 16},
|
||||
{screen_width / 2, UI_POS_Y(0), screen_width / 2, 16},
|
||||
"0x20",
|
||||
};
|
||||
NavigationView& nav_;
|
||||
|
|
|
|||
|
|
@ -54,23 +54,23 @@ class FoxhuntRxView : public View {
|
|||
"rx_foxhunt", app_settings::Mode::RX};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{13 * 8, 0 * 16}};
|
||||
{13 * 8, UI_POS_Y(0)}};
|
||||
LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
{15 * 8, UI_POS_Y(0)}};
|
||||
VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4}};
|
||||
{UI_POS_X(21), 0, UI_POS_WIDTH_REMAINING(24), 4}};
|
||||
AudioVolumeField field_volume{
|
||||
{screen_width - 2 * 8, 0 * 16}};
|
||||
{screen_width - 2 * 8, UI_POS_Y(0)}};
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{0 * 8, 0 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0)},
|
||||
nav_};
|
||||
|
||||
// Power: -XXX db
|
||||
Text freq_stats_db{
|
||||
{0 * 8, 2 * 16 + 4, 14 * 8, 14},
|
||||
{UI_POS_X(0), 2 * 16 + 4, 14 * 8, 14},
|
||||
};
|
||||
RSSIGraph rssi_graph{
|
||||
{0, 50, screen_width, 30},
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ namespace ui::external_app::game2048 {
|
|||
Game2048View::Game2048View(NavigationView& nav)
|
||||
: nav_(nav), score(0), best_score(0), game_state(STATE_PLAYING) {
|
||||
add_children({&dummy});
|
||||
TILE_SIZE = (screen_width - 2 * BOARD_START_X - (GRID_SIZE + 1) * TILE_MARGIN) / GRID_SIZE;
|
||||
init_game();
|
||||
}
|
||||
|
||||
|
|
@ -301,11 +302,11 @@ void Game2048View::draw_game() {
|
|||
void Game2048View::show_game_over() {
|
||||
if (show_you_won_you_lost_slow_down_cunter++ % 1000 != 0) return;
|
||||
// slow down otherwies it repaint even faster than it finished paint full stuff
|
||||
painter.fill_rectangle({40, 100, 160, 100}, Color::black());
|
||||
painter.draw_rectangle({40, 100, 160, 100}, Color::white());
|
||||
painter.draw_string({80, 115}, *Theme::getInstance()->bg_darkest, "GAME OVER");
|
||||
painter.draw_string({70, 135}, *Theme::getInstance()->bg_darkest, "Press SELECT");
|
||||
painter.draw_string({75, 155}, *Theme::getInstance()->bg_darkest, "to restart");
|
||||
painter.fill_rectangle({UI_POS_X_CENTER(20), 100, 160, 100}, Color::black());
|
||||
painter.draw_rectangle({UI_POS_X_CENTER(20), 100, 160, 100}, Color::white());
|
||||
painter.draw_string({UI_POS_X_CENTER(10), 115}, *Theme::getInstance()->bg_darkest, "GAME OVER");
|
||||
painter.draw_string({UI_POS_X_CENTER(13), 135}, *Theme::getInstance()->bg_darkest, "Press SELECT");
|
||||
painter.draw_string({UI_POS_X_CENTER(11), 155}, *Theme::getInstance()->bg_darkest, "to restart");
|
||||
need_repaint = false;
|
||||
need_repaint_bg_frame = true;
|
||||
}
|
||||
|
|
@ -313,11 +314,11 @@ void Game2048View::show_game_over() {
|
|||
void Game2048View::show_you_won() {
|
||||
if (show_you_won_you_lost_slow_down_cunter++ % 1000 != 0) return;
|
||||
// slow down otherwies it repaint even faster than it finished paint full stuff
|
||||
painter.fill_rectangle({40, 100, 160, 100}, Color::black());
|
||||
painter.draw_rectangle({40, 100, 160, 100}, Color::white());
|
||||
painter.draw_string({80, 115}, *Theme::getInstance()->bg_darkest, "YOU WON!");
|
||||
painter.draw_string({70, 135}, *Theme::getInstance()->bg_darkest, "Press SELECT");
|
||||
painter.draw_string({75, 155}, *Theme::getInstance()->bg_darkest, "to restart");
|
||||
painter.fill_rectangle({UI_POS_X_CENTER(20), 100, 160, 100}, Color::black());
|
||||
painter.draw_rectangle({UI_POS_X_CENTER(20), 100, 160, 100}, Color::white());
|
||||
painter.draw_string({UI_POS_X_CENTER(9), 115}, *Theme::getInstance()->bg_darkest, "YOU WON!");
|
||||
painter.draw_string({UI_POS_X_CENTER(13), 135}, *Theme::getInstance()->bg_darkest, "Press SELECT");
|
||||
painter.draw_string({UI_POS_X_CENTER(11), 155}, *Theme::getInstance()->bg_darkest, "to restart");
|
||||
need_repaint = false;
|
||||
need_repaint_bg_frame = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
namespace ui::external_app::game2048 {
|
||||
|
||||
#define GRID_SIZE 4
|
||||
#define TILE_SIZE 50
|
||||
#define TILE_MARGIN 5
|
||||
#define BOARD_START_X 15
|
||||
#define BOARD_START_Y 35
|
||||
|
|
@ -63,6 +62,7 @@ class Game2048View : public View {
|
|||
Painter painter{};
|
||||
|
||||
int grid[GRID_SIZE][GRID_SIZE];
|
||||
int TILE_SIZE = 50;
|
||||
int score;
|
||||
int best_score;
|
||||
GameState game_state;
|
||||
|
|
|
|||
10
firmware/application/external/gfxeq/ui_gfxeq.hpp
vendored
10
firmware/application/external/gfxeq/ui_gfxeq.hpp
vendored
|
|
@ -68,12 +68,12 @@ class gfxEQView : public View {
|
|||
ColorTheme{Color(64, 64, 64), Color(255, 0, 0)},
|
||||
ColorTheme{Color(255, 192, 0), Color(0, 64, 128)}};
|
||||
|
||||
ButtonWithEncoder button_frequency{{0 * 8, 0 * 16 + 4, 11 * 8, 1 * 8}, ""};
|
||||
RFAmpField field_rf_amp{{13 * 8, 0 * 16}};
|
||||
LNAGainField field_lna{{15 * 8, 0 * 16}};
|
||||
VGAGainField field_vga{{18 * 8, 0 * 16}};
|
||||
ButtonWithEncoder button_frequency{{UI_POS_X(0), UI_POS_Y(0) + 4, 11 * 8, 1 * 8}, ""};
|
||||
RFAmpField field_rf_amp{{13 * 8, UI_POS_Y(0)}};
|
||||
LNAGainField field_lna{{15 * 8, UI_POS_Y(0)}};
|
||||
VGAGainField field_vga{{18 * 8, UI_POS_Y(0)}};
|
||||
Button button_mood{{21 * 8, 0, 6 * 8, 16}, "MOOD"};
|
||||
AudioVolumeField field_volume{{screen_width - 2 * 8, 0 * 16}};
|
||||
AudioVolumeField field_volume{{screen_width - 2 * 8, UI_POS_Y(0)}};
|
||||
GraphEq gr{{2, UI_POS_DEFAULT_HEIGHT, UI_POS_MAXWIDTH - 4, UI_POS_HEIGHT_REMAINING(2)}, false};
|
||||
|
||||
rf::Frequency frequency_value{93100000};
|
||||
|
|
|
|||
|
|
@ -82,24 +82,24 @@ class GpsSimAppView : public View {
|
|||
bool ready_signal{false};
|
||||
|
||||
Button button_open{
|
||||
{0 * 8, 0 * 16, 10 * 8, 2 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0), 10 * 8, 2 * 16},
|
||||
"Open file"};
|
||||
|
||||
Text text_filename{
|
||||
{11 * 8, 0 * 16, 12 * 8, 16},
|
||||
{11 * 8, UI_POS_Y(0), 12 * 8, 16},
|
||||
"-"};
|
||||
Text text_sample_rate{
|
||||
{24 * 8, 0 * 16, 6 * 8, 16},
|
||||
{24 * 8, UI_POS_Y(0), 6 * 8, 16},
|
||||
"-"};
|
||||
|
||||
Text text_duration{
|
||||
{11 * 8, 1 * 16, 6 * 8, 16},
|
||||
"-"};
|
||||
ProgressBar progressbar{
|
||||
{18 * 8, 1 * 16, 12 * 8, 16}};
|
||||
{18 * 8, 1 * 16, UI_POS_WIDTH_REMAINING(18), 16}};
|
||||
|
||||
TxFrequencyField field_frequency{
|
||||
{0 * 8, 2 * 16},
|
||||
{UI_POS_X(0), 2 * 16},
|
||||
nav_};
|
||||
|
||||
TransmitterView2 tx_view{
|
||||
|
|
|
|||
|
|
@ -88,55 +88,55 @@ class HopperView : public View {
|
|||
false};
|
||||
|
||||
NewButton button_load_list{
|
||||
{0 * 8, 9 * 16 + 4, 4 * 8, 32},
|
||||
{UI_POS_X(0), UI_POS_Y_BOTTOM(10), 4 * 8, 32},
|
||||
{},
|
||||
&bitmap_icon_load,
|
||||
Color::dark_blue(),
|
||||
/*vcenter*/ true};
|
||||
|
||||
NewButton button_save_list{
|
||||
{4 * 8, 9 * 16 + 4, 4 * 8, 32},
|
||||
{4 * 8, UI_POS_Y_BOTTOM(10), 4 * 8, 32},
|
||||
{},
|
||||
&bitmap_icon_save,
|
||||
Color::dark_blue(),
|
||||
/*vcenter*/ true};
|
||||
|
||||
NewButton button_add_freq{
|
||||
{8 * 8 + 4, 9 * 16 + 4, 4 * 8, 32},
|
||||
{8 * 8 + 4, UI_POS_Y_BOTTOM(10), 4 * 8, 32},
|
||||
{},
|
||||
&bitmap_icon_add,
|
||||
Color::dark_green(),
|
||||
/*vcenter*/ true};
|
||||
|
||||
NewButton button_delete_freq{
|
||||
{12 * 8 + 4, 9 * 16 + 4, 4 * 8, 32},
|
||||
{12 * 8 + 4, UI_POS_Y_BOTTOM(10), 4 * 8, 32},
|
||||
{},
|
||||
&bitmap_icon_trash,
|
||||
Color::dark_red(),
|
||||
/*vcenter*/ true};
|
||||
|
||||
NewButton button_clear{
|
||||
{screen_width - 4 * 8, 9 * 16 + 4, 4 * 8, 32},
|
||||
{screen_width - 4 * 8, UI_POS_Y_BOTTOM(10), 4 * 8, 32},
|
||||
{},
|
||||
&bitmap_icon_tools_wipesd,
|
||||
Color::red(),
|
||||
/*vcenter*/ true};
|
||||
|
||||
Labels labels{
|
||||
{{2 * 8, 23 * 8}, "Type:", Theme::getInstance()->fg_light->foreground},
|
||||
{{1 * 8, 25 * 8}, "Speed:", Theme::getInstance()->fg_light->foreground},
|
||||
{{3 * 8, 27 * 8}, "Hop:", Theme::getInstance()->fg_light->foreground},
|
||||
{{4 * 8, 29 * 8}, "TX:", Theme::getInstance()->fg_light->foreground},
|
||||
{{1 * 8, 31 * 8}, "Sle3p:", Theme::getInstance()->fg_light->foreground}, // euquiq: Token of appreciation to TheSle3p, which made this ehnancement a reality with his bounty.
|
||||
{{0 * 8, 33 * 8}, "Jitter:", Theme::getInstance()->fg_light->foreground}, // Maybe the repository curator can keep the "mystype" for some versions.
|
||||
{{11 * 8, 29 * 8}, "Secs.", Theme::getInstance()->fg_light->foreground},
|
||||
{{11 * 8, 31 * 8}, "Secs.", Theme::getInstance()->fg_light->foreground},
|
||||
{{11 * 8, 33 * 8}, "/60", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, 35 * 8}, "Gain:", Theme::getInstance()->fg_light->foreground},
|
||||
{{11 * 8, 35 * 8}, "A:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{2 * 8, UI_POS_Y_BOTTOM(8)}, "Type:", Theme::getInstance()->fg_light->foreground},
|
||||
{{1 * 8, UI_POS_Y_BOTTOM(7)}, "Speed:", Theme::getInstance()->fg_light->foreground},
|
||||
{{3 * 8, UI_POS_Y_BOTTOM(6)}, "Hop:", Theme::getInstance()->fg_light->foreground},
|
||||
{{4 * 8, UI_POS_Y_BOTTOM(5)}, "TX:", Theme::getInstance()->fg_light->foreground},
|
||||
{{1 * 8, UI_POS_Y_BOTTOM(4)}, "Sle3p:", Theme::getInstance()->fg_light->foreground}, // euquiq: Token of appreciation to TheSle3p, which made this ehnancement a reality with his bounty.
|
||||
{{UI_POS_X(0), UI_POS_Y_BOTTOM(3)}, "Jitter:", Theme::getInstance()->fg_light->foreground}, // Maybe the repository curator can keep the "mystype" for some versions.
|
||||
{{11 * 8, UI_POS_Y_BOTTOM(5)}, "Secs.", Theme::getInstance()->fg_light->foreground},
|
||||
{{11 * 8, UI_POS_Y_BOTTOM(4)}, "Secs.", Theme::getInstance()->fg_light->foreground},
|
||||
{{11 * 8, UI_POS_Y_BOTTOM(3)}, "/60", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, UI_POS_Y_BOTTOM(2)}, "Gain:", Theme::getInstance()->fg_light->foreground},
|
||||
{{11 * 8, UI_POS_Y_BOTTOM(2)}, "A:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
OptionsField options_type{
|
||||
{7 * 8, 23 * 8},
|
||||
{7 * 8, UI_POS_Y_BOTTOM(8)},
|
||||
8,
|
||||
{
|
||||
{"Rand FSK", 0},
|
||||
|
|
@ -153,14 +153,14 @@ class HopperView : public View {
|
|||
}};
|
||||
|
||||
Text text_range_number{
|
||||
{16 * 8, 23 * 8, 2 * 8, 16},
|
||||
{16 * 8, UI_POS_Y_BOTTOM(8), 2 * 8, 16},
|
||||
"--"};
|
||||
Text text_range_total{
|
||||
{18 * 8, 23 * 8, 3 * 8, 16},
|
||||
{18 * 8, UI_POS_Y_BOTTOM(8), 3 * 8, 16},
|
||||
"/--"};
|
||||
|
||||
OptionsField options_speed{
|
||||
{7 * 8, 25 * 8},
|
||||
{7 * 8, UI_POS_Y_BOTTOM(7)},
|
||||
6,
|
||||
{{"10Hz ", 10},
|
||||
{"100Hz ", 100},
|
||||
|
|
@ -169,7 +169,7 @@ class HopperView : public View {
|
|||
{"100kHz", 100000}}};
|
||||
|
||||
OptionsField options_hop{
|
||||
{7 * 8, 27 * 8},
|
||||
{7 * 8, UI_POS_Y_BOTTOM(6)},
|
||||
6,
|
||||
{{"0ms !!", 0},
|
||||
{"1ms ", 1},
|
||||
|
|
@ -182,7 +182,7 @@ class HopperView : public View {
|
|||
{"10s ", 10000}}};
|
||||
|
||||
NumberField field_timetx{
|
||||
{7 * 8, 29 * 8},
|
||||
{7 * 8, UI_POS_Y_BOTTOM(5)},
|
||||
3,
|
||||
{1, 180},
|
||||
1,
|
||||
|
|
@ -190,7 +190,7 @@ class HopperView : public View {
|
|||
};
|
||||
|
||||
NumberField field_timepause{
|
||||
{8 * 8, 31 * 8},
|
||||
{8 * 8, UI_POS_Y_BOTTOM(4)},
|
||||
2,
|
||||
{1, 60},
|
||||
1,
|
||||
|
|
@ -198,7 +198,7 @@ class HopperView : public View {
|
|||
};
|
||||
|
||||
NumberField field_jitter{
|
||||
{8 * 8, 33 * 8},
|
||||
{8 * 8, UI_POS_Y_BOTTOM(3)},
|
||||
2,
|
||||
{1, 60},
|
||||
1,
|
||||
|
|
@ -206,7 +206,7 @@ class HopperView : public View {
|
|||
};
|
||||
|
||||
NumberField field_gain{
|
||||
{8 * 8, 35 * 8},
|
||||
{8 * 8, UI_POS_Y_BOTTOM(2)},
|
||||
2,
|
||||
{0, 47},
|
||||
1,
|
||||
|
|
@ -214,7 +214,7 @@ class HopperView : public View {
|
|||
};
|
||||
|
||||
NumberField field_amp{
|
||||
{13 * 8, 35 * 8},
|
||||
{13 * 8, UI_POS_Y_BOTTOM(2)},
|
||||
1,
|
||||
{0, 1},
|
||||
1,
|
||||
|
|
@ -222,7 +222,7 @@ class HopperView : public View {
|
|||
};
|
||||
|
||||
Button button_transmit{
|
||||
{148, 216, 80, 80},
|
||||
{148, UI_POS_Y_BOTTOM(6), 80, 80},
|
||||
LanguageHelper::currentMessages[LANG_START]};
|
||||
|
||||
MessageHandlerRegistration message_handler_retune{
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class RangeView : public View {
|
|||
"Load range"};
|
||||
|
||||
Button button_start{
|
||||
{0 * 8, 11 * 8, 11 * 8, 28},
|
||||
{UI_POS_X(0), 11 * 8, 11 * 8, 28},
|
||||
""};
|
||||
|
||||
Button button_stop{
|
||||
|
|
@ -144,7 +144,7 @@ class JammerView : public View {
|
|||
{{3 * 8, 27 * 8}, "Hop:", Theme::getInstance()->fg_light->foreground},
|
||||
{{4 * 8, 29 * 8}, "TX:", Theme::getInstance()->fg_light->foreground},
|
||||
{{1 * 8, 31 * 8}, "Sleep:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 33 * 8}, "Jitter:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 33 * 8}, "Jitter:", Theme::getInstance()->fg_light->foreground},
|
||||
{{11 * 8, 29 * 8}, "Secs.", Theme::getInstance()->fg_light->foreground},
|
||||
{{11 * 8, 31 * 8}, "Secs.", Theme::getInstance()->fg_light->foreground},
|
||||
{{11 * 8, 33 * 8}, "/60", Theme::getInstance()->fg_light->foreground},
|
||||
|
|
|
|||
|
|
@ -106,14 +106,14 @@ class KeyfobView : public View {
|
|||
SymField::Type::Hex};
|
||||
|
||||
Text text_status{
|
||||
{2 * 8, 13 * 16, 128, 16},
|
||||
{2 * 8, UI_POS_Y_BOTTOM(7), 128, 16},
|
||||
"Ready"};
|
||||
|
||||
ProgressBar progressbar{
|
||||
{2 * 8, 13 * 16 + 20, 208, 16}};
|
||||
{2 * 8, UI_POS_Y_BOTTOM(6), UI_POS_WIDTH_REMAINING(4), 16}};
|
||||
|
||||
TransmitterView tx_view{
|
||||
16 * 16,
|
||||
(int16_t)UI_POS_Y_BOTTOM(4),
|
||||
0,
|
||||
15,
|
||||
true};
|
||||
|
|
|
|||
4
firmware/application/external/lcr/ui_lcr.hpp
vendored
4
firmware/application/external/lcr/ui_lcr.hpp
vendored
|
|
@ -145,10 +145,10 @@ class LCRView : public View {
|
|||
{2 * 8, 27 * 8 + 4, 26 * 8, 16},
|
||||
LanguageHelper::currentMessages[LANG_READY]};
|
||||
ProgressBar progress{
|
||||
{2 * 8, 29 * 8 + 4, 26 * 8, 16}};
|
||||
{2 * 8, 29 * 8 + 4, UI_POS_WIDTH_REMAINING(4), 16}};
|
||||
|
||||
TransmitterView tx_view{
|
||||
16 * 16,
|
||||
(int16_t)UI_POS_Y_BOTTOM(4),
|
||||
10000,
|
||||
12};
|
||||
|
||||
|
|
|
|||
20
firmware/application/external/level/ui_level.hpp
vendored
20
firmware/application/external/level/ui_level.hpp
vendored
|
|
@ -80,21 +80,21 @@ class LevelView : public View {
|
|||
}};
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 0 * 16}, "LNA: VGA: AMP: VOL: ", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 1 * 16}, "BW: MODE: S: ", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), UI_POS_Y(0)}, "LNA: VGA: AMP: VOL: ", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 1 * 16}, "BW: MODE: S: ", Theme::getInstance()->fg_light->foreground},
|
||||
};
|
||||
|
||||
LNAGainField field_lna{
|
||||
{4 * 8, 0 * 16}};
|
||||
{4 * 8, UI_POS_Y(0)}};
|
||||
|
||||
VGAGainField field_vga{
|
||||
{11 * 8, 0 * 16}};
|
||||
{11 * 8, UI_POS_Y(0)}};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
|
||||
AudioVolumeField field_volume{
|
||||
{24 * 8, 0 * 16}};
|
||||
{24 * 8, UI_POS_Y(0)}};
|
||||
|
||||
OptionsField field_bw{
|
||||
{3 * 8, 1 * 16},
|
||||
|
|
@ -112,7 +112,7 @@ class LevelView : public View {
|
|||
{}};
|
||||
|
||||
ButtonWithEncoder button_frequency{
|
||||
{0 * 8, 2 * 16 + 8, 15 * 8, 1 * 8},
|
||||
{UI_POS_X(0), 2 * 16 + 8, 15 * 8, 1 * 8},
|
||||
""};
|
||||
|
||||
OptionsField field_audio_mode{
|
||||
|
|
@ -135,12 +135,12 @@ class LevelView : public View {
|
|||
|
||||
// RSSI: XX/XX/XXX
|
||||
Text freq_stats_rssi{
|
||||
{0 * 8, 3 * 16 + 4, 15 * 8, 1 * 16},
|
||||
{UI_POS_X(0), 3 * 16 + 4, 15 * 8, 1 * 16},
|
||||
};
|
||||
|
||||
// Power: -XXX db
|
||||
Text freq_stats_db{
|
||||
{0 * 8, 4 * 16 + 4, 15 * 8, 1 * 16},
|
||||
{UI_POS_X(0), 4 * 16 + 4, 15 * 8, 1 * 16},
|
||||
};
|
||||
|
||||
OptionsField peak_mode{
|
||||
|
|
@ -169,7 +169,7 @@ class LevelView : public View {
|
|||
|
||||
// RxSat: XX%
|
||||
Text freq_stats_rx{
|
||||
{0 * 8, 5 * 16 + 4, 10 * 8, 1 * 16},
|
||||
{UI_POS_X(0), 5 * 16 + 4, 10 * 8, 1 * 16},
|
||||
};
|
||||
|
||||
Text text_ctcss{
|
||||
|
|
|
|||
|
|
@ -93,8 +93,8 @@ class LGEView : public View {
|
|||
{{2 * 8, 3 * 8}, "Room:", Theme::getInstance()->fg_light->foreground},
|
||||
{{14 * 8, 3 * 8}, "Text:", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, 5 * 8}, "Team:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 7 * 8}, "Player:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 10 * 8}, "Vest:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 7 * 8}, "Player:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 10 * 8}, "Vest:", Theme::getInstance()->fg_light->foreground},
|
||||
{{4 * 8, 12 * 8}, "ID:", Theme::getInstance()->fg_light->foreground},
|
||||
{{3 * 8, 14 * 8}, "Pow: /10", Theme::getInstance()->fg_light->foreground},
|
||||
{{2 * 8, 16 * 8}, "Time: x100ms", Theme::getInstance()->fg_light->foreground}};
|
||||
|
|
@ -171,10 +171,10 @@ class LGEView : public View {
|
|||
'0'};
|
||||
|
||||
Console console{
|
||||
{0, 18 * 8, screen_width, 7 * 16}};
|
||||
{0, 18 * 8, screen_width, UI_POS_Y_BOTTOM(4) - 18 * 8}};
|
||||
|
||||
TransmitterView tx_view{
|
||||
16 * 16,
|
||||
(int16_t)UI_POS_Y_BOTTOM(4),
|
||||
10000,
|
||||
12};
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ class McuTemperatureView : public View {
|
|||
|
||||
private:
|
||||
Text text_title{
|
||||
{76, 16, screen_width, 16},
|
||||
{UI_POS_X_CENTER(11), 16, UI_POS_WIDTH(11), 16},
|
||||
"Temperature",
|
||||
};
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ class McuTemperatureView : public View {
|
|||
};
|
||||
|
||||
Button button_done{
|
||||
{72, screen_height - 56, 96, 24},
|
||||
{UI_POS_X_CENTER(12), UI_POS_Y_BOTTOM(3), UI_POS_WIDTH(12), 24},
|
||||
"Done"};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -60,13 +60,13 @@ class MetronomeView : public View {
|
|||
uint32_t current_beat_{0};
|
||||
|
||||
Labels labels{
|
||||
{{0 * 8, 1 * 16}, "BPM:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 2 * 16}, "Accent Beep Tune:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 3 * 16}, "Unaccent Beep Tune:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 4 * 16}, "Rhythm:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 1 * 16}, "BPM:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 2 * 16}, "Accent Beep Tune:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 3 * 16}, "Unaccent Beep Tune:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 4 * 16}, "Rhythm:", Theme::getInstance()->fg_light->foreground},
|
||||
{{(sizeof("Rhythm:") + 1) * 8 + 4 * 8, 4 * 16}, "/", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 5 * 16}, "Beep Flash Duration:", Theme::getInstance()->fg_light->foreground},
|
||||
{{0 * 8, 6 * 16}, "Volume:", Theme::getInstance()->fg_light->foreground}};
|
||||
{{UI_POS_X(0), 5 * 16}, "Beep Flash Duration:", Theme::getInstance()->fg_light->foreground},
|
||||
{{UI_POS_X(0), 6 * 16}, "Volume:", Theme::getInstance()->fg_light->foreground}};
|
||||
|
||||
NumberField field_bpm{
|
||||
{(sizeof("BPM:") + 1) * 8, 1 * 16},
|
||||
|
|
|
|||
|
|
@ -171,10 +171,10 @@ class MorseView : public View {
|
|||
"Set message"};
|
||||
|
||||
ProgressBar progressbar{
|
||||
{2 * 8, 28 * 8, 208, 16}};
|
||||
{2 * 8, 28 * 8, UI_POS_WIDTH_REMAINING(4), 16}};
|
||||
|
||||
TransmitterView tx_view{
|
||||
16 * 16,
|
||||
(int16_t)UI_POS_Y_BOTTOM(4),
|
||||
10000,
|
||||
12};
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ class NoaaAptRxView : public View {
|
|||
VGAGainField field_vga{
|
||||
{UI_POS_X(18), UI_POS_Y(0)}};
|
||||
RSSI rssi{
|
||||
{UI_POS_X(21), UI_POS_Y(0), UI_POS_WIDTH(6), 4}};
|
||||
{UI_POS_X(21), UI_POS_Y(0), UI_POS_WIDTH_REMAINING(24), 4}};
|
||||
AudioVolumeField field_volume{
|
||||
{UI_POS_X_RIGHT(2), UI_POS_Y(0)}};
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ class NoaaAptRxView : public View {
|
|||
};
|
||||
|
||||
Button button_ss{
|
||||
{UI_POS_X_RIGHT(6), UI_POS_Y(1), UI_POS_WIDTH(5), UI_POS_DEFAULT_HEIGHT},
|
||||
{UI_POS_X_RIGHT(6), UI_POS_Y(1), UI_POS_WIDTH(6), UI_POS_HEIGHT(2)},
|
||||
LanguageHelper::currentMessages[LANG_START]};
|
||||
|
||||
MessageHandlerRegistration message_handler_stats{
|
||||
|
|
|
|||
|
|
@ -62,18 +62,18 @@ class NRFRxView : public View {
|
|||
uint32_t prev_value{0};
|
||||
|
||||
RFAmpField field_rf_amp{
|
||||
{13 * 8, 0 * 16}};
|
||||
{13 * 8, UI_POS_Y(0)}};
|
||||
LNAGainField field_lna{
|
||||
{15 * 8, 0 * 16}};
|
||||
{15 * 8, UI_POS_Y(0)}};
|
||||
VGAGainField field_vga{
|
||||
{18 * 8, 0 * 16}};
|
||||
{18 * 8, UI_POS_Y(0)}};
|
||||
RSSI rssi{
|
||||
{21 * 8, 0, 6 * 8, 4}};
|
||||
{21 * 8, 0, UI_POS_WIDTH_REMAINING(22), 4}};
|
||||
Channel channel{
|
||||
{21 * 8, 5, 6 * 8, 4}};
|
||||
{21 * 8, 5, UI_POS_WIDTH_REMAINING(22), 4}};
|
||||
|
||||
RxFrequencyField field_frequency{
|
||||
{0 * 8, 0 * 16},
|
||||
{UI_POS_X(0), UI_POS_Y(0)},
|
||||
nav_};
|
||||
|
||||
Button button_modem_setup{
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue