mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2024-12-13 19:54:39 +00:00
Looking Glass - persist range/preset settings, UI tweaks (#1401)
* WIP * Add encoder support for TextField * Working settings, use TextField * Remove unneeded blanking rectangle
This commit is contained in:
parent
a476647d70
commit
dc9a16c54b
@ -74,8 +74,8 @@ rf::Frequency GlassView::get_freq_from_bin_pos(uint8_t pos) {
|
|||||||
|
|
||||||
void GlassView::on_marker_change() {
|
void GlassView::on_marker_change() {
|
||||||
marker = get_freq_from_bin_pos(marker_pixel_index);
|
marker = get_freq_from_bin_pos(marker_pixel_index);
|
||||||
button_marker.set_text(to_string_short_freq(marker));
|
field_marker.set_text(to_string_short_freq(marker));
|
||||||
PlotMarker(marker_pixel_index); // Refresh marker on screen
|
plot_marker(marker_pixel_index); // Refresh marker on screen
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlassView::retune() {
|
void GlassView::retune() {
|
||||||
@ -87,21 +87,13 @@ void GlassView::retune() {
|
|||||||
baseband::spectrum_streaming_start(); // Do the RX
|
baseband::spectrum_streaming_start(); // Do the RX
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlassView::on_lna_changed(int32_t v_db) {
|
|
||||||
receiver_model.set_lna(v_db);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GlassView::on_vga_changed(int32_t v_db) {
|
|
||||||
receiver_model.set_vga(v_db);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GlassView::reset_live_view(bool clear_screen) {
|
void GlassView::reset_live_view(bool clear_screen) {
|
||||||
max_freq_hold = 0;
|
max_freq_hold = 0;
|
||||||
max_freq_power = -1000;
|
max_freq_power = -1000;
|
||||||
if (clear_screen) {
|
if (clear_screen) {
|
||||||
// only clear screen in peak mode
|
// only clear screen in peak mode
|
||||||
if (live_frequency_view == 2) {
|
if (live_frequency_view == 2) {
|
||||||
display.fill_rectangle({{0, 108 + 16}, {SCREEN_W, 320 - (108 + 16)}}, {0, 0, 0});
|
display.fill_rectangle({{0, 108 + 16}, {SCREEN_W, SCREEN_H - (108 + 16)}}, {0, 0, 0});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,15 +126,15 @@ void GlassView::add_spectrum_pixel(uint8_t power) {
|
|||||||
uint8_t color_gradient = (point * 255) / 212;
|
uint8_t color_gradient = (point * 255) / 212;
|
||||||
// clear if not in peak view
|
// clear if not in peak view
|
||||||
if (live_frequency_view != 2) {
|
if (live_frequency_view != 2) {
|
||||||
display.fill_rectangle({{xpos, 108 + 16}, {1, 320 - point}}, {0, 0, 0});
|
display.fill_rectangle({{xpos, 108 + 16}, {1, SCREEN_H - point}}, {0, 0, 0});
|
||||||
}
|
}
|
||||||
display.fill_rectangle({{xpos, 320 - point}, {1, point}}, {color_gradient, 0, uint8_t(255 - color_gradient)});
|
display.fill_rectangle({{xpos, SCREEN_H - point}, {1, point}}, {color_gradient, 0, uint8_t(255 - color_gradient)});
|
||||||
}
|
}
|
||||||
if (last_max_freq != max_freq_hold) {
|
if (last_max_freq != max_freq_hold) {
|
||||||
last_max_freq = max_freq_hold;
|
last_max_freq = max_freq_hold;
|
||||||
freq_stats.set("MAX HOLD: " + to_string_short_freq(max_freq_hold));
|
freq_stats.set("MAX HOLD: " + to_string_short_freq(max_freq_hold));
|
||||||
}
|
}
|
||||||
PlotMarker(marker_pixel_index);
|
plot_marker(marker_pixel_index);
|
||||||
} else {
|
} else {
|
||||||
display.draw_pixels({{0, display.scroll(1)}, {SCREEN_W, 1}}, spectrum_row); // new line at top, one less var, speedier
|
display.draw_pixels({{0, display.scroll(1)}, {SCREEN_W, 1}}, spectrum_row); // new line at top, one less var, speedier
|
||||||
}
|
}
|
||||||
@ -176,7 +168,7 @@ bool GlassView::process_bins(uint8_t* powerlevel) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apparently, the spectrum object returns an array of SPEC_NB_BINS (256) bins
|
// Apparently, the spectrum object returns an array of SPEC_NB_BINS (256) bins
|
||||||
// Each having the radio signal power for it's corresponding frequency slot
|
// Each having the radio signal power for its corresponding frequency slot
|
||||||
void GlassView::on_channel_spectrum(const ChannelSpectrum& spectrum) {
|
void GlassView::on_channel_spectrum(const ChannelSpectrum& spectrum) {
|
||||||
baseband::spectrum_streaming_stop();
|
baseband::spectrum_streaming_stop();
|
||||||
// Convert bins of this spectrum slice into a representative max_power and when enough, into pixels
|
// Convert bins of this spectrum slice into a representative max_power and when enough, into pixels
|
||||||
@ -232,7 +224,6 @@ void GlassView::on_range_changed() {
|
|||||||
each_bin_size = looking_glass_bandwidth / SCREEN_W;
|
each_bin_size = looking_glass_bandwidth / SCREEN_W;
|
||||||
looking_glass_step = looking_glass_bandwidth;
|
looking_glass_step = looking_glass_bandwidth;
|
||||||
f_center_ini = f_min + (looking_glass_bandwidth / 2); // Initial center frequency for sweep
|
f_center_ini = f_min + (looking_glass_bandwidth / 2); // Initial center frequency for sweep
|
||||||
portapack::display.fill_rectangle({17 * 8, 4 * 16, 2 * 8, 16}, Color::black()); // Clear old marker and whole marker rectangle btw
|
|
||||||
} else {
|
} else {
|
||||||
// view is made in multiple pass, use original bin picking
|
// view is made in multiple pass, use original bin picking
|
||||||
mode = scan_type.selected_index_value();
|
mode = scan_type.selected_index_value();
|
||||||
@ -253,19 +244,13 @@ void GlassView::on_range_changed() {
|
|||||||
}
|
}
|
||||||
search_span = looking_glass_range / MHZ_DIV;
|
search_span = looking_glass_range / MHZ_DIV;
|
||||||
marker_pixel_step = looking_glass_range / SCREEN_W; // Each pixel value in Hz
|
marker_pixel_step = looking_glass_range / SCREEN_W; // Each pixel value in Hz
|
||||||
//
|
|
||||||
button_range.set_text(" "); // clear up to 6 chars
|
|
||||||
if (locked_range) {
|
|
||||||
button_range.set_text(">" + to_string_dec_uint(search_span) + "<");
|
|
||||||
} else {
|
|
||||||
button_range.set_text(" " + to_string_dec_uint(search_span) + " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
pixel_index = 0; // reset pixel counter
|
pixel_index = 0; // reset pixel counter
|
||||||
max_power = 0; // reset save max power level
|
max_power = 0; // reset save max power level
|
||||||
bins_Hz_size = 0; // reset amount of Hz filled up by pixels
|
bins_Hz_size = 0; // reset amount of Hz filled up by pixels
|
||||||
//
|
|
||||||
on_marker_change();
|
on_marker_change();
|
||||||
|
update_range_field();
|
||||||
|
|
||||||
// set the sample rate and bandwidth
|
// set the sample rate and bandwidth
|
||||||
receiver_model.set_sampling_rate(looking_glass_sampling_rate);
|
receiver_model.set_sampling_rate(looking_glass_sampling_rate);
|
||||||
@ -277,7 +262,7 @@ void GlassView::on_range_changed() {
|
|||||||
receiver_model.set_target_frequency(f_center); // tune rx for this slice
|
receiver_model.set_target_frequency(f_center); // tune rx for this slice
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlassView::PlotMarker(uint8_t pos) {
|
void GlassView::plot_marker(uint8_t pos) {
|
||||||
uint8_t shift_y = 0;
|
uint8_t shift_y = 0;
|
||||||
if (live_frequency_view > 0) // plot one line down when in live view
|
if (live_frequency_view > 0) // plot one line down when in live view
|
||||||
{
|
{
|
||||||
@ -289,7 +274,7 @@ void GlassView::PlotMarker(uint8_t pos) {
|
|||||||
portapack::display.fill_rectangle({pos, 106 + shift_y, 1, 2}, Color::red()); // Red marker bottom
|
portapack::display.fill_rectangle({pos, 106 + shift_y, 1, 2}, Color::red()); // Red marker bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlassView::clip_min(int32_t v) {
|
void GlassView::update_min(int32_t v) {
|
||||||
int32_t min_size = steps;
|
int32_t min_size = steps;
|
||||||
if (locked_range)
|
if (locked_range)
|
||||||
min_size = search_span;
|
min_size = search_span;
|
||||||
@ -299,15 +284,14 @@ void GlassView::clip_min(int32_t v) {
|
|||||||
v = 7200 - min_size;
|
v = 7200 - min_size;
|
||||||
}
|
}
|
||||||
if (v > (field_frequency_max.value() - min_size))
|
if (v > (field_frequency_max.value() - min_size))
|
||||||
field_frequency_max.set_value(v + min_size);
|
field_frequency_max.set_value(v + min_size, false);
|
||||||
if (locked_range)
|
if (locked_range)
|
||||||
field_frequency_max.set_value(v + min_size);
|
field_frequency_max.set_value(v + min_size, false);
|
||||||
else
|
else
|
||||||
field_frequency_min.set_value(v);
|
field_frequency_min.set_value(v, false);
|
||||||
on_range_changed();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlassView::clip_max(int32_t v) {
|
void GlassView::update_max(int32_t v) {
|
||||||
int32_t min_size = steps;
|
int32_t min_size = steps;
|
||||||
if (locked_range)
|
if (locked_range)
|
||||||
min_size = search_span;
|
min_size = search_span;
|
||||||
@ -317,12 +301,21 @@ void GlassView::clip_max(int32_t v) {
|
|||||||
v = min_size;
|
v = min_size;
|
||||||
}
|
}
|
||||||
if (v < (field_frequency_min.value() + min_size))
|
if (v < (field_frequency_min.value() + min_size))
|
||||||
field_frequency_min.set_value(v - min_size);
|
field_frequency_min.set_value(v - min_size, false);
|
||||||
if (locked_range)
|
if (locked_range)
|
||||||
field_frequency_min.set_value(v - min_size);
|
field_frequency_min.set_value(v - min_size, false);
|
||||||
else
|
else
|
||||||
field_frequency_max.set_value(v);
|
field_frequency_max.set_value(v, false);
|
||||||
on_range_changed();
|
}
|
||||||
|
|
||||||
|
void GlassView::update_range_field() {
|
||||||
|
if (!locked_range) {
|
||||||
|
field_range.set_style(&Styles::white);
|
||||||
|
field_range.set_text(" " + to_string_dec_uint(search_span) + " ");
|
||||||
|
} else {
|
||||||
|
field_range.set_style(&Styles::red);
|
||||||
|
field_range.set_text(">" + to_string_dec_uint(search_span) + "<");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GlassView::GlassView(
|
GlassView::GlassView(
|
||||||
@ -335,7 +328,7 @@ GlassView::GlassView(
|
|||||||
&field_frequency_max,
|
&field_frequency_max,
|
||||||
&field_lna,
|
&field_lna,
|
||||||
&field_vga,
|
&field_vga,
|
||||||
&button_range,
|
&field_range,
|
||||||
&steps_config,
|
&steps_config,
|
||||||
&scan_type,
|
&scan_type,
|
||||||
&view_config,
|
&view_config,
|
||||||
@ -343,69 +336,67 @@ GlassView::GlassView(
|
|||||||
&filter_config,
|
&filter_config,
|
||||||
&field_rf_amp,
|
&field_rf_amp,
|
||||||
&range_presets,
|
&range_presets,
|
||||||
&button_marker,
|
&field_marker,
|
||||||
&field_trigger,
|
&field_trigger,
|
||||||
&button_jump,
|
&button_jump,
|
||||||
&button_rst,
|
&button_rst,
|
||||||
&freq_stats});
|
&freq_stats});
|
||||||
|
|
||||||
load_Presets(); // Load available presets from TXT files (or default)
|
load_presets(); // Load available presets from TXT files (or default).
|
||||||
|
preset_index = clip<uint8_t>(preset_index, 0, presets_db.size());
|
||||||
|
|
||||||
|
field_frequency_min.set_value(f_min / MHZ_DIV);
|
||||||
field_frequency_min.on_change = [this](int32_t v) {
|
field_frequency_min.on_change = [this](int32_t v) {
|
||||||
clip_min(v);
|
range_presets.set_selected_index(0); // Manual
|
||||||
|
update_min(v);
|
||||||
|
on_range_changed();
|
||||||
};
|
};
|
||||||
field_frequency_min.set_value(presets_db[0].min); // Defaults to first preset
|
|
||||||
field_frequency_min.set_step(steps);
|
|
||||||
|
|
||||||
field_frequency_min.on_select = [this, &nav](NumberField& field) {
|
field_frequency_min.on_select = [this, &nav](NumberField& field) {
|
||||||
auto new_view = nav_.push<FrequencyKeypadView>(field_frequency_min.value() * MHZ_DIV);
|
auto new_view = nav_.push<FrequencyKeypadView>(field_frequency_min.value() * MHZ_DIV);
|
||||||
new_view->on_changed = [this, &field](rf::Frequency f) {
|
new_view->on_changed = [this, &field](rf::Frequency f) {
|
||||||
clip_min(f / MHZ_DIV);
|
field_frequency_min.set_value(f / MHZ_DIV);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
field_frequency_max.set_value(f_max / MHZ_DIV);
|
||||||
field_frequency_max.on_change = [this](int32_t v) {
|
field_frequency_max.on_change = [this](int32_t v) {
|
||||||
clip_max(v);
|
range_presets.set_selected_index(0); // Manual
|
||||||
|
update_max(v);
|
||||||
|
on_range_changed();
|
||||||
};
|
};
|
||||||
field_frequency_max.set_value(presets_db[0].max); // Defaults to first preset
|
|
||||||
field_frequency_max.set_step(steps);
|
|
||||||
|
|
||||||
field_frequency_max.on_select = [this, &nav](NumberField& field) {
|
field_frequency_max.on_select = [this, &nav](NumberField& field) {
|
||||||
auto new_view = nav_.push<FrequencyKeypadView>(field_frequency_max.value() * MHZ_DIV);
|
auto new_view = nav_.push<FrequencyKeypadView>(field_frequency_max.value() * MHZ_DIV);
|
||||||
new_view->on_changed = [this, &field](rf::Frequency f) {
|
new_view->on_changed = [this, &field](rf::Frequency f) {
|
||||||
clip_max(f / MHZ_DIV);
|
field_frequency_max.set_value(f / MHZ_DIV);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
field_lna.on_change = [this](int32_t v) {
|
field_lna.on_change = [this](int32_t v_db) {
|
||||||
reset_live_view(true);
|
reset_live_view(true);
|
||||||
this->on_lna_changed(v);
|
receiver_model.set_lna(v_db);
|
||||||
};
|
};
|
||||||
field_lna.set_value(receiver_model.lna());
|
field_lna.set_value(receiver_model.lna());
|
||||||
|
|
||||||
field_vga.on_change = [this](int32_t v_db) {
|
field_vga.on_change = [this](int32_t v_db) {
|
||||||
reset_live_view(true);
|
reset_live_view(true);
|
||||||
this->on_vga_changed(v_db);
|
receiver_model.set_vga(v_db);
|
||||||
};
|
};
|
||||||
field_vga.set_value(receiver_model.vga());
|
field_vga.set_value(receiver_model.vga());
|
||||||
|
|
||||||
steps_config.on_change = [this](size_t n, OptionsField::value_t v) {
|
steps_config.on_change = [this](size_t, OptionsField::value_t v) {
|
||||||
(void)n;
|
|
||||||
field_frequency_min.set_step(v);
|
field_frequency_min.set_step(v);
|
||||||
field_frequency_max.set_step(v);
|
field_frequency_max.set_step(v);
|
||||||
steps = v;
|
steps = v;
|
||||||
};
|
};
|
||||||
steps_config.set_selected_index(0); // default of 1 Mhz steps
|
steps_config.set_selected_index(0); // default of 1 Mhz steps
|
||||||
|
|
||||||
scan_type.on_change = [this](size_t n, OptionsField::value_t v) {
|
scan_type.on_change = [this](size_t, OptionsField::value_t v) {
|
||||||
(void)n;
|
|
||||||
mode = v;
|
mode = v;
|
||||||
on_range_changed();
|
on_range_changed();
|
||||||
};
|
};
|
||||||
scan_type.set_selected_index(0); // default legacy fast scan
|
scan_type.set_selected_index(0); // default legacy fast scan
|
||||||
|
|
||||||
view_config.on_change = [this](size_t n, OptionsField::value_t v) {
|
view_config.on_change = [this](size_t, OptionsField::value_t v) {
|
||||||
(void)n;
|
|
||||||
// clear between changes
|
// clear between changes
|
||||||
reset_live_view(true);
|
reset_live_view(true);
|
||||||
if (v == 0) {
|
if (v == 0) {
|
||||||
@ -436,41 +427,37 @@ GlassView::GlassView(
|
|||||||
};
|
};
|
||||||
view_config.set_selected_index(0); // default spectrum
|
view_config.set_selected_index(0); // default spectrum
|
||||||
|
|
||||||
level_integration.on_change = [this](size_t n, OptionsField::value_t v) {
|
level_integration.on_change = [this](size_t, OptionsField::value_t v) {
|
||||||
(void)n;
|
|
||||||
reset_live_view(true);
|
reset_live_view(true);
|
||||||
live_frequency_integrate = v;
|
live_frequency_integrate = v;
|
||||||
};
|
};
|
||||||
level_integration.set_selected_index(3); // default integration of ( 3 * old value + new_value ) / 4
|
level_integration.set_selected_index(3); // default integration of ( 3 * old value + new_value ) / 4
|
||||||
|
|
||||||
filter_config.on_change = [this](size_t n, OptionsField::value_t v) {
|
filter_config.on_change = [this](size_t, OptionsField::value_t v) {
|
||||||
(void)n;
|
|
||||||
reset_live_view(true);
|
reset_live_view(true);
|
||||||
min_color_power = v;
|
min_color_power = v;
|
||||||
};
|
};
|
||||||
filter_config.set_selected_index(0);
|
filter_config.set_selected_index(0);
|
||||||
|
|
||||||
range_presets.on_change = [this](size_t n, OptionsField::value_t v) {
|
range_presets.on_change = [this](size_t ix, OptionsField::value_t v) {
|
||||||
(void)n;
|
preset_index = ix;
|
||||||
|
if (ix == 0) return; // Don't update range for "Manual".
|
||||||
|
|
||||||
|
// NB: Don't trigger updates, presets directly set the range
|
||||||
|
// values without applying step or range lock.
|
||||||
field_frequency_min.set_value(presets_db[v].min, false);
|
field_frequency_min.set_value(presets_db[v].min, false);
|
||||||
field_frequency_max.set_value(presets_db[v].max, false);
|
field_frequency_max.set_value(presets_db[v].max, false);
|
||||||
on_range_changed();
|
on_range_changed();
|
||||||
};
|
};
|
||||||
|
range_presets.set_selected_index(preset_index);
|
||||||
|
|
||||||
button_marker.on_change = [this]() {
|
field_marker.on_encoder_change = [this](TextField&, EncoderEvent delta) {
|
||||||
if (((int)marker_pixel_index + button_marker.get_encoder_delta()) < 0) {
|
marker_pixel_index = clip<uint8_t>(marker_pixel_index + delta, 0, SCREEN_W);
|
||||||
marker_pixel_index = 0;
|
|
||||||
} else if (((int)marker_pixel_index + button_marker.get_encoder_delta()) > SCREEN_W) {
|
|
||||||
marker_pixel_index = SCREEN_W;
|
|
||||||
} else {
|
|
||||||
marker_pixel_index = marker_pixel_index + button_marker.get_encoder_delta();
|
|
||||||
}
|
|
||||||
on_marker_change();
|
on_marker_change();
|
||||||
button_marker.set_encoder_delta(0);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
button_marker.on_select = [this](ButtonWithEncoder&) {
|
field_marker.on_select = [this](TextField&) {
|
||||||
receiver_model.set_target_frequency(marker); // Center tune rx in marker freq.
|
receiver_model.set_target_frequency(marker); // Center tune rx to marker freq.
|
||||||
auto settings = receiver_model.settings();
|
auto settings = receiver_model.settings();
|
||||||
settings.frequency_step = MHZ_DIV; // Preset a 1 MHz frequency step into RX -> AUDIO
|
settings.frequency_step = MHZ_DIV; // Preset a 1 MHz frequency step into RX -> AUDIO
|
||||||
nav_.replace<AnalogAudioView>(settings); // Jump into audio view
|
nav_.replace<AnalogAudioView>(settings); // Jump into audio view
|
||||||
@ -481,16 +468,9 @@ GlassView::GlassView(
|
|||||||
};
|
};
|
||||||
field_trigger.set_value(32); // Defaults to 32, as normal triggering resolution
|
field_trigger.set_value(32); // Defaults to 32, as normal triggering resolution
|
||||||
|
|
||||||
button_range.on_select = [this](Button&) {
|
field_range.on_select = [this](TextField&) {
|
||||||
if (locked_range) {
|
locked_range = !locked_range;
|
||||||
locked_range = false;
|
update_range_field();
|
||||||
button_range.set_style(&Styles::white);
|
|
||||||
button_range.set_text(" " + to_string_dec_uint(search_span) + " ");
|
|
||||||
} else {
|
|
||||||
locked_range = true;
|
|
||||||
button_range.set_style(&Styles::red);
|
|
||||||
button_range.set_text(">" + to_string_dec_uint(search_span) + "<");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
button_jump.on_select = [this](Button&) {
|
button_jump.on_select = [this](Button&) {
|
||||||
@ -506,12 +486,12 @@ GlassView::GlassView(
|
|||||||
|
|
||||||
display.scroll_set_area(109, 319);
|
display.scroll_set_area(109, 319);
|
||||||
baseband::set_spectrum(looking_glass_bandwidth, field_trigger.value()); // trigger:
|
baseband::set_spectrum(looking_glass_bandwidth, field_trigger.value()); // trigger:
|
||||||
// Discord User jteich: WidebandSpectrum::on_message to set the trigger value. In WidebandSpectrum::execute ,
|
// Discord User jteich: WidebandSpectrum::on_message to set the trigger value. In WidebandSpectrum::execute,
|
||||||
// it keeps adding the output of the fft to the buffer until "trigger" number of calls are made,
|
// it keeps adding the output of the fft to the buffer until "trigger" number of calls are made,
|
||||||
// at which time it pushes the buffer up with channel_spectrum.feed
|
// at which time it pushes the buffer up with channel_spectrum.feed
|
||||||
|
|
||||||
marker_pixel_index = 120;
|
marker_pixel_index = SCREEN_W / 2;
|
||||||
on_range_changed();
|
on_range_changed(); // Force an update.
|
||||||
|
|
||||||
receiver_model.set_sampling_rate(looking_glass_sampling_rate); // 20mhz
|
receiver_model.set_sampling_rate(looking_glass_sampling_rate); // 20mhz
|
||||||
receiver_model.set_baseband_bandwidth(looking_glass_bandwidth); // possible values: 1.75/2.5/3.5/5/5.5/6/7/8/9/10/12/14/15/20/24/28MHz
|
receiver_model.set_baseband_bandwidth(looking_glass_bandwidth); // possible values: 1.75/2.5/3.5/5/5.5/6/7/8/9/10/12/14/15/20/24/28MHz
|
||||||
@ -519,11 +499,14 @@ GlassView::GlassView(
|
|||||||
receiver_model.enable();
|
receiver_model.enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlassView::load_Presets() {
|
void GlassView::load_presets() {
|
||||||
File presets_file;
|
File presets_file;
|
||||||
auto error = presets_file.open("LOOKINGGLASS/PRESETS.TXT");
|
auto error = presets_file.open("LOOKINGGLASS/PRESETS.TXT");
|
||||||
presets_db.clear();
|
presets_db.clear();
|
||||||
|
|
||||||
|
// Add the "Manual" entry.
|
||||||
|
presets_db.push_back({0, 0, "Manual"});
|
||||||
|
|
||||||
if (!error) {
|
if (!error) {
|
||||||
auto reader = FileLineReader(presets_file);
|
auto reader = FileLineReader(presets_file);
|
||||||
for (const auto& line : reader) {
|
for (const auto& line : reader) {
|
||||||
@ -546,14 +529,16 @@ void GlassView::load_Presets() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Couldn't load any from the file, load a default instead.
|
/*
|
||||||
if (presets_db.empty())
|
// Didn't load any from the file, add a default.
|
||||||
presets_Default();
|
if (presets_db.size() == 1)
|
||||||
|
presets_db.push_back({2320, 2560, "DEFAULT WIFI 2.4GHz"});
|
||||||
|
*/
|
||||||
|
|
||||||
populate_Presets();
|
populate_presets();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlassView::populate_Presets() {
|
void GlassView::populate_presets() {
|
||||||
using option_t = std::pair<std::string, int32_t>;
|
using option_t = std::pair<std::string, int32_t>;
|
||||||
using options_t = std::vector<option_t>;
|
using options_t = std::vector<option_t>;
|
||||||
options_t entries;
|
options_t entries;
|
||||||
@ -561,12 +546,7 @@ void GlassView::populate_Presets() {
|
|||||||
for (const auto& preset : presets_db)
|
for (const auto& preset : presets_db)
|
||||||
entries.emplace_back(preset.label, entries.size());
|
entries.emplace_back(preset.label, entries.size());
|
||||||
|
|
||||||
range_presets.set_options(entries);
|
range_presets.set_options(std::move(entries));
|
||||||
}
|
|
||||||
|
|
||||||
void GlassView::presets_Default() {
|
|
||||||
presets_db.clear();
|
|
||||||
presets_db.push_back({2320, 2560, "DEFAULT WIFI 2.4GHz"});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
@ -72,8 +72,18 @@ class GlassView : public View {
|
|||||||
private:
|
private:
|
||||||
NavigationView& nav_;
|
NavigationView& nav_;
|
||||||
RxRadioState radio_state_{ReceiverModel::Mode::SpectrumAnalysis};
|
RxRadioState radio_state_{ReceiverModel::Mode::SpectrumAnalysis};
|
||||||
|
// Settings
|
||||||
|
rf::Frequency f_min = 260 * MHZ_DIV; // Default to 315/433 remote range.
|
||||||
|
rf::Frequency f_max = 500 * MHZ_DIV;
|
||||||
|
uint8_t preset_index = 0;
|
||||||
app_settings::SettingsManager settings_{
|
app_settings::SettingsManager settings_{
|
||||||
"rx_glass", app_settings::Mode::RX};
|
"rx_glass"sv,
|
||||||
|
app_settings::Mode::RX,
|
||||||
|
{
|
||||||
|
{"min"sv, &f_min},
|
||||||
|
{"max"sv, &f_max},
|
||||||
|
{"preset"sv, &preset_index},
|
||||||
|
}};
|
||||||
|
|
||||||
struct preset_entry {
|
struct preset_entry {
|
||||||
rf::Frequency min{};
|
rf::Frequency min{};
|
||||||
@ -82,8 +92,9 @@ class GlassView : public View {
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::vector<preset_entry> presets_db{};
|
std::vector<preset_entry> presets_db{};
|
||||||
void clip_min(int32_t v);
|
void update_min(int32_t v);
|
||||||
void clip_max(int32_t v);
|
void update_max(int32_t v);
|
||||||
|
void update_range_field();
|
||||||
void get_max_power(const ChannelSpectrum& spectrum, uint8_t bin, uint8_t& max_power);
|
void get_max_power(const ChannelSpectrum& spectrum, uint8_t bin, uint8_t& max_power);
|
||||||
rf::Frequency get_freq_from_bin_pos(uint8_t pos);
|
rf::Frequency get_freq_from_bin_pos(uint8_t pos);
|
||||||
void on_marker_change();
|
void on_marker_change();
|
||||||
@ -94,17 +105,13 @@ class GlassView : public View {
|
|||||||
int64_t next_mult_of(int64_t num, int64_t multiplier);
|
int64_t next_mult_of(int64_t num, int64_t multiplier);
|
||||||
void adjust_range(int64_t* f_min, int64_t* f_max, int64_t width);
|
void adjust_range(int64_t* f_min, int64_t* f_max, int64_t width);
|
||||||
void on_range_changed();
|
void on_range_changed();
|
||||||
void on_lna_changed(int32_t v_db);
|
|
||||||
void on_vga_changed(int32_t v_db);
|
|
||||||
void reset_live_view(bool clear_screen);
|
void reset_live_view(bool clear_screen);
|
||||||
void add_spectrum_pixel(uint8_t power);
|
void add_spectrum_pixel(uint8_t power);
|
||||||
void PlotMarker(uint8_t pos);
|
void plot_marker(uint8_t pos);
|
||||||
void load_Presets();
|
void load_presets();
|
||||||
void txtline_process(std::string& line);
|
void txtline_process(std::string& line);
|
||||||
void populate_Presets();
|
void populate_presets();
|
||||||
void presets_Default();
|
|
||||||
|
|
||||||
rf::Frequency f_min{0}, f_max{0};
|
|
||||||
rf::Frequency search_span{0};
|
rf::Frequency search_span{0};
|
||||||
rf::Frequency f_center{0};
|
rf::Frequency f_center{0};
|
||||||
rf::Frequency f_center_ini{0};
|
rf::Frequency f_center_ini{0};
|
||||||
@ -113,7 +120,7 @@ class GlassView : public View {
|
|||||||
rf::Frequency marker_pixel_step{0};
|
rf::Frequency marker_pixel_step{0};
|
||||||
// size of one spectrum bin in Hz
|
// size of one spectrum bin in Hz
|
||||||
rf::Frequency each_bin_size{0};
|
rf::Frequency each_bin_size{0};
|
||||||
// consumed number of Hz, used to know if we have filled a 'bag' , a corresponding pixel length on screen
|
// consumed number of Hz, used to know if we have filled a 'bag', a corresponding pixel length on screen
|
||||||
rf::Frequency bins_Hz_size{0};
|
rf::Frequency bins_Hz_size{0};
|
||||||
rf::Frequency looking_glass_sampling_rate{0};
|
rf::Frequency looking_glass_sampling_rate{0};
|
||||||
rf::Frequency looking_glass_bandwidth{0};
|
rf::Frequency looking_glass_bandwidth{0};
|
||||||
@ -141,7 +148,7 @@ class GlassView : public View {
|
|||||||
uint8_t ignore_dc = 0;
|
uint8_t ignore_dc = 0;
|
||||||
|
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{0, 0}, "MIN: MAX: LNA VGA ", Color::light_grey()},
|
{{0, 0 * 16}, "MIN: MAX: LNA VGA ", Color::light_grey()},
|
||||||
{{0, 1 * 16}, "RANGE: FILTER: AMP:", Color::light_grey()},
|
{{0, 1 * 16}, "RANGE: FILTER: AMP:", Color::light_grey()},
|
||||||
{{0, 2 * 16}, "PRESET:", Color::light_grey()},
|
{{0, 2 * 16}, "PRESET:", Color::light_grey()},
|
||||||
{{0, 3 * 16}, "MARKER: MHz", Color::light_grey()},
|
{{0, 3 * 16}, "MARKER: MHz", Color::light_grey()},
|
||||||
@ -167,8 +174,8 @@ class GlassView : public View {
|
|||||||
VGAGainField field_vga{
|
VGAGainField field_vga{
|
||||||
{27 * 8, 0 * 16}};
|
{27 * 8, 0 * 16}};
|
||||||
|
|
||||||
Button button_range{
|
TextField field_range{
|
||||||
{7 * 8, 1 * 16, 4 * 8, 16},
|
{6 * 8, 1 * 16, 6 * 8, 16},
|
||||||
""};
|
""};
|
||||||
|
|
||||||
OptionsField filter_config{
|
OptionsField filter_config{
|
||||||
@ -176,23 +183,21 @@ class GlassView : public View {
|
|||||||
4,
|
4,
|
||||||
{
|
{
|
||||||
{"OFF ", 0},
|
{"OFF ", 0},
|
||||||
{"MID ", 118}, // 85 +25 (110) + a bit more to kill all blue
|
{"MID ", 118}, // 85 + 25 (110) + a bit more to kill all blue
|
||||||
{"HIGH", 202}, // 168 + 25 (193)
|
{"HIGH", 202}, // 168 + 25 (193)
|
||||||
}};
|
}};
|
||||||
|
|
||||||
RFAmpField field_rf_amp{
|
RFAmpField field_rf_amp{
|
||||||
{29 * 8, 1 * 16}};
|
{28 * 8, 1 * 16}};
|
||||||
|
|
||||||
OptionsField range_presets{
|
OptionsField range_presets{
|
||||||
{7 * 8, 2 * 16},
|
{7 * 8, 2 * 16},
|
||||||
20,
|
20,
|
||||||
{
|
{}};
|
||||||
{" NONE (WIFI 2.4GHz)", 0},
|
|
||||||
}};
|
|
||||||
|
|
||||||
ButtonWithEncoder button_marker{
|
TextField field_marker{
|
||||||
{7 * 8, 3 * 16, 10 * 8, 16},
|
{7 * 8, 3 * 16, 9 * 8, 16},
|
||||||
" "};
|
""};
|
||||||
|
|
||||||
NumberField field_trigger{
|
NumberField field_trigger{
|
||||||
{4 * 8, 4 * 16},
|
{4 * 8, 4 * 16},
|
||||||
|
@ -1764,6 +1764,15 @@ bool TextField::on_key(KeyEvent key) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TextField::on_encoder(EncoderEvent delta) {
|
||||||
|
if (on_encoder_change) {
|
||||||
|
on_encoder_change(*this, delta);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* NumberField ***********************************************************/
|
/* NumberField ***********************************************************/
|
||||||
|
|
||||||
NumberField::NumberField(
|
NumberField::NumberField(
|
||||||
|
@ -694,6 +694,7 @@ class TextField : public Text {
|
|||||||
public:
|
public:
|
||||||
std::function<void(TextField&)> on_select{};
|
std::function<void(TextField&)> on_select{};
|
||||||
std::function<void(TextField&)> on_change{};
|
std::function<void(TextField&)> on_change{};
|
||||||
|
std::function<void(TextField&, EncoderEvent)> on_encoder_change{};
|
||||||
|
|
||||||
TextField(Rect parent_rect, std::string text);
|
TextField(Rect parent_rect, std::string text);
|
||||||
|
|
||||||
@ -701,6 +702,7 @@ class TextField : public Text {
|
|||||||
void set_text(std::string_view value);
|
void set_text(std::string_view value);
|
||||||
|
|
||||||
bool on_key(KeyEvent key) override;
|
bool on_key(KeyEvent key) override;
|
||||||
|
bool on_encoder(EncoderEvent delta) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Text::set;
|
using Text::set;
|
||||||
|
Loading…
Reference in New Issue
Block a user