From 5cd9c377d25cd9f507e68d10e997c1c8acbc0533 Mon Sep 17 00:00:00 2001 From: gullradriel <3157857+gullradriel@users.noreply.github.com> Date: Sun, 25 Jun 2023 08:16:49 +0200 Subject: [PATCH] Recon record (#1182) * added auto record checbox and functions (audio and raw) * Changed baseband compile option from -O3 to -O2. Trying lower gave unexpeted and crashing results. * added 650k SPEC bw * fix hang if wait is -100 * fixing no SPEC support in scanner --- firmware/application/apps/ui_recon.cpp | 184 +++++++++++++++--- firmware/application/apps/ui_recon.hpp | 15 +- .../application/apps/ui_recon_settings.cpp | 5 +- .../application/apps/ui_recon_settings.hpp | 4 + firmware/application/apps/ui_scanner.cpp | 10 + firmware/application/freqman.cpp | 22 ++- firmware/application/freqman.hpp | 3 +- firmware/baseband/CMakeLists.txt | 2 +- .../common/portapack_persistent_memory.cpp | 37 ++-- .../common/portapack_persistent_memory.hpp | 2 + 10 files changed, 231 insertions(+), 53 deletions(-) diff --git a/firmware/application/apps/ui_recon.cpp b/firmware/application/apps/ui_recon.cpp index c6325928..d93c4ae9 100644 --- a/firmware/application/apps/ui_recon.cpp +++ b/firmware/application/apps/ui_recon.cpp @@ -30,14 +30,26 @@ using portapack::memory::map::backup_ram; namespace ui { +static RecordView* record_view = NULL; + void ReconView::set_loop_config(bool v) { continuous = v; button_loop_config.set_style(v ? &Styles::green : &Styles::white); persistent_memory::set_recon_continuous(continuous); } +void ReconView::recon_stop_recording() { + if (is_recording) { + button_audio_app.set_style(&Styles::white); + record_view->stop(); + is_recording = false; + } +} + void ReconView::clear_freqlist_for_ui_action() { - audio::output::stop(); + recon_stop_recording(); + if (field_mode.selected_index_value() != SPEC_MODULATION) + 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 @@ -232,8 +244,8 @@ bool ReconView::recon_save_config_to_sd() { make_new_directory(u"SETTINGS"); - auto result = settings_file.create(RECON_CFG_FILE); - if (result.is_valid()) + auto error = settings_file.create(RECON_CFG_FILE); + if (error) return false; settings_file.write_line(input_file); settings_file.write_line(output_file); @@ -246,7 +258,8 @@ bool ReconView::recon_save_config_to_sd() { } void ReconView::audio_output_start() { - audio::output::start(); + if (field_mode.selected_index_value() != SPEC_MODULATION) + audio::output::start(); receiver_model.set_headphone_volume(receiver_model.headphone_volume()); // WM8731 hack. } @@ -279,10 +292,6 @@ void ReconView::recon_redraw() { } else if (freq_lock >= recon_lock_nb_match) { big_display.set_style(&Styles::green); button_pause.set_text(""); - // FREQ IS STRONG: GREEN and recon will pause when on_statistics_update() - if ((!scanner_mode) && autosave && frequency_list.size() > 0) { - recon_save_freq(freq_file_path, current_index, false); - } } } if (last_db != db || last_list_size != frequency_list.size()) { @@ -354,16 +363,20 @@ void ReconView::focus() { } ReconView::~ReconView() { - // Save recon config. + recon_stop_recording(); + delete record_view; recon_save_config_to_sd(); - - audio::output::stop(); + if (field_mode.selected_index_value() != SPEC_MODULATION) + audio::output::stop(); + receiver_model.set_modulation(ReceiverModel::Mode::WidebandFMAudio); receiver_model.disable(); baseband::shutdown(); } ReconView::ReconView(NavigationView& nav) : nav_{nav} { + chrono_start = chTimeNow(); + record_view = new RecordView({0, 0, 30 * 8, 1 * 16}, u"AUTO_AUDIO_", u"AUDIO", RecordView::FileType::WAV, 4096, 4); add_children({&labels, &field_lna, &field_vga, @@ -399,7 +412,14 @@ ReconView::ReconView(NavigationView& nav) &button_dir, &button_restart, &button_mic_app, - &button_remove}); + &button_remove, + record_view}); + + record_view->hidden(true); + record_view->set_filename_date_frequency(true); + record_view->on_error = [&nav](std::string message) { + nav.display_modal("Error", message); + }; def_step = 0; // HELPER: Pre-setting a manual range, based on stored frequency @@ -424,6 +444,7 @@ ReconView::ReconView(NavigationView& nav) load_ranges = persistent_memory::recon_load_ranges(); load_hamradios = persistent_memory::recon_load_hamradios(); update_ranges = persistent_memory::recon_update_ranges_when_recon(); + auto_record_locked = persistent_memory::recon_auto_record_locked(); button_manual_start.on_select = [this, &nav](ButtonWithEncoder& button) { clear_freqlist_for_ui_action(); @@ -680,7 +701,8 @@ ReconView::ReconView(NavigationView& nav) } else if (frequency_range.min > frequency_range.max) { nav_.display_modal("Error", "END freq\nis lower than START"); } else { - audio::output::stop(); + 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().swap(frequency_list); @@ -760,6 +782,9 @@ ReconView::ReconView(NavigationView& nav) button_scanner_mode.set_style(&Styles::blue); button_scanner_mode.set_text("RECON"); } + if (frequency_list.size() > FREQMAN_MAX_PER_FILE) { + file_name.set_style(&Styles::yellow); + } }; button_add.on_select = [this](ButtonWithEncoder&) { // frequency_list[current_index] @@ -796,7 +821,8 @@ ReconView::ReconView(NavigationView& nav) button_config.on_select = [this, &nav](Button&) { clear_freqlist_for_ui_action(); - + freq_lock = 0; + timer = 0; auto open_view = nav.push(input_file, output_file); open_view->on_changed = [this](std::vector result) { input_file = result[0]; @@ -811,6 +837,7 @@ ReconView::ReconView(NavigationView& nav) load_ranges = persistent_memory::recon_load_ranges(); load_hamradios = persistent_memory::recon_load_hamradios(); update_ranges = persistent_memory::recon_update_ranges_when_recon(); + auto_record_locked = persistent_memory::recon_auto_record_locked(); frequency_file_load(false); freqlist_cleared_for_ui_action = false; @@ -830,6 +857,9 @@ ReconView::ReconView(NavigationView& nav) field_wait.on_change = [this](int32_t v) { wait = v; + // replacing -100 by 200 else it's freezing the device + if (wait == -100) + wait = -200; colorize_waits(); }; @@ -888,7 +918,8 @@ ReconView::ReconView(NavigationView& nav) void ReconView::frequency_file_load(bool stop_all_before) { (void)(stop_all_before); - audio::output::stop(); + if (field_mode.selected_index_value() != SPEC_MODULATION) + audio::output::stop(); def_step = step_mode.selected_index(); // use def_step from manual selector std::string file_input = input_file; // default recon mode @@ -896,29 +927,27 @@ void ReconView::frequency_file_load(bool stop_all_before) { file_input = output_file; file_name.set_style(&Styles::red); button_scanner_mode.set_style(&Styles::red); + desc_cycle.set_style(&Styles::red); button_scanner_mode.set_text("SCANNER"); } else { file_name.set_style(&Styles::blue); button_scanner_mode.set_style(&Styles::blue); + desc_cycle.set_style(&Styles::blue); button_scanner_mode.set_text("RECON"); } - desc_cycle.set_style(&Styles::white); if (!load_freqman_file(file_input, frequency_list, load_freqs, load_ranges, load_hamradios)) { file_name.set_style(&Styles::red); - desc_cycle.set_style(&Styles::red); desc_cycle.set(" NO " + file_input + ".TXT FILE ..."); file_name.set("=> NO DATA"); } else { file_name.set(file_input + "=>" + output_file); if (frequency_list.size() == 0) { file_name.set_style(&Styles::red); - desc_cycle.set_style(&Styles::red); desc_cycle.set("/0 no entries in list"); file_name.set("BadOrEmpty " + file_input); } else { if (frequency_list.size() > FREQMAN_MAX_PER_FILE) { file_name.set_style(&Styles::yellow); - desc_cycle.set_style(&Styles::yellow); } } } @@ -992,6 +1021,14 @@ void ReconView::frequency_file_load(bool stop_all_before) { } void ReconView::on_statistics_update(const ChannelStatistics& statistics) { + systime_t time_interval = 100; + + if (field_mode.selected_index_value() == SPEC_MODULATION) { + chrono_end = chTimeNow(); + time_interval = chrono_end - chrono_start; + chrono_start = chrono_end; + } + // hack to reload the list if it was cleared by going into CONFIG if (freqlist_cleared_for_ui_action) { if (!manual_mode) { @@ -1018,7 +1055,9 @@ void ReconView::on_statistics_update(const ChannelStatistics& statistics) { if (status != 1) { status = 1; if (wait != 0) { - audio::output::stop(); + recon_stop_recording(); + if (field_mode.selected_index_value() != SPEC_MODULATION) + audio::output::stop(); } } if (db > squelch) // MATCHING LEVEL @@ -1040,8 +1079,23 @@ void ReconView::on_statistics_update(const ChannelStatistics& statistics) { if (status != 2) { continuous_lock = false; status = 2; + // FREQ IS STRONG: GREEN and recon will pause when on_statistics_update() + if ((!scanner_mode) && autosave && frequency_list.size() > 0) { + recon_save_freq(freq_file_path, current_index, false); + } if (wait != 0) { - audio_output_start(); + if (field_mode.selected_index_value() != SPEC_MODULATION) + audio_output_start(); + // contents of a possible recon_start_recording(), but not yet since it's only called once + if (auto_record_locked && !is_recording) { + button_audio_app.set_style(&Styles::red); + record_view->start(); + is_recording = true; + } + // FREQ IS STRONG: GREEN and recon will pause when on_statistics_update() + if ((!scanner_mode) && autosave && frequency_list.size() > 0) { + recon_save_freq(freq_file_path, current_index, false); + } } if (wait >= 0) { timer = wait; @@ -1060,8 +1114,9 @@ void ReconView::on_statistics_update(const ChannelStatistics& statistics) { text_timer.set("TIMER: " + to_string_dec_int(timer)); } if (timer) { - if (!continuous_lock || recon_match_mode == RECON_MATCH_SPARSE) - timer -= STATS_UPDATE_INTERVAL; + if (!continuous_lock || recon_match_mode == RECON_MATCH_SPARSE) { + timer -= time_interval; + } if (timer < 0) { timer = 0; } @@ -1072,7 +1127,6 @@ void ReconView::on_statistics_update(const ChannelStatistics& statistics) { if (frequency_list.size() > 0) { has_looped = false; entry_has_changed = false; - if (recon || stepper != 0 || index_stepper != 0) { if (index_stepper == 0) { /* we are doing a range */ @@ -1172,7 +1226,8 @@ void ReconView::on_statistics_update(const ChannelStatistics& statistics) { entry_has_changed = true; - if (!recon) // for some motive, audio output gets stopped. + // for some motive, audio output gets stopped. + if (!recon && field_mode.selected_index_value() != SPEC_MODULATION) audio_output_start(); } // reload entry if changed @@ -1224,7 +1279,8 @@ void ReconView::recon_pause() { continuous_lock = false; recon = false; - audio_output_start(); + if (field_mode.selected_index_value() != SPEC_MODULATION) + audio_output_start(); big_display.set_style(&Styles::white); button_pause.set_text(""); // PAUSED, show resume @@ -1236,7 +1292,8 @@ void ReconView::recon_resume() { continuous_lock = false; recon = true; - audio::output::stop(); + if (field_mode.selected_index_value() != SPEC_MODULATION) + audio::output::stop(); big_display.set_style(&Styles::white); button_pause.set_text(""); @@ -1277,10 +1334,29 @@ void ReconView::on_stepper_delta(int32_t v) { size_t ReconView::change_mode(freqman_index_t new_mod) { field_mode.on_change = [this](size_t, OptionsField::value_t) {}; field_bw.on_change = [this](size_t, OptionsField::value_t) {}; - + recon_stop_recording(); + if (new_mod != SPEC_MODULATION) { + remove_children({record_view}); + delete record_view; + record_view = new RecordView({0, 0, 30 * 8, 1 * 16}, u"AUTO_AUDIO_", u"AUDIO", RecordView::FileType::WAV, 4096, 4); + record_view->set_filename_date_frequency(true); + add_children({record_view}); + } + if (new_mod == SPEC_MODULATION) { + audio::output::stop(); + remove_children({record_view}); + delete record_view; + record_view = new RecordView({0, 0, 30 * 8, 1 * 16}, u"AUTO_RAW_", u"CAPTURES", RecordView::FileType::RawS16, 16384, 3); + record_view->set_filename_date_frequency(true); + add_children({record_view}); + } + record_view->hidden(true); + record_view->on_error = [this](std::string message) { + nav_.display_modal("Error", message); + }; receiver_model.disable(); baseband::shutdown(); - + size_t recording_sampling_rate = 0; switch (new_mod) { case AM_MODULATION: freqman_set_bandwidth_option(new_mod, field_bw); @@ -1291,6 +1367,7 @@ size_t ReconView::change_mode(freqman_index_t new_mod) { receiver_model.set_am_configuration(field_bw.selected_index_value()); field_bw.on_change = [this](size_t, OptionsField::value_t n) { receiver_model.set_am_configuration(n); }; text_ctcss.set(" "); + recording_sampling_rate = 12000; break; case NFM_MODULATION: freqman_set_bandwidth_option(new_mod, field_bw); @@ -1300,6 +1377,7 @@ size_t ReconView::change_mode(freqman_index_t new_mod) { receiver_model.set_modulation(ReceiverModel::Mode::NarrowbandFMAudio); receiver_model.set_nbfm_configuration(field_bw.selected_index_value()); field_bw.on_change = [this](size_t, OptionsField::value_t n) { receiver_model.set_nbfm_configuration(n); }; + recording_sampling_rate = 24000; break; case WFM_MODULATION: freqman_set_bandwidth_option(new_mod, field_bw); @@ -1310,10 +1388,55 @@ size_t ReconView::change_mode(freqman_index_t new_mod) { receiver_model.set_wfm_configuration(field_bw.selected_index_value()); field_bw.on_change = [this](size_t, OptionsField::value_t n) { receiver_model.set_wfm_configuration(n); }; text_ctcss.set(" "); + recording_sampling_rate = 48000; + break; + case SPEC_MODULATION: + freqman_set_bandwidth_option(new_mod, field_bw); + // bw 200k (0) default + baseband::run_image(portapack::spi_flash::image_tag_capture); + receiver_model.set_modulation(ReceiverModel::Mode::Capture); + field_bw.set_by_value(0); + field_bw.on_change = [this](size_t, OptionsField::value_t sampling_rate) { + uint32_t anti_alias_baseband_bandwidth_filter = 2500000; + switch (sampling_rate) { // we use the var fs (sampling_rate) , to set up BPF aprox < fs_max/2 by Nyquist theorem. + case 0 ... 2000000: // BW Captured range (0 <= 250kHz max ) fs = 8 x 250 kHz + anti_alias_baseband_bandwidth_filter = 1750000; // Minimum BPF MAX2837 for all those lower BW options. + break; + case 4000000 ... 6000000: // BW capture range (500k ... 750kHz max ) fs_max = 8 x 750kHz = 6Mhz + // BW 500k ... 750kHz , ex. 500kHz (fs = 8*BW = 4Mhz) , BW 600kHz (fs = 4,8Mhz) , BW 750 kHz (fs = 6Mhz) + anti_alias_baseband_bandwidth_filter = 2500000; // in some IC MAX2837 appear 2250000 , but both works similar. + break; + case 8800000: // BW capture 1,1Mhz fs = 8 x 1,1Mhz = 8,8Mhz . (1Mhz showed slightly higher noise background). + anti_alias_baseband_bandwidth_filter = 3500000; + break; + case 14000000: // BW capture 1,75Mhz , fs = 8 x 1,75Mhz = 14Mhz + // good BPF, good matching, but LCD making flicker , refresh rate should be < 20 Hz , but reasonable picture + anti_alias_baseband_bandwidth_filter = 5000000; + break; + case 16000000: // BW capture 2Mhz , fs = 8 x 2Mhz = 16Mhz + // good BPF, good matching, but LCD making flicker , refresh rate should be < 20 Hz , but reasonable picture + anti_alias_baseband_bandwidth_filter = 6000000; + break; + case 20000000: // BW capture 2,5Mhz , fs= 8 x 2,5 Mhz = 20Mhz + // good BPF, good matching, but LCD making flicker , refresh rate should be < 20 Hz , but reasonable picture + anti_alias_baseband_bandwidth_filter = 7000000; + break; + default: // BW capture 2,75Mhz, fs = 8 x 2,75Mhz= 22Mhz max ADC sampling) and others. + // We tested also 9Mhz FPB stightly too much noise floor, better 8Mhz + anti_alias_baseband_bandwidth_filter = 8000000; + } + record_view->set_sampling_rate(sampling_rate); + receiver_model.set_sampling_rate(sampling_rate); + receiver_model.set_baseband_bandwidth(anti_alias_baseband_bandwidth_filter); + }; + text_ctcss.set(" "); break; default: break; } + if (new_mod != SPEC_MODULATION) + record_view->set_sampling_rate(recording_sampling_rate); + field_mode.set_selected_index(new_mod); field_mode.on_change = [this](size_t, OptionsField::value_t v) { if (v != -1) { @@ -1321,7 +1444,8 @@ size_t ReconView::change_mode(freqman_index_t new_mod) { } }; - if (!recon) // for some motive, audio output gets stopped. + // for some motive, audio output gets stopped. + if (!recon && field_mode.selected_index_value() != SPEC_MODULATION) audio::output::start(); // so if recon was stopped we resume audio receiver_model.enable(); diff --git a/firmware/application/apps/ui_recon.hpp b/firmware/application/apps/ui_recon.hpp index 8b2fcc63..f90fa2ca 100644 --- a/firmware/application/apps/ui_recon.hpp +++ b/firmware/application/apps/ui_recon.hpp @@ -84,6 +84,8 @@ class ReconView : public View { 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); + // placeholder for possible void recon_start_recording(); + void recon_stop_recording(); jammer::jammer_range_t frequency_range{false, 0, MAX_UFREQ}; // perfect for manual recon task too... int32_t squelch{0}; @@ -108,6 +110,8 @@ class ReconView : public View { bool fwd{true}; bool recon{true}; bool user_pause{false}; + bool auto_record_locked{false}; + bool is_recording{false}; uint32_t recon_lock_nb_match{3}; uint32_t recon_lock_duration{RECON_MIN_LOCK_DURATION}; uint32_t recon_match_mode{RECON_MATCH_CONTINUOUS}; @@ -118,10 +122,7 @@ class ReconView : public View { int32_t index_stepper{0}; int64_t freq{0}; uint32_t step{0}; - freqman_index_t def_modulation{0}; - freqman_index_t def_bandwidth{0}; freqman_index_t def_step{0}; - tone_index tone{0}; freqman_entry last_entry{}; bool entry_has_changed{false}; uint32_t freq_lock{0}; @@ -141,13 +142,15 @@ class ReconView : public View { int32_t last_squelch_index{-1}; int64_t last_freq{0}; std::string freq_file_path{}; + systime_t chrono_start{}; + systime_t chrono_end{}; Labels labels{ {{0 * 8, 0 * 16}, "LNA: VGA: AMP: VOL: ", Color::light_grey()}, {{3 * 8, 8 * 16}, "START END", Color::light_grey()}, {{0 * 8, (22 * 8)}, " S: ", Color::light_grey()}, {{0 * 8, (24 * 8) + 4}, "NBLCKS:x W,L: , ", Color::light_grey()}, - {{0 * 8, (26 * 8) + 4}, "MODE: , SQUELCH: ", Color::light_grey()}}; + {{0 * 8, (26 * 8) + 4}, "MODE: , SQUELCH: ", Color::light_grey()}}; LNAGainField field_lna{ {4 * 8, 0 * 16}}; @@ -272,11 +275,11 @@ class ReconView : public View { OptionsField field_mode{ {6 * 8, (26 * 8) + 4}, - 3, + 4, {}}; OptionsField field_bw{ - {10 * 8, (26 * 8) + 4}, + {11 * 8, (26 * 8) + 4}, 6, {}}; diff --git a/firmware/application/apps/ui_recon_settings.cpp b/firmware/application/apps/ui_recon_settings.cpp index 2de7058d..1d3251d4 100644 --- a/firmware/application/apps/ui_recon_settings.cpp +++ b/firmware/application/apps/ui_recon_settings.cpp @@ -103,6 +103,7 @@ void ReconSetupViewMore::save() { persistent_memory::set_recon_load_ranges(checkbox_load_ranges.value()); persistent_memory::set_recon_load_hamradios(checkbox_load_hamradios.value()); persistent_memory::set_recon_update_ranges_when_recon(checkbox_update_ranges_when_recon.value()); + persistent_memory::set_recon_auto_record_locked(checkbox_auto_record_locked.value()); }; void ReconSetupViewMain::focus() { @@ -117,12 +118,14 @@ ReconSetupViewMore::ReconSetupViewMore(NavigationView& nav, Rect parent_rect) add_children({&checkbox_load_freqs, &checkbox_load_ranges, &checkbox_load_hamradios, - &checkbox_update_ranges_when_recon}); + &checkbox_update_ranges_when_recon, + &checkbox_auto_record_locked}); checkbox_load_freqs.set_value(persistent_memory::recon_load_freqs()); checkbox_load_ranges.set_value(persistent_memory::recon_load_ranges()); checkbox_load_hamradios.set_value(persistent_memory::recon_load_hamradios()); checkbox_update_ranges_when_recon.set_value(persistent_memory::recon_update_ranges_when_recon()); + checkbox_auto_record_locked.set_value(persistent_memory::recon_auto_record_locked()); }; void ReconSetupViewMore::focus() { diff --git a/firmware/application/apps/ui_recon_settings.hpp b/firmware/application/apps/ui_recon_settings.hpp index 2f39807d..1751469f 100644 --- a/firmware/application/apps/ui_recon_settings.hpp +++ b/firmware/application/apps/ui_recon_settings.hpp @@ -132,6 +132,10 @@ class ReconSetupViewMore : public View { {1 * 8, 102}, 3, "auto update m-ranges"}; + Checkbox checkbox_auto_record_locked{ + {1 * 8, 132}, + 3, + "auto record locked periods"}; }; class ReconSetupView : public View { diff --git a/firmware/application/apps/ui_scanner.cpp b/firmware/application/apps/ui_scanner.cpp index e5f52954..2381dbe5 100644 --- a/firmware/application/apps/ui_scanner.cpp +++ b/firmware/application/apps/ui_scanner.cpp @@ -447,6 +447,16 @@ ScannerView::ScannerView( // Mode field was changed (AM/NFM/WFM) field_mode.on_change = [this](size_t, OptionsField::value_t v) { + static freqman_index_t last_mode = AM_MODULATION; + // unsupported SPEC mode fix + if (v == SPEC_MODULATION) { + if (last_mode == AM_MODULATION) + v = WFM_MODULATION; + else + v = AM_MODULATION; + field_mode.set_selected_index(v); + } + last_mode = v; receiver_model.disable(); baseband::shutdown(); change_mode((freqman_index_t)v); diff --git a/firmware/application/freqman.cpp b/firmware/application/freqman.cpp index 14e664f6..648e8803 100644 --- a/firmware/application/freqman.cpp +++ b/firmware/application/freqman.cpp @@ -30,7 +30,8 @@ using options_t = std::vector; options_t freqman_entry_modulations = { {"AM", 0}, {"NFM", 1}, - {"WFM", 2}}; + {"WFM", 2}, + {"SPEC", 3}}; options_t freqman_entry_bandwidths[4] = { {// AM @@ -48,6 +49,25 @@ options_t freqman_entry_bandwidths[4] = { {"40k", 2}, {"180k", 1}, {"200k", 0}, + }, + { + // SPEC + {"8k5", 8500}, + {"11k", 11000}, + {"16k", 16000}, + {"25k", 25000}, + {"50k", 50000}, + {"100k", 100000}, + {"250k", 250000}, + {"500k", 500000}, /* Previous Limit bandwith Option with perfect micro SD write .C16 format operaton.*/ + {"600k", 600000}, /* That extended option is still possible to record with FW version Mayhem v1.41 (< 2,5MB/sec) */ + {"650k", 650000}, + {"750k", 750000}, /* From this BW onwards, the LCD is ok, but the recorded file is decimated, (not real file size) */ + {"1100k", 1100000}, + {"1750k", 1750000}, + {"2000k", 2000000}, + {"2500k", 2500000}, + {"2750k", 2750000}, // That is our max Capture option, to keep using later / 8 decimation (22Mhz sampling ADC) }}; options_t freqman_entry_steps = { diff --git a/firmware/application/freqman.hpp b/firmware/application/freqman.hpp index c4cd2c17..658664dc 100644 --- a/firmware/application/freqman.hpp +++ b/firmware/application/freqman.hpp @@ -59,10 +59,11 @@ enum freqman_entry_type : int8_t { NOTYPE // undetected }; -enum freqman_entry_modulation : int8_t { +enum freqman_entry_modulation : uint8_t { AM_MODULATION = 0, NFM_MODULATION, WFM_MODULATION, + SPEC_MODULATION, }; // Entry step placed for AlainD freqman version (or any other enhanced version) diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index 1721bb9a..53262b06 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -32,7 +32,7 @@ include(CheckCXXCompilerFlag) project(baseband_shared) # Compiler options here. -set(USE_OPT "-O3 -g -falign-functions=16 -fno-math-errno --specs=nano.specs") +set(USE_OPT "-O2 -g -falign-functions=16 -fno-math-errno --specs=nano.specs") # C specific options here (added to USE_OPT). set(USE_COPT "-std=gnu99") diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index edd59c52..945c1658 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -822,6 +822,9 @@ bool recon_load_hamradios() { bool recon_match_mode() { return (data->recon_config & 0x00800000UL) ? true : false; } +bool recon_auto_record_locked() { + return (data->recon_config & 0x00400000UL) ? true : false; +} void set_recon_autosave_freqs(const bool v) { data->recon_config = (data->recon_config & ~0x80000000UL) | (v << 31); @@ -850,6 +853,9 @@ void set_recon_load_hamradios(const bool v) { void set_recon_match_mode(const bool v) { data->recon_config = (data->recon_config & ~0x00800000UL) | (v << 23); } +void set_recon_auto_record_locked(const bool v) { + data->recon_config = (data->recon_config & ~0x00400000UL) | (v << 22); +} /* UI Config 2 */ bool ui_hide_speaker() { @@ -925,25 +931,26 @@ void set_config_converter_freq(int64_t v) { data->converter_frequency_offset = v; } -// frequency correction settings +// Frequency correction settings + bool config_freq_tx_correction_updown() { return data->updown_frequency_tx_correction; } -void set_freq_tx_correction_updown(bool v) { - data->updown_frequency_tx_correction = v; -} bool config_freq_rx_correction_updown() { return data->updown_frequency_rx_correction; } -void set_freq_rx_correction_updown(bool v) { - data->updown_frequency_rx_correction = v; -} uint32_t config_freq_tx_correction() { return data->frequency_tx_correction; } uint32_t config_freq_rx_correction() { return data->frequency_rx_correction; } +void set_freq_tx_correction_updown(bool v) { + data->updown_frequency_tx_correction = v; +} +void set_freq_rx_correction_updown(bool v) { + data->updown_frequency_rx_correction = v; +} void set_config_freq_tx_correction(uint32_t v) { data->frequency_tx_correction = v; } @@ -951,7 +958,8 @@ void set_config_freq_rx_correction(uint32_t v) { data->frequency_rx_correction = v; } -// rotary encoder dial settings +// Rotary encoder dial settings + uint8_t config_encoder_dial_sensitivity() { return data->encoder_dial_sensitivity; } @@ -959,11 +967,12 @@ void set_encoder_dial_sensitivity(uint8_t v) { data->encoder_dial_sensitivity = v; } +// PMem to sdcard settings + bool should_use_sdcard_for_pmem() { return std::filesystem::file_exists(PMEM_FILEFLAG); } -// sd persisting settings int save_persistent_settings_to_file() { std::string filename = PMEM_SETTING_FILE; delete_file(filename); @@ -987,10 +996,14 @@ int load_persistent_settings_from_file() { return false; } +// Pmem size helper + size_t data_size() { return sizeof(data_t); } +// Dump pmem, receiver and transmitter models internals in human readable format + bool debug_dump() { ui::Painter painter{}; std::string debug_dir = "DEBUG"; @@ -1000,6 +1013,7 @@ bool debug_dump() { make_new_directory(debug_dir); filename = next_filename_matching_pattern(debug_dir + "/DEBUG_DUMP_????.TXT"); if (filename.empty()) { + painter.draw_string({0, 320 - 16}, ui::Styles::red, "COULD NOT GET DUMP NAME !"); return false; } // dump data fo filename @@ -1008,7 +1022,6 @@ bool debug_dump() { painter.draw_string({0, 320 - 16}, ui::Styles::red, "ERROR DUMPING " + filename.filename().string() + " !"); return false; } - // write persistent memory pmem_dump_file.write_line("[Persistent Memory]"); @@ -1075,7 +1088,6 @@ bool debug_dump() { // misc_config bits pmem_dump_file.write_line("misc_config config_audio_mute: " + to_string_dec_int(config_audio_mute())); pmem_dump_file.write_line("misc_config config_speaker_disable: " + to_string_dec_int(config_speaker_disable())); - // receiver_model pmem_dump_file.write_line("[Receiver Model]"); pmem_dump_file.write_line("target_frequency: " + to_string_dec_uint(receiver_model.target_frequency())); @@ -1121,9 +1133,8 @@ bool debug_dump() { pmem_dump_file.write_line("sampling_rate: " + to_string_dec_uint(transmitter_model.sampling_rate())); pmem_dump_file.write_line("tx_gain: " + to_string_dec_int(transmitter_model.tx_gain())); pmem_dump_file.write_line("channel_bandwidth: " + to_string_dec_uint(transmitter_model.channel_bandwidth())); - + // on screen information painter.draw_string({0, 320 - 16}, ui::Styles::green, filename.filename().string() + " DUMPED !"); - return true; } diff --git a/firmware/common/portapack_persistent_memory.hpp b/firmware/common/portapack_persistent_memory.hpp index 1931955b..08a4c4df 100644 --- a/firmware/common/portapack_persistent_memory.hpp +++ b/firmware/common/portapack_persistent_memory.hpp @@ -236,6 +236,7 @@ bool recon_clear_output(); bool recon_load_freqs(); bool recon_load_ranges(); bool recon_update_ranges_when_recon(); +bool recon_auto_record_locked(); bool recon_load_hamradios(); bool recon_match_mode(); void set_recon_autosave_freqs(const bool v); @@ -245,6 +246,7 @@ void set_recon_clear_output(const bool v); void set_recon_load_freqs(const bool v); void set_recon_load_ranges(const bool v); void set_recon_update_ranges_when_recon(const bool v); +void set_recon_auto_record_locked(const bool v); void set_recon_load_hamradios(const bool v); void set_recon_match_mode(const bool v);