mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-08-22 14:37:25 +00:00
Refactor freqman_db parsing (#1244)
* WIP freqman changes/memory perf/stash * Split ui tone_key function out for testing. * Add more tests and fix bugs. * Use default max_entries in recond * Set limit back to 90 for now
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include "soundboard_app.hpp"
|
||||
#include "string_format.hpp"
|
||||
#include "tonesets.hpp"
|
||||
#include "ui_tone_key.hpp"
|
||||
|
||||
using namespace tonekey;
|
||||
using namespace portapack;
|
||||
|
@@ -29,7 +29,6 @@
|
||||
#include "baseband_api.hpp"
|
||||
#include "lfsr_random.hpp"
|
||||
#include "io_wave.hpp"
|
||||
#include "tone_key.hpp"
|
||||
#include "app_settings.hpp"
|
||||
#include "radio_state.hpp"
|
||||
|
||||
|
@@ -25,6 +25,8 @@
|
||||
#include "portapack.hpp"
|
||||
#include "event_m0.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
using namespace portapack;
|
||||
|
||||
namespace ui {
|
||||
@@ -63,7 +65,8 @@ void FreqManBaseView::focus() {
|
||||
}
|
||||
|
||||
void FreqManBaseView::get_freqman_files() {
|
||||
std::vector<std::string>().swap(file_list);
|
||||
// Assume this does change much, clear will preserve the existing alloc.
|
||||
file_list.clear();
|
||||
|
||||
auto files = scan_root_files(u"FREQMAN", u"*.TXT");
|
||||
|
||||
@@ -71,7 +74,7 @@ void FreqManBaseView::get_freqman_files() {
|
||||
std::string file_name = file.stem().string();
|
||||
// don't propose tmp / hidden files in freqman's list
|
||||
if (file_name.length() && file_name[0] != '.') {
|
||||
file_list.emplace_back(file_name);
|
||||
file_list.emplace_back(std::move(file_name));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -81,7 +84,7 @@ void FreqManBaseView::change_category(int32_t category_id) {
|
||||
|
||||
if (file_list.empty()) return;
|
||||
|
||||
if (!load_freqman_file(file_list[categories[category_id].second], database)) {
|
||||
if (!load_freqman_file(file_list[categories[category_id].second], database, {})) {
|
||||
error_ = ERROR_ACCESS;
|
||||
}
|
||||
freqlist_view.set_db(database);
|
||||
@@ -113,13 +116,13 @@ void FrequencySaveView::save_current_file() {
|
||||
|
||||
void FrequencySaveView::on_save_name() {
|
||||
text_prompt(nav_, desc_buffer, 28, [this](std::string& buffer) {
|
||||
database.push_back({value_, 0, buffer, SINGLE});
|
||||
database.push_back(std::make_unique<freqman_entry>(freqman_entry{value_, 0, buffer, freqman_type::Single}));
|
||||
save_current_file();
|
||||
});
|
||||
}
|
||||
|
||||
void FrequencySaveView::on_save_timestamp() {
|
||||
database.push_back({value_, 0, live_timestamp.string(), SINGLE});
|
||||
database.push_back(std::make_unique<freqman_entry>(freqman_entry{value_, 0, live_timestamp.string(), freqman_type::Single}));
|
||||
save_current_file();
|
||||
}
|
||||
|
||||
@@ -159,10 +162,6 @@ FrequencySaveView::FrequencySaveView(
|
||||
};
|
||||
}
|
||||
|
||||
FrequencyLoadView::~FrequencyLoadView() {
|
||||
std::vector<freqman_entry>().swap(database);
|
||||
}
|
||||
|
||||
void FrequencyLoadView::refresh_widgets(const bool v) {
|
||||
freqlist_view.hidden(v);
|
||||
text_empty.hidden(!v);
|
||||
@@ -185,33 +184,32 @@ FrequencyLoadView::FrequencyLoadView(
|
||||
|
||||
freqlist_view.on_select = [&nav, this](FreqManUIList&) {
|
||||
auto& entry = database[freqlist_view.get_index()];
|
||||
if (entry.type == RANGE) {
|
||||
// User chose a frequency range entry
|
||||
if (entry->type == freqman_type::Range) {
|
||||
if (on_range_loaded)
|
||||
on_range_loaded(entry.frequency_a, entry.frequency_b);
|
||||
on_range_loaded(entry->frequency_a, entry->frequency_b);
|
||||
else if (on_frequency_loaded)
|
||||
on_frequency_loaded(entry.frequency_a);
|
||||
// TODO: Maybe return center of range if user choses a range when the app needs a unique frequency, instead of frequency_a ?
|
||||
on_frequency_loaded(entry->frequency_a);
|
||||
// TODO: Maybe return center of range if user choses a range when the app
|
||||
// needs a unique frequency, instead of frequency_a?
|
||||
// TODO: HamRadio?
|
||||
} else {
|
||||
// User chose an unique frequency entry
|
||||
if (on_frequency_loaded)
|
||||
on_frequency_loaded(entry.frequency_a);
|
||||
on_frequency_loaded(entry->frequency_a);
|
||||
}
|
||||
// swap with empty vector to ensure memory is immediately released
|
||||
std::vector<freqman_entry>().swap(database);
|
||||
nav_.pop();
|
||||
|
||||
nav_.pop(); // NB: this will call dtor.
|
||||
};
|
||||
}
|
||||
|
||||
void FrequencyManagerView::on_edit_freq(rf::Frequency f) {
|
||||
database[freqlist_view.get_index()].frequency_a = f;
|
||||
database[freqlist_view.get_index()]->frequency_a = f;
|
||||
save_freqman_file(file_list[categories[current_category_id].second], database);
|
||||
change_category(current_category_id);
|
||||
}
|
||||
|
||||
void FrequencyManagerView::on_edit_desc(NavigationView& nav) {
|
||||
text_prompt(nav, desc_buffer, 28, [this](std::string& buffer) {
|
||||
database[freqlist_view.get_index()].description = buffer;
|
||||
database[freqlist_view.get_index()]->description = std::move(buffer);
|
||||
save_freqman_file(file_list[categories[current_category_id].second], database);
|
||||
change_category(current_category_id);
|
||||
});
|
||||
@@ -277,20 +275,20 @@ FrequencyManagerView::FrequencyManagerView(
|
||||
};
|
||||
|
||||
button_edit_freq.on_select = [this, &nav](Button&) {
|
||||
if (database.empty()) {
|
||||
database.push_back({0, 0, "", SINGLE});
|
||||
}
|
||||
auto new_view = nav.push<FrequencyKeypadView>(database[freqlist_view.get_index()].frequency_a);
|
||||
if (database.empty())
|
||||
database.push_back(std::make_unique<freqman_entry>(freqman_entry{0, 0, "", freqman_type::Single}));
|
||||
|
||||
auto new_view = nav.push<FrequencyKeypadView>(database[freqlist_view.get_index()]->frequency_a);
|
||||
new_view->on_changed = [this](rf::Frequency f) {
|
||||
on_edit_freq(f);
|
||||
};
|
||||
};
|
||||
|
||||
button_edit_desc.on_select = [this, &nav](Button&) {
|
||||
if (database.empty()) {
|
||||
database.push_back({0, 0, "", SINGLE});
|
||||
}
|
||||
desc_buffer = database[freqlist_view.get_index()].description;
|
||||
if (database.empty())
|
||||
database.push_back(std::make_unique<freqman_entry>(freqman_entry{0, 0, "", freqman_type::Single}));
|
||||
|
||||
desc_buffer = database[freqlist_view.get_index()]->description;
|
||||
on_edit_desc(nav);
|
||||
};
|
||||
|
||||
|
@@ -116,7 +116,6 @@ class FrequencyLoadView : public FreqManBaseView {
|
||||
std::function<void(rf::Frequency, rf::Frequency)> on_range_loaded{};
|
||||
|
||||
FrequencyLoadView(NavigationView& nav);
|
||||
~FrequencyLoadView();
|
||||
|
||||
std::string title() const override { return "Load freq."; };
|
||||
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include "file.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
using namespace tonekey;
|
||||
using portapack::memory::map::backup_ram;
|
||||
|
||||
namespace ui {
|
||||
|
@@ -22,21 +22,20 @@
|
||||
|
||||
#include "ui_mictx.hpp"
|
||||
|
||||
#include "baseband_api.hpp"
|
||||
#include "audio.hpp"
|
||||
|
||||
#include "wm8731.hpp"
|
||||
using wolfson::wm8731::WM8731;
|
||||
|
||||
#include "tonesets.hpp"
|
||||
#include "baseband_api.hpp"
|
||||
#include "irq_controls.hpp"
|
||||
#include "portapack_hal.hpp"
|
||||
#include "string_format.hpp"
|
||||
#include "irq_controls.hpp"
|
||||
#include "tonesets.hpp"
|
||||
#include "ui_tone_key.hpp"
|
||||
#include "wm8731.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
using namespace tonekey;
|
||||
using namespace portapack;
|
||||
using wolfson::wm8731::WM8731;
|
||||
|
||||
WM8731 audio_codec_wm8731{i2c0, 0x1a};
|
||||
|
||||
|
@@ -35,7 +35,6 @@
|
||||
#include "ui_navigation.hpp"
|
||||
#include "ui_receiver.hpp"
|
||||
#include "transmitter_model.hpp"
|
||||
#include "tone_key.hpp"
|
||||
#include "message.hpp"
|
||||
#include "receiver_model.hpp"
|
||||
#include "ui_transmitter.hpp"
|
||||
|
@@ -23,14 +23,24 @@
|
||||
|
||||
#include "ui_recon.hpp"
|
||||
#include "ui_fileman.hpp"
|
||||
#include "file.hpp"
|
||||
#include "capture_app.hpp"
|
||||
#include "file.hpp"
|
||||
#include "tone_key.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
using namespace tonekey;
|
||||
using portapack::memory::map::backup_ram;
|
||||
|
||||
namespace ui {
|
||||
|
||||
bool ReconView::current_is_valid() {
|
||||
return (unsigned)current_index < frequency_list.size();
|
||||
}
|
||||
|
||||
freqman_entry& ReconView::current_entry() {
|
||||
return *frequency_list[current_index];
|
||||
}
|
||||
|
||||
void ReconView::set_loop_config(bool v) {
|
||||
continuous = v;
|
||||
button_loop_config.set_style(v ? &Styles::green : &Styles::white);
|
||||
@@ -56,22 +66,41 @@ void ReconView::clear_freqlist_for_ui_action() {
|
||||
audio::output::stop();
|
||||
// flag to detect and reload frequency_list
|
||||
if (!manual_mode) {
|
||||
// clear and shrink_to_fit are not enough to really start with a new, clean, empty vector
|
||||
// swap is the only way to achieve a perfect memory liberation
|
||||
std::vector<freqman_entry>().swap(frequency_list);
|
||||
// Clear doesn't actually free, re-assign so destructor runs on previous instance.
|
||||
frequency_list = freqman_db{};
|
||||
} else
|
||||
frequency_list.shrink_to_fit();
|
||||
freqlist_cleared_for_ui_action = true;
|
||||
}
|
||||
|
||||
void ReconView::reset_indexes() {
|
||||
last_entry.modulation = -1;
|
||||
last_entry.bandwidth = -1;
|
||||
last_entry.step = -1;
|
||||
description = "...no description...";
|
||||
last_entry.modulation = freqman_invalid_index;
|
||||
last_entry.bandwidth = freqman_invalid_index;
|
||||
last_entry.step = freqman_invalid_index;
|
||||
current_index = 0;
|
||||
}
|
||||
|
||||
void ReconView::update_description() {
|
||||
if (frequency_list.empty() || current_entry().description.empty()) {
|
||||
description = "...no description...";
|
||||
return;
|
||||
} else {
|
||||
switch (current_entry().type) {
|
||||
case freqman_type::Range:
|
||||
description = "R: ";
|
||||
break;
|
||||
case freqman_type::HamRadio:
|
||||
description = "H: ";
|
||||
break;
|
||||
default:
|
||||
description = "S: ";
|
||||
}
|
||||
description += current_entry().description;
|
||||
}
|
||||
|
||||
desc_cycle.set(description);
|
||||
}
|
||||
|
||||
void ReconView::colorize_waits() {
|
||||
// colorize wait on match
|
||||
if (wait == 0) {
|
||||
@@ -98,15 +127,15 @@ void ReconView::colorize_waits() {
|
||||
bool ReconView::recon_save_freq(const std::string& freq_file_path, size_t freq_index, bool warn_if_exists) {
|
||||
File recon_file;
|
||||
|
||||
if (frequency_list.size() == 0 || (frequency_list.size() && current_index > (int32_t)frequency_list.size()))
|
||||
if (frequency_list.size() == 0 || !current_is_valid())
|
||||
return false;
|
||||
|
||||
freqman_entry entry = frequency_list[freq_index];
|
||||
freqman_entry entry = *frequency_list[freq_index]; // Makes a copy.
|
||||
entry.frequency_a = freq;
|
||||
entry.frequency_b = 0;
|
||||
entry.modulation = last_entry.modulation;
|
||||
entry.bandwidth = last_entry.bandwidth;
|
||||
entry.type = SINGLE;
|
||||
entry.type = freqman_type::Single;
|
||||
|
||||
std::string frequency_to_add;
|
||||
get_freq_string(entry, frequency_to_add);
|
||||
@@ -176,7 +205,7 @@ bool ReconView::recon_load_config_from_sd() {
|
||||
pos = line_start;
|
||||
while ((line_end = strstr(line_start, "\x0A"))) {
|
||||
length = line_end - line_start - 1;
|
||||
params[it] = string(pos, length);
|
||||
params[it] = std::string(pos, length);
|
||||
it++;
|
||||
line_start = line_end + 1;
|
||||
pos = line_start;
|
||||
@@ -311,53 +340,38 @@ void ReconView::handle_retune() {
|
||||
receiver_model.set_target_frequency(freq); // Retune
|
||||
}
|
||||
if (frequency_list.size() > 0) {
|
||||
if (last_entry.modulation != frequency_list[current_index].modulation && frequency_list[current_index].modulation >= 0) {
|
||||
last_entry.modulation = frequency_list[current_index].modulation;
|
||||
field_mode.set_selected_index(frequency_list[current_index].modulation);
|
||||
last_entry.bandwidth = -1;
|
||||
if (last_entry.modulation != current_entry().modulation && is_valid(current_entry().modulation)) {
|
||||
last_entry.modulation = current_entry().modulation;
|
||||
field_mode.set_selected_index(current_entry().modulation);
|
||||
last_entry.bandwidth = freqman_invalid_index;
|
||||
}
|
||||
// Set bandwidth if any
|
||||
if (last_entry.bandwidth != frequency_list[current_index].bandwidth && frequency_list[current_index].bandwidth >= 0) {
|
||||
last_entry.bandwidth = frequency_list[current_index].bandwidth;
|
||||
field_bw.set_selected_index(frequency_list[current_index].bandwidth);
|
||||
if (last_entry.bandwidth != current_entry().bandwidth && is_valid(current_entry().bandwidth)) {
|
||||
last_entry.bandwidth = current_entry().bandwidth;
|
||||
field_bw.set_selected_index(current_entry().bandwidth);
|
||||
}
|
||||
if (last_entry.step != frequency_list[current_index].step && frequency_list[current_index].step >= 0) {
|
||||
last_entry.step = frequency_list[current_index].step;
|
||||
if (last_entry.step != current_entry().step && is_valid(current_entry().step)) {
|
||||
last_entry.step = current_entry().step;
|
||||
step = freqman_entry_get_step_value(last_entry.step);
|
||||
step_mode.set_selected_index(step);
|
||||
}
|
||||
if (last_index != current_index) {
|
||||
last_index = current_index;
|
||||
if ((int32_t)frequency_list.size() && current_index < (int32_t)frequency_list.size() && frequency_list[current_index].type == RANGE) {
|
||||
if (frequency_list.size() && current_is_valid() && current_entry().type == freqman_type::Range) {
|
||||
if (update_ranges && !manual_mode) {
|
||||
button_manual_start.set_text(to_string_short_freq(frequency_list[current_index].frequency_a));
|
||||
frequency_range.min = frequency_list[current_index].frequency_a;
|
||||
if (frequency_list[current_index].frequency_b != 0) {
|
||||
button_manual_end.set_text(to_string_short_freq(frequency_list[current_index].frequency_b));
|
||||
frequency_range.max = frequency_list[current_index].frequency_b;
|
||||
button_manual_start.set_text(to_string_short_freq(current_entry().frequency_a));
|
||||
frequency_range.min = current_entry().frequency_a;
|
||||
if (current_entry().frequency_b != 0) {
|
||||
button_manual_end.set_text(to_string_short_freq(current_entry().frequency_b));
|
||||
frequency_range.max = current_entry().frequency_b;
|
||||
} else {
|
||||
button_manual_end.set_text(to_string_short_freq(frequency_list[current_index].frequency_a));
|
||||
frequency_range.max = frequency_list[current_index].frequency_a;
|
||||
button_manual_end.set_text(to_string_short_freq(current_entry().frequency_a));
|
||||
frequency_range.max = current_entry().frequency_a;
|
||||
}
|
||||
}
|
||||
}
|
||||
text_cycle.set_text(to_string_dec_uint(current_index + 1, 3));
|
||||
if (frequency_list[current_index].description.size() > 0) {
|
||||
switch (frequency_list[current_index].type) {
|
||||
case RANGE:
|
||||
desc_cycle.set("R: " + frequency_list[current_index].description); // Show new description
|
||||
break;
|
||||
case HAMRADIO:
|
||||
desc_cycle.set("H: " + frequency_list[current_index].description); // Show new description
|
||||
break;
|
||||
default:
|
||||
case SINGLE:
|
||||
desc_cycle.set("S: " + frequency_list[current_index].description); // Show new description
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
desc_cycle.set("...no description..."); // Show new description
|
||||
}
|
||||
update_description();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -576,11 +590,11 @@ ReconView::ReconView(NavigationView& nav)
|
||||
// TODO: *BUG* Both transmitter_model and receiver_model share the same pmem setting for target_frequency.
|
||||
button_mic_app.on_select = [this](Button&) {
|
||||
if (frequency_list.size() > 0 && current_index >= 0 && (unsigned)current_index < frequency_list.size()) {
|
||||
if (frequency_list[current_index].type == HAMRADIO) {
|
||||
// if it's a HAMRADIO entry, then frequency_a is the freq at which the repeater receives, so we have to set it in transmit in mic app
|
||||
transmitter_model.set_target_frequency(frequency_list[current_index].frequency_a);
|
||||
// if it's a HAMRADIO entry, then frequency_b is the freq at which the repeater transmits, so we have to set it in receive in mic app
|
||||
receiver_model.set_target_frequency(frequency_list[current_index].frequency_b);
|
||||
if (current_entry().type == freqman_type::HamRadio) {
|
||||
// if it's a HamRadio entry, then frequency_a is the freq at which the repeater receives, so we have to set it in transmit in mic app
|
||||
transmitter_model.set_target_frequency(current_entry().frequency_a);
|
||||
// if it's a HamRadio entry, then frequency_b is the freq at which the repeater transmits, so we have to set it in receive in mic app
|
||||
receiver_model.set_target_frequency(current_entry().frequency_b);
|
||||
} else {
|
||||
// it's single or range so we us actual tuned frequency
|
||||
transmitter_model.set_target_frequency(freq);
|
||||
@@ -605,23 +619,8 @@ ReconView::ReconView(NavigationView& nav)
|
||||
current_index = frequency_list.size() - 1;
|
||||
}
|
||||
if (frequency_list.size() > 0) {
|
||||
if (frequency_list[current_index].description.size() > 0) {
|
||||
switch (frequency_list[current_index].type) {
|
||||
case RANGE:
|
||||
desc_cycle.set("R: " + frequency_list[current_index].description);
|
||||
break;
|
||||
case HAMRADIO:
|
||||
desc_cycle.set("H: " + frequency_list[current_index].description);
|
||||
break;
|
||||
default:
|
||||
case SINGLE:
|
||||
desc_cycle.set("S: " + frequency_list[current_index].description);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
desc_cycle.set("...no description...");
|
||||
}
|
||||
text_cycle.set_text(to_string_dec_uint(current_index + 1, 3));
|
||||
update_description();
|
||||
}
|
||||
// also remove from output file if in scanner mode
|
||||
if (scanner_mode) {
|
||||
@@ -631,7 +630,7 @@ ReconView::ReconView(NavigationView& nav)
|
||||
if (!result.is_valid()) {
|
||||
for (size_t n = 0; n < frequency_list.size(); n++) {
|
||||
std::string line;
|
||||
get_freq_string(frequency_list[n], line);
|
||||
get_freq_string(*frequency_list[n], line);
|
||||
freqman_file.write_line(line);
|
||||
}
|
||||
}
|
||||
@@ -643,12 +642,12 @@ ReconView::ReconView(NavigationView& nav)
|
||||
std::string tmp_freq_file_path{freq_file_path + ".TMP"};
|
||||
std::string frequency_to_add{};
|
||||
|
||||
freqman_entry entry = frequency_list[current_index];
|
||||
freqman_entry entry = current_entry();
|
||||
entry.frequency_a = freq;
|
||||
entry.frequency_b = 0;
|
||||
entry.modulation = last_entry.modulation;
|
||||
entry.bandwidth = last_entry.bandwidth;
|
||||
entry.type = SINGLE;
|
||||
entry.type = freqman_type::Single;
|
||||
|
||||
get_freq_string(entry, frequency_to_add);
|
||||
|
||||
@@ -683,7 +682,7 @@ ReconView::ReconView(NavigationView& nav)
|
||||
}
|
||||
}
|
||||
}
|
||||
receiver_model.set_target_frequency(frequency_list[current_index].frequency_a); // retune
|
||||
receiver_model.set_target_frequency(current_entry().frequency_a); // retune
|
||||
}
|
||||
if (frequency_list.size() == 0) {
|
||||
text_cycle.set_text(" ");
|
||||
@@ -711,25 +710,23 @@ ReconView::ReconView(NavigationView& nav)
|
||||
} else {
|
||||
if (field_mode.selected_index_value() != SPEC_MODULATION)
|
||||
audio::output::stop();
|
||||
// clear and shrink_to_fit are not enough to really start with a new, clean, empty vector
|
||||
// swap is the only way to achieve a perfect memory liberation
|
||||
std::vector<freqman_entry>().swap(frequency_list);
|
||||
|
||||
freqman_entry manual_freq_entry;
|
||||
// Clear doesn't actually free, re-assign so destructor runs on previous instance.
|
||||
frequency_list = freqman_db{};
|
||||
current_index = 0;
|
||||
frequency_list.push_back(std::make_unique<freqman_entry>());
|
||||
|
||||
def_step = step_mode.selected_index(); // max range val
|
||||
|
||||
manual_freq_entry.type = RANGE;
|
||||
manual_freq_entry.description =
|
||||
to_string_short_freq(frequency_range.min).erase(0, 1) + ">" + to_string_short_freq(frequency_range.max).erase(0, 1) + " S:" // current Manual range
|
||||
+ freqman_entry_get_step_string_short(def_step); // euquiq: lame kludge to reduce spacing in step freq
|
||||
manual_freq_entry.frequency_a = frequency_range.min; // min range val
|
||||
manual_freq_entry.frequency_b = frequency_range.max; // max range val
|
||||
manual_freq_entry.modulation = -1;
|
||||
manual_freq_entry.bandwidth = -1;
|
||||
manual_freq_entry.step = def_step;
|
||||
|
||||
frequency_list.push_back(manual_freq_entry);
|
||||
def_step = step_mode.selected_index();
|
||||
current_entry().type = freqman_type::Range;
|
||||
current_entry().description =
|
||||
to_string_short_freq(frequency_range.min).erase(0, 1) + ">" + // euquiq: lame kludge to reduce spacing in step freq
|
||||
to_string_short_freq(frequency_range.max).erase(0, 1) + " S:" +
|
||||
freqman_entry_get_step_string_short(def_step);
|
||||
current_entry().frequency_a = frequency_range.min;
|
||||
current_entry().frequency_b = frequency_range.max;
|
||||
current_entry().modulation = freqman_invalid_index;
|
||||
current_entry().bandwidth = freqman_invalid_index;
|
||||
current_entry().step = def_step;
|
||||
|
||||
big_display.set_style(&Styles::white); // Back to white color
|
||||
|
||||
@@ -744,13 +741,12 @@ ReconView::ReconView(NavigationView& nav)
|
||||
file_name.set("MANUAL RANGE RECON");
|
||||
desc_cycle.set_style(&Styles::white);
|
||||
|
||||
last_entry.modulation = -1;
|
||||
last_entry.bandwidth = -1;
|
||||
last_entry.step = -1;
|
||||
last_entry.modulation = freqman_invalid_index;
|
||||
last_entry.bandwidth = freqman_invalid_index;
|
||||
last_entry.step = freqman_invalid_index;
|
||||
last_index = -1;
|
||||
|
||||
current_index = 0;
|
||||
freq = manual_freq_entry.frequency_a;
|
||||
freq = current_entry().frequency_a;
|
||||
handle_retune();
|
||||
recon_redraw();
|
||||
recon_resume();
|
||||
@@ -795,7 +791,7 @@ ReconView::ReconView(NavigationView& nav)
|
||||
}
|
||||
};
|
||||
|
||||
button_add.on_select = [this](ButtonWithEncoder&) { // frequency_list[current_index]
|
||||
button_add.on_select = [this](ButtonWithEncoder&) {
|
||||
if (!scanner_mode) {
|
||||
recon_save_freq(freq_file_path, current_index, true);
|
||||
}
|
||||
@@ -945,7 +941,11 @@ void ReconView::frequency_file_load(bool stop_all_before) {
|
||||
desc_cycle.set_style(&Styles::blue);
|
||||
button_scanner_mode.set_text("RECON");
|
||||
}
|
||||
if (!load_freqman_file(file_input, frequency_list, load_freqs, load_ranges, load_hamradios)) {
|
||||
freqman_load_options options{
|
||||
.load_freqs = load_freqs,
|
||||
.load_ranges = load_ranges,
|
||||
.load_hamradios = load_hamradios};
|
||||
if (!load_freqman_file(file_input, frequency_list, options)) {
|
||||
file_name.set_style(&Styles::red);
|
||||
desc_cycle.set(" NO " + file_input + ".TXT FILE ...");
|
||||
file_name.set("=> NO DATA");
|
||||
@@ -962,71 +962,39 @@ void ReconView::frequency_file_load(bool stop_all_before) {
|
||||
}
|
||||
}
|
||||
|
||||
if (frequency_list[0].step >= 0)
|
||||
step = freqman_entry_get_step_value(frequency_list[0].step);
|
||||
else
|
||||
step = freqman_entry_get_step_value(def_step);
|
||||
|
||||
switch (frequency_list[0].type) {
|
||||
case SINGLE:
|
||||
freq = frequency_list[0].frequency_a;
|
||||
break;
|
||||
case RANGE:
|
||||
minfreq = frequency_list[0].frequency_a;
|
||||
maxfreq = frequency_list[0].frequency_b;
|
||||
if (fwd) {
|
||||
freq = minfreq;
|
||||
} else {
|
||||
freq = maxfreq;
|
||||
}
|
||||
if (frequency_list[0].step >= 0)
|
||||
step = freqman_entry_get_step_value(frequency_list[0].step);
|
||||
break;
|
||||
case HAMRADIO:
|
||||
minfreq = frequency_list[0].frequency_a;
|
||||
maxfreq = frequency_list[0].frequency_b;
|
||||
if (fwd) {
|
||||
freq = minfreq;
|
||||
} else {
|
||||
freq = maxfreq;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (frequency_list.empty()) {
|
||||
text_cycle.set_text(" ");
|
||||
return; // Can't really do much.
|
||||
}
|
||||
|
||||
reset_indexes();
|
||||
step = freqman_entry_get_step_value(
|
||||
is_valid(current_entry().step) ? current_entry().step : def_step);
|
||||
|
||||
if (current_entry().type == freqman_type::Single) {
|
||||
freq = current_entry().frequency_a;
|
||||
} else if (current_entry().type != freqman_type::Unknown) {
|
||||
minfreq = current_entry().frequency_a;
|
||||
maxfreq = current_entry().frequency_b;
|
||||
freq = fwd ? minfreq : maxfreq;
|
||||
}
|
||||
|
||||
step_mode.set_selected_index(def_step); // Impose the default step into the manual step selector
|
||||
receiver_model.enable();
|
||||
receiver_model.set_squelch_level(0);
|
||||
if (frequency_list.size() != 0) {
|
||||
switch (frequency_list[current_index].type) {
|
||||
case RANGE:
|
||||
description = "R: " + frequency_list[current_index].description;
|
||||
break;
|
||||
case HAMRADIO:
|
||||
description = "H: " + frequency_list[current_index].description;
|
||||
break;
|
||||
default:
|
||||
case SINGLE:
|
||||
description = "S: " + frequency_list[current_index].description;
|
||||
break;
|
||||
text_cycle.set_text(to_string_dec_uint(current_index + 1, 3));
|
||||
if (update_ranges && !manual_mode) {
|
||||
button_manual_start.set_text(to_string_short_freq(current_entry().frequency_a));
|
||||
frequency_range.min = current_entry().frequency_a;
|
||||
if (current_entry().frequency_b != 0) {
|
||||
button_manual_end.set_text(to_string_short_freq(current_entry().frequency_b));
|
||||
frequency_range.max = current_entry().frequency_b;
|
||||
} else {
|
||||
button_manual_end.set_text(to_string_short_freq(current_entry().frequency_a));
|
||||
frequency_range.max = current_entry().frequency_a;
|
||||
}
|
||||
text_cycle.set_text(to_string_dec_uint(current_index + 1, 3));
|
||||
if (update_ranges && !manual_mode) {
|
||||
button_manual_start.set_text(to_string_short_freq(frequency_list[current_index].frequency_a));
|
||||
frequency_range.min = frequency_list[current_index].frequency_a;
|
||||
if (frequency_list[current_index].frequency_b != 0) {
|
||||
button_manual_end.set_text(to_string_short_freq(frequency_list[current_index].frequency_b));
|
||||
frequency_range.max = frequency_list[current_index].frequency_b;
|
||||
} else {
|
||||
button_manual_end.set_text(to_string_short_freq(frequency_list[current_index].frequency_a));
|
||||
frequency_range.max = frequency_list[current_index].frequency_a;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
text_cycle.set_text(" ");
|
||||
}
|
||||
desc_cycle.set(description);
|
||||
update_description();
|
||||
handle_retune();
|
||||
}
|
||||
|
||||
@@ -1156,7 +1124,7 @@ void ReconView::on_statistics_update(const ChannelStatistics& statistics) {
|
||||
if (recon || stepper != 0 || index_stepper != 0) {
|
||||
if (index_stepper == 0) {
|
||||
/* we are doing a range */
|
||||
if (frequency_list[current_index].type == RANGE) {
|
||||
if (current_entry().type == freqman_type::Range) {
|
||||
if ((fwd && stepper == 0) || stepper > 0) {
|
||||
// forward
|
||||
freq += step;
|
||||
@@ -1186,7 +1154,7 @@ void ReconView::on_statistics_update(const ChannelStatistics& statistics) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (frequency_list[current_index].type == SINGLE) {
|
||||
} else if (current_entry().type == freqman_type::Single) {
|
||||
if ((fwd && stepper == 0) || stepper > 0) { // forward
|
||||
current_index++;
|
||||
entry_has_changed = true;
|
||||
@@ -1205,7 +1173,7 @@ void ReconView::on_statistics_update(const ChannelStatistics& statistics) {
|
||||
current_index = frequency_list.size() - 1;
|
||||
}
|
||||
}
|
||||
} else if (frequency_list[current_index].type == HAMRADIO) {
|
||||
} else if (current_entry().type == freqman_type::HamRadio) {
|
||||
if ((fwd && stepper == 0) || stepper > 0) { // forward
|
||||
if ((minfreq != maxfreq) && freq == minfreq) {
|
||||
freq = maxfreq;
|
||||
@@ -1259,22 +1227,22 @@ void ReconView::on_statistics_update(const ChannelStatistics& statistics) {
|
||||
// reload entry if changed
|
||||
if (entry_has_changed) {
|
||||
timer = 0;
|
||||
switch (frequency_list[current_index].type) {
|
||||
case SINGLE:
|
||||
freq = frequency_list[current_index].frequency_a;
|
||||
switch (current_entry().type) {
|
||||
case freqman_type::Single:
|
||||
freq = current_entry().frequency_a;
|
||||
break;
|
||||
case RANGE:
|
||||
minfreq = frequency_list[current_index].frequency_a;
|
||||
maxfreq = frequency_list[current_index].frequency_b;
|
||||
case freqman_type::Range:
|
||||
minfreq = current_entry().frequency_a;
|
||||
maxfreq = current_entry().frequency_b;
|
||||
if ((fwd && !stepper && !index_stepper) || stepper > 0 || index_stepper > 0) {
|
||||
freq = minfreq;
|
||||
} else if ((!fwd && !stepper && !index_stepper) || stepper < 0 || index_stepper < 0) {
|
||||
freq = maxfreq;
|
||||
}
|
||||
break;
|
||||
case HAMRADIO:
|
||||
minfreq = frequency_list[current_index].frequency_a;
|
||||
maxfreq = frequency_list[current_index].frequency_b;
|
||||
case freqman_type::HamRadio:
|
||||
minfreq = current_entry().frequency_a;
|
||||
maxfreq = current_entry().frequency_b;
|
||||
if ((fwd && !stepper && !index_stepper) || stepper > 0 || index_stepper > 0) {
|
||||
freq = minfreq;
|
||||
} else if ((!fwd && !stepper && !index_stepper) || stepper < 0 || index_stepper < 0) {
|
||||
|
@@ -67,6 +67,7 @@ class ReconView : public View {
|
||||
void set_loop_config(bool v);
|
||||
void clear_freqlist_for_ui_action();
|
||||
void reset_indexes();
|
||||
void update_description();
|
||||
void audio_output_start();
|
||||
bool check_sd_card();
|
||||
size_t change_mode(freqman_index_t mod_type);
|
||||
@@ -87,6 +88,10 @@ class ReconView : public View {
|
||||
// placeholder for possible void recon_start_recording();
|
||||
void recon_stop_recording();
|
||||
|
||||
// Returns true if 'current_index' is in bounds of frequency_list.
|
||||
bool current_is_valid();
|
||||
freqman_entry& current_entry();
|
||||
|
||||
jammer::jammer_range_t frequency_range{false, 0, MAX_UFREQ}; // perfect for manual recon task too...
|
||||
int32_t squelch{0};
|
||||
int32_t db{0};
|
||||
|
@@ -318,7 +318,7 @@ ScannerView::ScannerView(
|
||||
std::string dir_filter = "FREQMAN/";
|
||||
std::string str_file_path = new_file_path.string();
|
||||
|
||||
if (str_file_path.find(dir_filter) != string::npos) { // assert file from the FREQMAN folder
|
||||
if (str_file_path.find(dir_filter) != std::string::npos) { // assert file from the FREQMAN folder
|
||||
scan_pause();
|
||||
// get the filename without txt extension so we can use load_freqman_file fcn
|
||||
std::string str_file_name = new_file_path.stem().string();
|
||||
@@ -576,9 +576,9 @@ ScannerView::ScannerView(
|
||||
void ScannerView::frequency_file_load(std::string file_name, bool stop_all_before) {
|
||||
bool found_range{false};
|
||||
bool found_single{false};
|
||||
freqman_index_t def_mod_index{-1};
|
||||
freqman_index_t def_bw_index{-1};
|
||||
freqman_index_t def_step_index{-1};
|
||||
freqman_index_t def_mod_index{freqman_invalid_index};
|
||||
freqman_index_t def_bw_index{freqman_invalid_index};
|
||||
freqman_index_t def_step_index{freqman_invalid_index};
|
||||
|
||||
// stop everything running now if required
|
||||
if (stop_all_before) {
|
||||
@@ -587,56 +587,56 @@ void ScannerView::frequency_file_load(std::string file_name, bool stop_all_befor
|
||||
description_list.clear();
|
||||
}
|
||||
|
||||
if (load_freqman_file(file_name, database)) {
|
||||
loaded_file_name = file_name; // keep loaded filename in memory
|
||||
for (auto& entry : database) { // READ LINE PER LINE
|
||||
if (frequency_list.size() < FREQMAN_MAX_PER_FILE) { // We got space!
|
||||
//
|
||||
// Get modulation & bw & step from file if specified
|
||||
// Note these values could be different for each line in the file, but we only look at the first one
|
||||
//
|
||||
// Note that freqman requires a very specific string for these parameters,
|
||||
// so check syntax in frequency file if specified value isn't being loaded
|
||||
//
|
||||
if (def_mod_index == -1)
|
||||
def_mod_index = entry.modulation;
|
||||
if (load_freqman_file(file_name, database, {})) {
|
||||
loaded_file_name = file_name;
|
||||
for (auto& entry_ptr : database) {
|
||||
if (frequency_list.size() >= FREQMAN_MAX_PER_FILE)
|
||||
break;
|
||||
|
||||
if (def_bw_index == -1)
|
||||
def_bw_index = entry.bandwidth;
|
||||
auto& entry = *entry_ptr;
|
||||
|
||||
if (def_step_index == -1)
|
||||
def_step_index = entry.step;
|
||||
// Get modulation & bw & step from file if specified
|
||||
// Note these values could be different for each line in the file, but we only look at the first one
|
||||
//
|
||||
// Note that freqman requires a very specific string for these parameters,
|
||||
// so check syntax in frequency file if specified value isn't being loaded
|
||||
//
|
||||
if (is_invalid(def_mod_index))
|
||||
def_mod_index = entry.modulation;
|
||||
|
||||
// Get frequency
|
||||
if (entry.type == RANGE) {
|
||||
if (!found_range) {
|
||||
// Set Start & End Search Range instead of populating the small in-memory frequency table
|
||||
// NOTE: There may be multiple single frequencies in file, but only one search range is supported.
|
||||
found_range = true;
|
||||
frequency_range.min = entry.frequency_a;
|
||||
button_manual_start.set_text(to_string_short_freq(frequency_range.min));
|
||||
frequency_range.max = entry.frequency_b;
|
||||
button_manual_end.set_text(to_string_short_freq(frequency_range.max));
|
||||
}
|
||||
} else if (entry.type == SINGLE) {
|
||||
found_single = true;
|
||||
frequency_list.push_back(entry.frequency_a);
|
||||
description_list.push_back(entry.description);
|
||||
} else if (entry.type == HAMRADIO) {
|
||||
// For HAM repeaters, add both receive & transmit frequencies to scan list and modify description
|
||||
// (FUTURE fw versions might handle these differently)
|
||||
found_single = true;
|
||||
frequency_list.push_back(entry.frequency_a);
|
||||
description_list.push_back("R:" + entry.description);
|
||||
if (is_invalid(def_bw_index))
|
||||
def_bw_index = entry.bandwidth;
|
||||
|
||||
if ((entry.frequency_a != entry.frequency_b) &&
|
||||
(frequency_list.size() < FREQMAN_MAX_PER_FILE)) {
|
||||
frequency_list.push_back(entry.frequency_b);
|
||||
description_list.push_back("T:" + entry.description);
|
||||
}
|
||||
if (is_invalid(def_step_index))
|
||||
def_step_index = entry.step;
|
||||
|
||||
// Get frequency
|
||||
if (entry.type == freqman_type::Range) {
|
||||
if (!found_range) {
|
||||
// Set Start & End Search Range instead of populating the small in-memory frequency table
|
||||
// NOTE: There may be multiple single frequencies in file, but only one search range is supported.
|
||||
found_range = true;
|
||||
frequency_range.min = entry.frequency_a;
|
||||
button_manual_start.set_text(to_string_short_freq(frequency_range.min));
|
||||
frequency_range.max = entry.frequency_b;
|
||||
button_manual_end.set_text(to_string_short_freq(frequency_range.max));
|
||||
}
|
||||
} else if (entry.type == freqman_type::Single) {
|
||||
found_single = true;
|
||||
frequency_list.push_back(entry.frequency_a);
|
||||
description_list.push_back(entry.description);
|
||||
} else if (entry.type == freqman_type::HamRadio) {
|
||||
// For HAM repeaters, add both receive & transmit frequencies to scan list and modify description
|
||||
// (FUTURE fw versions might handle these differently)
|
||||
found_single = true;
|
||||
frequency_list.push_back(entry.frequency_a);
|
||||
description_list.push_back("R:" + entry.description);
|
||||
|
||||
if ((entry.frequency_a != entry.frequency_b) &&
|
||||
(frequency_list.size() < FREQMAN_MAX_PER_FILE)) {
|
||||
frequency_list.push_back(entry.frequency_b);
|
||||
description_list.push_back("T:" + entry.description);
|
||||
}
|
||||
} else {
|
||||
break; // No more space: Stop reading the txt file !
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -650,13 +650,13 @@ void ScannerView::frequency_file_load(std::string file_name, bool stop_all_befor
|
||||
desc_freq_list_scan = desc_freq_list_scan + "...";
|
||||
}
|
||||
|
||||
if ((def_mod_index != -1) && (def_mod_index != (freqman_index_t)field_mode.selected_index_value()))
|
||||
if (is_valid(def_mod_index) && def_mod_index != (freqman_index_t)field_mode.selected_index_value())
|
||||
field_mode.set_by_value(def_mod_index); // Update mode (also triggers a change callback that disables & reenables RF background)
|
||||
|
||||
if (def_bw_index != -1) // Update BW if specified in file
|
||||
if (is_valid(def_bw_index)) // Update BW if specified in file
|
||||
field_bw.set_selected_index(def_bw_index);
|
||||
|
||||
if (def_step_index != -1) // Update step if specified in file
|
||||
if (is_valid(def_step_index)) // Update step if specified in file
|
||||
field_step.set_selected_index(def_step_index);
|
||||
|
||||
audio::output::stop();
|
||||
|
@@ -90,7 +90,7 @@ class ScannerView : public View {
|
||||
|
||||
std::string title() const override { return "Scanner"; };
|
||||
std::vector<rf::Frequency> frequency_list{};
|
||||
std::vector<string> description_list{};
|
||||
std::vector<std::string> description_list{};
|
||||
|
||||
// void set_parent_rect(const Rect new_parent_rect) override;
|
||||
|
||||
|
Reference in New Issue
Block a user