mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-08-14 23:17:49 +00:00
Freqman improvements (#1276)
* Show .1 MHz in pretty freqman string * Refactor load to user FreqmanDB * Recon file parsing cleanup * use strtol for parse_int * recon file cleanup * Fix bugs in Recon changes * PR feedback --------- Co-authored-by: kallanreed <kallanreed@noreply.github.com>
This commit is contained in:
@@ -25,10 +25,10 @@
|
||||
#include "audio.hpp"
|
||||
#include "baseband_api.hpp"
|
||||
#include "file.hpp"
|
||||
#include "freqman.hpp"
|
||||
#include "portapack.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
#include "string_format.hpp"
|
||||
#include "ui_freqman.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include "capture_app.hpp"
|
||||
#include "baseband_api.hpp"
|
||||
#include "portapack.hpp"
|
||||
#include "ui_freqman.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
|
||||
|
@@ -31,7 +31,6 @@
|
||||
#include "ui_spectrum.hpp"
|
||||
#include "app_settings.hpp"
|
||||
#include "radio_state.hpp"
|
||||
#include "freqman.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
|
@@ -24,7 +24,6 @@
|
||||
#include "ui_freqman.hpp"
|
||||
|
||||
#include "event_m0.hpp"
|
||||
#include "freqman.hpp"
|
||||
#include "portapack.hpp"
|
||||
#include "rtc_time.hpp"
|
||||
#include "tone_key.hpp"
|
||||
@@ -35,11 +34,33 @@
|
||||
#include <memory>
|
||||
|
||||
using namespace portapack;
|
||||
using namespace ui;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
// TODO: Clean up after moving to better lookup tables.
|
||||
extern ui::OptionsField::options_t freqman_bandwidths[4];
|
||||
extern ui::OptionsField::options_t freqman_steps;
|
||||
using options_t = OptionsField::options_t;
|
||||
extern options_t freqman_modulations;
|
||||
extern options_t freqman_bandwidths[4];
|
||||
extern options_t freqman_steps;
|
||||
extern options_t freqman_steps_short;
|
||||
|
||||
/* Set options. */
|
||||
void freqman_set_modulation_option(OptionsField& option) {
|
||||
option.set_options(freqman_modulations);
|
||||
}
|
||||
|
||||
void freqman_set_bandwidth_option(freqman_index_t modulation, OptionsField& option) {
|
||||
if (is_valid(modulation))
|
||||
option.set_options(freqman_bandwidths[modulation]);
|
||||
}
|
||||
|
||||
void freqman_set_step_option(OptionsField& option) {
|
||||
option.set_options(freqman_steps);
|
||||
}
|
||||
|
||||
void freqman_set_step_option_short(OptionsField& option) {
|
||||
option.set_options(freqman_steps_short);
|
||||
}
|
||||
|
||||
namespace ui {
|
||||
|
||||
@@ -155,7 +176,7 @@ FrequencySaveView::FrequencySaveView(
|
||||
};
|
||||
|
||||
button_save.on_select = [this, &nav](Button&) {
|
||||
db_.insert_entry(entry_, db_.entry_count());
|
||||
db_.insert_entry(db_.entry_count(), entry_);
|
||||
nav_.pop();
|
||||
};
|
||||
}
|
||||
@@ -255,7 +276,7 @@ void FrequencyManagerView::on_add_entry() {
|
||||
};
|
||||
|
||||
// Add will insert below the currently selected item.
|
||||
db_.insert_entry(entry, current_index() + 1);
|
||||
db_.insert_entry(current_index() + 1, entry);
|
||||
refresh_list(1);
|
||||
}
|
||||
|
||||
@@ -488,12 +509,13 @@ void FrequencyEditView::populate_step_options() {
|
||||
}
|
||||
|
||||
void FrequencyEditView::populate_tone_options() {
|
||||
using namespace tonekey;
|
||||
OptionsField::options_t options;
|
||||
options.push_back({"None", -1});
|
||||
|
||||
for (auto i = 1u; i < tonekey::tone_keys.size(); ++i) {
|
||||
auto& item = tonekey::tone_keys[i];
|
||||
options.push_back({item.first, (OptionsField::value_t)i});
|
||||
for (auto i = 1u; i < tone_keys.size(); ++i) {
|
||||
auto& item = tone_keys[i];
|
||||
options.push_back({fx100_string(item.second), (OptionsField::value_t)i});
|
||||
}
|
||||
|
||||
field_tone.set_options(std::move(options));
|
||||
|
@@ -256,3 +256,9 @@ class FrequencyEditView : public View {
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
void freqman_set_bandwidth_option(freqman_index_t modulation, ui::OptionsField& option);
|
||||
void freqman_set_modulation_option(ui::OptionsField& option);
|
||||
void freqman_set_step_option(ui::OptionsField& option);
|
||||
void freqman_set_step_option_short(ui::OptionsField& option);
|
||||
void freqman_set_tone_option(ui::OptionsField& option);
|
||||
|
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "ui_level.hpp"
|
||||
#include "ui_fileman.hpp"
|
||||
#include "ui_freqman.hpp"
|
||||
#include "file.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
|
@@ -24,21 +24,21 @@
|
||||
#ifndef _UI_LEVEL
|
||||
#define _UI_LEVEL
|
||||
|
||||
#include "ui.hpp"
|
||||
#include "receiver_model.hpp"
|
||||
#include "ui_receiver.hpp"
|
||||
#include "ui_styles.hpp"
|
||||
#include "freqman.hpp"
|
||||
#include "analog_audio_app.hpp"
|
||||
#include "audio.hpp"
|
||||
#include "ui_mictx.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
#include "baseband_api.hpp"
|
||||
#include "ui_spectrum.hpp"
|
||||
#include "string_format.hpp"
|
||||
#include "file.hpp"
|
||||
#include "app_settings.hpp"
|
||||
#include "audio.hpp"
|
||||
#include "baseband_api.hpp"
|
||||
#include "file.hpp"
|
||||
#include "freqman_db.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
#include "radio_state.hpp"
|
||||
#include "receiver_model.hpp"
|
||||
#include "string_format.hpp"
|
||||
#include "ui.hpp"
|
||||
#include "ui_mictx.hpp"
|
||||
#include "ui_receiver.hpp"
|
||||
#include "ui_spectrum.hpp"
|
||||
#include "ui_styles.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
|
@@ -23,13 +23,17 @@
|
||||
|
||||
#include "ui_recon.hpp"
|
||||
#include "ui_fileman.hpp"
|
||||
#include "ui_freqman.hpp"
|
||||
#include "capture_app.hpp"
|
||||
#include "convert.hpp"
|
||||
#include "file.hpp"
|
||||
#include "file_reader.hpp"
|
||||
#include "tone_key.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
using namespace tonekey;
|
||||
using portapack::memory::map::backup_ram;
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace ui {
|
||||
|
||||
@@ -124,152 +128,81 @@ 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;
|
||||
|
||||
bool ReconView::recon_save_freq(const fs::path& path, size_t freq_index, bool warn_if_exists) {
|
||||
if (frequency_list.size() == 0 || !current_is_valid())
|
||||
return false;
|
||||
|
||||
FreqmanDB freq_db;
|
||||
if (!freq_db.open(path, /*create*/ true))
|
||||
return false;
|
||||
|
||||
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 = freqman_type::Single;
|
||||
|
||||
// TODO: Use FreqmanDB
|
||||
auto frequency_to_add = to_freqman_string(entry);
|
||||
|
||||
auto result = recon_file.open(freq_file_path); // First recon if freq is already in txt
|
||||
if (!result.is_valid()) {
|
||||
char one_char[1]{}; // Read it char by char
|
||||
std::string line{}; // and put read line in here
|
||||
bool found{false};
|
||||
for (size_t pointer = 0; pointer < recon_file.size(); pointer++) {
|
||||
recon_file.seek(pointer);
|
||||
recon_file.read(one_char, 1);
|
||||
if ((int)one_char[0] > 31) { // ascii space upwards
|
||||
line += one_char[0]; // add it to the textline
|
||||
} else if (one_char[0] == '\n') { // New Line
|
||||
if (line.compare(0, frequency_to_add.size(), frequency_to_add) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
line.clear(); // Ready for next textline
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
result = recon_file.append(freq_file_path); // Second: append if it is not there
|
||||
if (!result.is_valid()) {
|
||||
recon_file.write_line(frequency_to_add);
|
||||
}
|
||||
}
|
||||
if (found && warn_if_exists) {
|
||||
nav_.display_modal("Error", "Frequency already exists");
|
||||
}
|
||||
} else {
|
||||
result = recon_file.create(freq_file_path); // First freq if no output file
|
||||
if (!result.is_valid()) {
|
||||
recon_file.write_line(frequency_to_add);
|
||||
}
|
||||
// For ranges, save the current frequency instead.
|
||||
if (entry.type == freqman_type::Range) {
|
||||
entry.frequency_a = freq;
|
||||
entry.frequency_b = 0;
|
||||
entry.type = freqman_type::Single;
|
||||
entry.modulation = last_entry.modulation;
|
||||
entry.bandwidth = last_entry.bandwidth;
|
||||
entry.step = freqman_invalid_index;
|
||||
}
|
||||
|
||||
auto it = freq_db.find_entry(entry);
|
||||
auto found = (it != freq_db.end());
|
||||
|
||||
if (found && warn_if_exists)
|
||||
nav_.display_modal("Error", "Frequency already exists");
|
||||
|
||||
if (!found)
|
||||
freq_db.append_entry(entry);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReconView::recon_load_config_from_sd() {
|
||||
File settings_file{};
|
||||
size_t length{0};
|
||||
size_t file_position{0};
|
||||
char* pos{NULL};
|
||||
char* line_start{NULL};
|
||||
char* line_end{NULL};
|
||||
char file_data[257]{};
|
||||
uint32_t it{0};
|
||||
uint32_t nb_params{RECON_SETTINGS_NB_PARAMS};
|
||||
std::string params[RECON_SETTINGS_NB_PARAMS]{};
|
||||
|
||||
make_new_directory(u"SETTINGS");
|
||||
|
||||
auto result = settings_file.open(RECON_CFG_FILE);
|
||||
if (!result.is_valid()) {
|
||||
while (it < nb_params) {
|
||||
// Read a 256 bytes block from file
|
||||
settings_file.seek(file_position);
|
||||
memset(file_data, 0, 257);
|
||||
auto read_size = settings_file.read(file_data, 256);
|
||||
if (read_size.is_error())
|
||||
break;
|
||||
file_position += 256;
|
||||
// Reset line_start to beginning of buffer
|
||||
line_start = file_data;
|
||||
pos = line_start;
|
||||
while ((line_end = strstr(line_start, "\x0A"))) {
|
||||
length = line_end - line_start - 1;
|
||||
params[it] = std::string(pos, length);
|
||||
it++;
|
||||
line_start = line_end + 1;
|
||||
pos = line_start;
|
||||
if (line_start - file_data >= 256)
|
||||
break;
|
||||
if (it >= nb_params)
|
||||
break;
|
||||
}
|
||||
if (read_size.value() != 256)
|
||||
break; // End of file
|
||||
|
||||
// Restart at beginning of last incomplete line
|
||||
file_position -= (file_data + 256 - line_start);
|
||||
}
|
||||
}
|
||||
|
||||
if (it < nb_params) {
|
||||
/* bad number of params, signal defaults */
|
||||
input_file = "RECON";
|
||||
output_file = "RECON_RESULTS";
|
||||
recon_lock_duration = RECON_MIN_LOCK_DURATION;
|
||||
recon_lock_nb_match = RECON_DEF_NB_MATCH;
|
||||
squelch = -14;
|
||||
recon_match_mode = RECON_MATCH_CONTINUOUS;
|
||||
wait = RECON_DEF_WAIT_DURATION;
|
||||
File settings_file;
|
||||
auto error = settings_file.open(RECON_CFG_FILE);
|
||||
if (error)
|
||||
return false;
|
||||
|
||||
auto complete = false;
|
||||
auto line_nb = 0;
|
||||
auto reader = FileLineReader(settings_file);
|
||||
for (const auto& line : reader) {
|
||||
switch (line_nb) {
|
||||
case 0:
|
||||
input_file = trim(line);
|
||||
break;
|
||||
case 1:
|
||||
output_file = trim(line);
|
||||
break;
|
||||
case 2:
|
||||
parse_int(line, recon_lock_duration);
|
||||
break;
|
||||
case 3:
|
||||
parse_int(line, recon_lock_nb_match);
|
||||
break;
|
||||
case 4:
|
||||
parse_int(line, squelch);
|
||||
break;
|
||||
case 5:
|
||||
parse_int(line, recon_match_mode);
|
||||
break;
|
||||
case 6:
|
||||
parse_int(line, recon_match_mode);
|
||||
complete = true; // NB: Last entry.
|
||||
break;
|
||||
}
|
||||
|
||||
if (complete) break;
|
||||
|
||||
line_nb++;
|
||||
}
|
||||
|
||||
if (it > 0)
|
||||
input_file = params[0];
|
||||
else
|
||||
input_file = "RECON";
|
||||
|
||||
if (it > 1)
|
||||
output_file = params[1];
|
||||
else
|
||||
output_file = "RECON_RESULTS";
|
||||
|
||||
if (it > 2)
|
||||
recon_lock_duration = strtoll(params[2].c_str(), nullptr, 10);
|
||||
else
|
||||
recon_lock_duration = RECON_MIN_LOCK_DURATION;
|
||||
|
||||
if (it > 3)
|
||||
recon_lock_nb_match = strtoll(params[3].c_str(), nullptr, 10);
|
||||
else
|
||||
recon_lock_nb_match = RECON_DEF_NB_MATCH;
|
||||
|
||||
if (it > 4)
|
||||
squelch = strtoll(params[4].c_str(), nullptr, 10);
|
||||
else
|
||||
squelch = -14;
|
||||
|
||||
if (it > 5)
|
||||
recon_match_mode = strtoll(params[5].c_str(), nullptr, 10);
|
||||
else
|
||||
recon_match_mode = RECON_MATCH_CONTINUOUS;
|
||||
|
||||
if (it > 6)
|
||||
wait = strtoll(params[6].c_str(), nullptr, 10);
|
||||
else
|
||||
wait = RECON_DEF_WAIT_DURATION;
|
||||
|
||||
return true;
|
||||
return complete;
|
||||
}
|
||||
|
||||
bool ReconView::recon_save_config_to_sd() {
|
||||
@@ -486,6 +419,7 @@ ReconView::ReconView(NavigationView& nav)
|
||||
if (frequency_list.size() > 0) {
|
||||
auto new_view = nav_.push<FrequencyKeypadView>(current_index);
|
||||
new_view->on_changed = [this, &button](rf::Frequency f) {
|
||||
// NB: This is using the freq keypad to select an index.
|
||||
f = f / OneMHz;
|
||||
if (f >= 1 && f <= frequency_list.size()) {
|
||||
index_stepper = f - 1 - current_index;
|
||||
@@ -496,17 +430,18 @@ ReconView::ReconView(NavigationView& nav)
|
||||
};
|
||||
|
||||
button_manual_start.on_change = [this]() {
|
||||
frequency_range.min = frequency_range.min + button_manual_start.get_encoder_delta() * freqman_entry_get_step_value(def_step);
|
||||
auto step_val = freqman_entry_get_step_value(def_step);
|
||||
frequency_range.min = frequency_range.min + button_manual_start.get_encoder_delta() * step_val;
|
||||
if (frequency_range.min < 0) {
|
||||
frequency_range.min = 0;
|
||||
}
|
||||
if (frequency_range.min > (MAX_UFREQ - freqman_entry_get_step_value(def_step))) {
|
||||
frequency_range.min = MAX_UFREQ - freqman_entry_get_step_value(def_step);
|
||||
if (frequency_range.min > (MAX_UFREQ - step_val)) {
|
||||
frequency_range.min = MAX_UFREQ - step_val;
|
||||
}
|
||||
if (frequency_range.min > (frequency_range.max - freqman_entry_get_step_value(def_step))) {
|
||||
frequency_range.max = frequency_range.min + freqman_entry_get_step_value(def_step);
|
||||
if (frequency_range.min > (frequency_range.max - step_val)) {
|
||||
frequency_range.max = frequency_range.min + step_val;
|
||||
if (frequency_range.max > MAX_UFREQ) {
|
||||
frequency_range.min = MAX_UFREQ - freqman_entry_get_step_value(def_step);
|
||||
frequency_range.min = MAX_UFREQ - step_val;
|
||||
frequency_range.max = MAX_UFREQ;
|
||||
}
|
||||
}
|
||||
@@ -516,18 +451,19 @@ ReconView::ReconView(NavigationView& nav)
|
||||
};
|
||||
|
||||
button_manual_end.on_change = [this]() {
|
||||
frequency_range.max = frequency_range.max + button_manual_end.get_encoder_delta() * freqman_entry_get_step_value(def_step);
|
||||
if (frequency_range.max < (freqman_entry_get_step_value(def_step) + 1)) {
|
||||
frequency_range.max = (freqman_entry_get_step_value(def_step) + 1);
|
||||
auto step_val = freqman_entry_get_step_value(def_step);
|
||||
frequency_range.max = frequency_range.max + button_manual_end.get_encoder_delta() * step_val;
|
||||
if (frequency_range.max < (step_val + 1)) {
|
||||
frequency_range.max = (step_val + 1);
|
||||
}
|
||||
if (frequency_range.max > MAX_UFREQ) {
|
||||
frequency_range.max = MAX_UFREQ;
|
||||
}
|
||||
if (frequency_range.max < (frequency_range.min + freqman_entry_get_step_value(def_step))) {
|
||||
frequency_range.min = frequency_range.max - freqman_entry_get_step_value(def_step);
|
||||
if (frequency_range.max < (freqman_entry_get_step_value(def_step) + 1)) {
|
||||
if (frequency_range.max < (frequency_range.min + step_val)) {
|
||||
frequency_range.min = frequency_range.max - step_val;
|
||||
if (frequency_range.max < (step_val + 1)) {
|
||||
frequency_range.min = 1;
|
||||
frequency_range.max = (freqman_entry_get_step_value(def_step) + 1);
|
||||
frequency_range.max = (step_val + 1);
|
||||
}
|
||||
}
|
||||
button_manual_start.set_text(to_string_short_freq(frequency_range.min));
|
||||
@@ -607,87 +543,9 @@ ReconView::ReconView(NavigationView& nav)
|
||||
};
|
||||
|
||||
button_remove.on_select = [this](ButtonWithEncoder&) {
|
||||
// TODO: Use FreqmanDB
|
||||
if (frequency_list.size() > 0) {
|
||||
if (!manual_mode) {
|
||||
// scanner or recon (!scanner) mode
|
||||
// in both we delete index from live view, but only remove in output file in scanner_mode
|
||||
if (current_index >= (int32_t)frequency_list.size()) {
|
||||
current_index = frequency_list.size() - 1;
|
||||
}
|
||||
frequency_list.erase(frequency_list.begin() + current_index);
|
||||
if (current_index >= (int32_t)frequency_list.size()) {
|
||||
current_index = frequency_list.size() - 1;
|
||||
}
|
||||
if (frequency_list.size() > 0) {
|
||||
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) {
|
||||
File freqman_file{};
|
||||
delete_file(freq_file_path);
|
||||
auto result = freqman_file.create(freq_file_path);
|
||||
if (!result.is_valid()) {
|
||||
for (size_t n = 0; n < frequency_list.size(); n++) {
|
||||
auto line = to_freqman_string(*frequency_list[n]);
|
||||
freqman_file.write_line(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (manual_mode) // only remove from output
|
||||
{
|
||||
File recon_file{};
|
||||
File tmp_recon_file{};
|
||||
std::string tmp_freq_file_path{freq_file_path + ".TMP"};
|
||||
handle_remove_current_item();
|
||||
|
||||
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 = freqman_type::Single;
|
||||
|
||||
auto frequency_to_add = to_freqman_string(entry);
|
||||
|
||||
delete_file(tmp_freq_file_path);
|
||||
auto result = tmp_recon_file.create(tmp_freq_file_path); // First recon if freq is already in txt
|
||||
if (!result.is_valid()) {
|
||||
bool found = false;
|
||||
result = recon_file.open(freq_file_path); // First recon if freq is already in txt
|
||||
if (!result.is_valid()) {
|
||||
char one_char[1]{}; // Read it char by char
|
||||
std::string line{}; // and put read line in here
|
||||
for (size_t pointer = 0; pointer < recon_file.size(); pointer++) {
|
||||
recon_file.seek(pointer);
|
||||
recon_file.read(one_char, 1);
|
||||
if ((int)one_char[0] > 31) { // ascii space upwards
|
||||
line += one_char[0]; // add it to the textline
|
||||
} else if (one_char[0] == '\n') { // new Line
|
||||
if (line.compare(0, frequency_to_add.size(), frequency_to_add) == 0) {
|
||||
found = true;
|
||||
} else {
|
||||
tmp_recon_file.write_line(frequency_to_add);
|
||||
}
|
||||
line.clear(); // ready for next textline
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
delete_file(freq_file_path);
|
||||
rename_file(tmp_freq_file_path, freq_file_path);
|
||||
} else {
|
||||
delete_file(tmp_freq_file_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
receiver_model.set_target_frequency(current_entry().frequency_a); // retune
|
||||
}
|
||||
if (frequency_list.size() == 0) {
|
||||
text_cycle.set_text(" ");
|
||||
desc_cycle.set("no entries in list"); // Show new description
|
||||
delete_file(freq_file_path);
|
||||
}
|
||||
// TODO: refresh UI.
|
||||
timer = 0;
|
||||
freq_lock = 0;
|
||||
};
|
||||
@@ -921,8 +779,7 @@ ReconView::ReconView(NavigationView& nav)
|
||||
recon_redraw();
|
||||
}
|
||||
|
||||
void ReconView::frequency_file_load(bool stop_all_before) {
|
||||
(void)(stop_all_before);
|
||||
void ReconView::frequency_file_load(bool) {
|
||||
if (field_mode.selected_index_value() != SPEC_MODULATION)
|
||||
audio::output::stop();
|
||||
|
||||
@@ -940,6 +797,7 @@ void ReconView::frequency_file_load(bool stop_all_before) {
|
||||
desc_cycle.set_style(&Styles::blue);
|
||||
button_scanner_mode.set_text("RECON");
|
||||
}
|
||||
|
||||
freqman_load_options options{
|
||||
.load_freqs = load_freqs,
|
||||
.load_ranges = load_ranges,
|
||||
@@ -1430,4 +1288,35 @@ void ReconView::handle_coded_squelch(const uint32_t value) {
|
||||
text_ctcss.set(" ");
|
||||
}
|
||||
|
||||
void ReconView::handle_remove_current_item() {
|
||||
if (frequency_list.empty() || !current_is_valid())
|
||||
return;
|
||||
|
||||
auto entry = current_entry(); // Copy the current entry.
|
||||
|
||||
// In Scanner or Recon modes, remove from the in-memory list.
|
||||
if (mode() != recon_mode::Manual) {
|
||||
if (current_is_valid()) {
|
||||
frequency_list.erase(frequency_list.begin() + current_index);
|
||||
}
|
||||
|
||||
if (frequency_list.size() > 0) {
|
||||
current_index = clip<int32_t>(current_index, 0u, frequency_list.size());
|
||||
text_cycle.set_text(to_string_dec_uint(current_index + 1, 3));
|
||||
update_description();
|
||||
} else {
|
||||
current_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// In Scanner or Manual mode, remove the entry from the output file.
|
||||
if (mode() != recon_mode::Recon) {
|
||||
FreqmanDB freq_db;
|
||||
if (!freq_db.open(freq_file_path))
|
||||
return;
|
||||
|
||||
freq_db.delete_entry(entry);
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
|
@@ -46,6 +46,12 @@ namespace ui {
|
||||
|
||||
#define RECON_CFG_FILE "SETTINGS/recon.cfg"
|
||||
|
||||
enum class recon_mode : uint8_t {
|
||||
Recon,
|
||||
Scanner,
|
||||
Manual
|
||||
};
|
||||
|
||||
class ReconView : public View {
|
||||
public:
|
||||
ReconView(NavigationView& nav);
|
||||
@@ -82,9 +88,10 @@ class ReconView : public View {
|
||||
void recon_redraw();
|
||||
void handle_retune();
|
||||
void handle_coded_squelch(const uint32_t value);
|
||||
void handle_remove_current_item();
|
||||
bool recon_load_config_from_sd();
|
||||
bool recon_save_config_to_sd();
|
||||
bool recon_save_freq(const std::string& freq_file_path, size_t index, bool warn_if_exists);
|
||||
bool recon_save_freq(const std::filesystem::path& path, size_t index, bool warn_if_exists);
|
||||
// placeholder for possible void recon_start_recording();
|
||||
void recon_stop_recording();
|
||||
|
||||
@@ -92,8 +99,15 @@ class ReconView : public View {
|
||||
bool current_is_valid();
|
||||
freqman_entry& current_entry();
|
||||
|
||||
// TODO: consolidate mode bools and use recon_mode.
|
||||
recon_mode mode() const {
|
||||
if (manual_mode) return recon_mode::Manual;
|
||||
if (scanner_mode) return recon_mode::Scanner;
|
||||
return recon_mode::Recon;
|
||||
}
|
||||
|
||||
jammer::jammer_range_t frequency_range{false, 0, MAX_UFREQ}; // perfect for manual recon task too...
|
||||
int32_t squelch{0};
|
||||
int32_t squelch{RECON_DEF_SQUELCH};
|
||||
int32_t db{0};
|
||||
int32_t timer{0};
|
||||
int32_t wait{RECON_DEF_WAIT_DURATION}; // in msec. if > 0 wait duration after a lock, if < 0 duration is set to 'wait' unless there is no more activity
|
||||
@@ -117,7 +131,7 @@ class ReconView : public View {
|
||||
bool user_pause{false};
|
||||
bool auto_record_locked{false};
|
||||
bool is_recording{false};
|
||||
uint32_t recon_lock_nb_match{3};
|
||||
uint32_t recon_lock_nb_match{RECON_DEF_NB_MATCH};
|
||||
uint32_t recon_lock_duration{RECON_MIN_LOCK_DURATION};
|
||||
uint32_t recon_match_mode{RECON_MATCH_CONTINUOUS};
|
||||
bool scanner_mode{false};
|
||||
|
@@ -70,11 +70,9 @@ ReconSetupViewMain::ReconSetupViewMain(NavigationView& nav, Rect parent_rect, st
|
||||
button_save_freqs.on_select = [this, &nav](Button&) {
|
||||
auto open_view = nav.push<FileLoadView>(".TXT");
|
||||
open_view->on_changed = [this, &nav](std::filesystem::path new_file_path) {
|
||||
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 (new_file_path.native().find(freqman_dir.native()) == 0) {
|
||||
_output_file = new_file_path.stem().string();
|
||||
button_output_file.set_text(_output_file);
|
||||
text_input_file.set(_output_file);
|
||||
} else {
|
||||
nav.display_modal("LOAD ERROR", "A valid file from\nFREQMAN directory is\nrequired.");
|
||||
}
|
||||
@@ -84,7 +82,7 @@ ReconSetupViewMain::ReconSetupViewMain(NavigationView& nav, Rect parent_rect, st
|
||||
button_output_file.on_select = [this, &nav](Button&) {
|
||||
text_prompt(nav, _output_file, 28,
|
||||
[this](std::string& buffer) {
|
||||
_output_file = buffer;
|
||||
_output_file = std::move(buffer);
|
||||
button_output_file.set_text(_output_file);
|
||||
});
|
||||
};
|
||||
|
@@ -50,6 +50,8 @@
|
||||
// maximum lock duration
|
||||
#define RECON_MAX_LOCK_DURATION 9900
|
||||
|
||||
#define RECON_DEF_SQUELCH -14
|
||||
|
||||
// default number of match to have a lock
|
||||
#define RECON_DEF_NB_MATCH 3
|
||||
#define RECON_MIN_LOCK_DURATION 100 // have to be >= and a multiple of STATS_UPDATE_INTERVAL
|
||||
|
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "ui_scanner.hpp"
|
||||
#include "ui_fileman.hpp"
|
||||
#include "ui_freqman.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
|
||||
|
@@ -20,13 +20,14 @@
|
||||
*/
|
||||
|
||||
#include "ui_spectrum_painter.hpp"
|
||||
|
||||
#include "bmp.hpp"
|
||||
#include "baseband_api.hpp"
|
||||
|
||||
#include "ui_fileman.hpp"
|
||||
#include "io_file.hpp"
|
||||
#include "file.hpp"
|
||||
#include "io_file.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
#include "ui_fileman.hpp"
|
||||
#include "ui_freqman.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
|
||||
|
Reference in New Issue
Block a user