From f50b376cbd3d07eca884e9b206b572719a5f74a5 Mon Sep 17 00:00:00 2001 From: euquiq <31453004+euquiq@users.noreply.github.com> Date: Mon, 20 Jul 2020 17:43:30 -0300 Subject: [PATCH 1/5] Update ui_scanner.hpp Sorry, I missed this before: These two includes are NOT necessary anymore. --- firmware/application/apps/ui_scanner.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/firmware/application/apps/ui_scanner.hpp b/firmware/application/apps/ui_scanner.hpp index 354700af..da83e83f 100644 --- a/firmware/application/apps/ui_scanner.hpp +++ b/firmware/application/apps/ui_scanner.hpp @@ -25,9 +25,7 @@ #include "ui_receiver.hpp" #include "ui_font_fixed_8x16.hpp" -#include "ui_spectrum.hpp" #include "freqman.hpp" -#include "log_file.hpp" #include "analog_audio_app.hpp" From e8f6e1389e53e8aeb7b6da61331d1a25a3512326 Mon Sep 17 00:00:00 2001 From: euquiq <31453004+euquiq@users.noreply.github.com> Date: Sat, 25 Jul 2020 14:07:03 -0300 Subject: [PATCH 2/5] better "squelch" and coloring big numbers When scanner finds a freq with high dbi, it locks into it "listening" a bit more (less than a second) for either confirm or discard it as an actual high dbi or just a spurious thing. The big number frequency changes color accordingly: Grey = just scanning, yellow = locking in, Green = Found something, allowing the user to listen. --- firmware/application/apps/ui_scanner.cpp | 91 +++++++++++++++++------- firmware/application/apps/ui_scanner.hpp | 12 +++- 2 files changed, 78 insertions(+), 25 deletions(-) diff --git a/firmware/application/apps/ui_scanner.cpp b/firmware/application/apps/ui_scanner.cpp index 1e68d081..26c5c776 100644 --- a/firmware/application/apps/ui_scanner.cpp +++ b/firmware/application/apps/ui_scanner.cpp @@ -21,7 +21,7 @@ */ #include "ui_scanner.hpp" - +#include "portapack_persistent_memory.hpp" #include "baseband_api.hpp" #include "string_format.hpp" #include "audio.hpp" @@ -66,6 +66,14 @@ bool ScannerThread::is_userpause() { return _userpause; } +void ScannerThread::set_freq_lock(const uint32_t v) { + _freq_lock = v; +} + +uint32_t ScannerThread::is_freq_lock() { + return _freq_lock; +} + msg_t ScannerThread::static_fn(void* arg) { auto obj = static_cast(arg); obj->run(); @@ -75,27 +83,44 @@ msg_t ScannerThread::static_fn(void* arg) { void ScannerThread::run() { if (frequency_list_.size()) { //IF THERE IS A FREQUENCY LIST ... RetuneMessage message { }; - uint32_t frequency_index = 0; + uint32_t frequency_index = frequency_list_.size(); + uint32_t freqlock_counter=0; while( !chThdShouldTerminate() ) { if (_scanning) { - // Retune - receiver_model.set_tuning_frequency(frequency_list_[frequency_index]); - message.range = frequency_index; + if (_freq_lock == 0) { //normal scanning + frequency_index++; + if (frequency_index >= frequency_list_.size()) + frequency_index = 0; + receiver_model.set_tuning_frequency(frequency_list_[frequency_index]); // Retune + } else { + chThdSleepMilliseconds(25); //Extra time ? + } + + message.range = frequency_index; //Inform freq (for coloring purposes also!) EventDispatcher::send_message(message); - - frequency_index++; - if (frequency_index >= frequency_list_.size()) - frequency_index = 0; } - chThdSleepMilliseconds(50); //50 is enough for reception stabilization, increase for more precise scanning ? + chThdSleepMilliseconds(50); } } } void ScannerView::handle_retune(uint32_t i) { - big_display.set(frequency_list[i]); //Show the big Freq - text_cycle.set( to_string_dec_uint(i + 1,3) ); - if (description_list[i].size() > 0) desc_cycle.set( description_list[i] ); //If this is a new description: show + switch (scan_thread->is_freq_lock()) + { + case 0: //NO FREQ LOCK, ONGOING STANDARD SCANNING + text_cycle.set( to_string_dec_uint(i + 1,3) ); + if (description_list[i].size() > 0) desc_cycle.set( description_list[i] ); //If this is a new description: show + break; + case 1: + big_display.set_style(&style_yellow); //STARTING LOCK FREQ + break; + case MAX_FREQ_LOCK: + big_display.set_style(&style_green); //FREQ LOCK FULL, GREEN! + break; + default: //freq lock is checking the signal, do not update display + return; + } + big_display.set(frequency_list[i]); //UPDATE the big Freq after 0, 1 or MAX_FREQ_LOCK (at least, for color synching) } void ScannerView::focus() { @@ -145,7 +170,14 @@ ScannerView::ScannerView( def_step = change_mode(AM); //Start on AM field_mode.set_by_value(AM); //Reflect the mode into the manual selector - big_display.set_style(&style_green); //Start with green color + big_display.set_style(&style_grey); //Start with gray color + + //HELPER: Pre-setting a manual range, based on stored frequency + rf::Frequency stored_freq = persistent_memory::tuned_frequency(); + frequency_range.min = stored_freq - 1000000; + button_manual_start.set_text(to_string_short_freq(frequency_range.min)); + frequency_range.max = stored_freq + 1000000; + button_manual_end.set_text(to_string_short_freq(frequency_range.max)); button_manual_start.on_select = [this, &nav](Button& button) { auto new_view = nav_.push(frequency_range.min); @@ -165,10 +197,9 @@ ScannerView::ScannerView( button_pause.on_select = [this](Button&) { if (scan_thread->is_userpause()) { - timer = wait * 10; //Unlock timer pause on_statistics_update + timer = wait * 10; //Unlock timer pause on_statistics_update button_pause.set_text("PAUSE"); //resume scanning (show button for pause) - scan_thread->set_userpause(false); - //scan_resume(); + scan_thread->set_userpause(false); //Signal user's will } else { scan_pause(); scan_thread->set_userpause(true); @@ -190,13 +221,14 @@ ScannerView::ScannerView( } else if (frequency_range.min > frequency_range.max) { nav_.display_modal("Error", "END freq\nis lower than START"); } else { + audio::output::stop(); scan_thread->stop(); //STOP SCANNER THREAD frequency_list.clear(); description_list.clear(); def_step = step_mode.selected_index_value(); //Use def_step from manual selector description_list.push_back( - "M:" + to_string_short_freq(frequency_range.min) + ">" + "M:" + to_string_short_freq(frequency_range.min) + " >" + to_string_short_freq(frequency_range.max) + " S:" + to_string_short_freq(def_step) ); @@ -249,7 +281,7 @@ ScannerView::ScannerView( } frequency_list.push_back(entry.frequency_a); //Store starting freq and description description_list.push_back("R:" + to_string_short_freq(entry.frequency_a) - + ">" + to_string_short_freq(entry.frequency_b) + + " >" + to_string_short_freq(entry.frequency_b) + " S:" + to_string_short_freq(def_step)); while (frequency_list.size() < MAX_DB_ENTRY && entry.frequency_a <= entry.frequency_b) { //add the rest of the range entry.frequency_a+=def_step; @@ -287,12 +319,21 @@ void ScannerView::on_statistics_update(const ChannelStatistics& statistics) { } else if (!timer) { - if (statistics.max_db > -squelch) { //There is something on the air... - scan_pause(); - timer++; - } + if (statistics.max_db > -squelch) { //There is something on the air... + if (scan_thread->is_freq_lock() >= MAX_FREQ_LOCK) { //checking time reached + scan_pause(); + timer++; + } else { + scan_thread->set_freq_lock( scan_thread->is_freq_lock() + 1 ); //in lock period, still analyzing the signal + } + } else { //There is NOTHING on the air + if (scan_thread->is_freq_lock() > 0) { //But are we already in freq_lock ? + big_display.set_style(&style_grey); //Back to grey color + scan_thread->set_freq_lock(0); //Reset the scanner lock, since there is no signal + } + } } - else + else //Ongoing wait time { timer++; } @@ -301,6 +342,7 @@ void ScannerView::on_statistics_update(const ChannelStatistics& statistics) { void ScannerView::scan_pause() { if (scan_thread->is_scanning()) { + scan_thread->set_freq_lock(0); //Reset the scanner lock (because user paused, or MAX_FREQ_LOCK reached) for next freq scan scan_thread->set_scanning(false); // WE STOP SCANNING audio::output::start(); } @@ -309,6 +351,7 @@ void ScannerView::scan_pause() { void ScannerView::scan_resume() { if (!scan_thread->is_scanning()) { audio::output::stop(); + big_display.set_style(&style_grey); //Back to grey color scan_thread->set_scanning(true); // WE RESCAN } } diff --git a/firmware/application/apps/ui_scanner.hpp b/firmware/application/apps/ui_scanner.hpp index da83e83f..f9ee3aa7 100644 --- a/firmware/application/apps/ui_scanner.hpp +++ b/firmware/application/apps/ui_scanner.hpp @@ -22,7 +22,6 @@ #include "ui.hpp" #include "receiver_model.hpp" - #include "ui_receiver.hpp" #include "ui_font_fixed_8x16.hpp" #include "freqman.hpp" @@ -30,6 +29,7 @@ #define MAX_DB_ENTRY 500 +#define MAX_FREQ_LOCK 10 //50ms cycles scanner locks into freq when signal detected, to verify signal is not spureous namespace ui { @@ -49,6 +49,9 @@ public: void set_userpause(const bool v); bool is_userpause(); + void set_freq_lock(const uint32_t v); + uint32_t is_freq_lock(); + void stop(); ScannerThread(const ScannerThread&) = delete; @@ -62,6 +65,7 @@ private: bool _scanning { true }; bool _userpause { false }; + uint32_t _freq_lock { 0 }; static msg_t static_fn(void* arg); void run(); }; @@ -81,6 +85,12 @@ public: .foreground = Color::grey(), }; + const Style style_yellow { //Found signal + .font = font::fixed_8x16, + .background = Color::black(), + .foreground = Color::dark_yellow(), + }; + const Style style_green { //Found signal .font = font::fixed_8x16, .background = Color::black(), From 03084251c5c1b901bf43bee2edeae6600b65bb46 Mon Sep 17 00:00:00 2001 From: euquiq <31453004+euquiq@users.noreply.github.com> Date: Tue, 28 Jul 2020 01:21:52 -0300 Subject: [PATCH 3/5] Added MIC TX and FREQ DEL buttons MIC TX button :Shortcut for jumping into TX -> MIC app. FREQ DEL button: Deletes currently displayed frequency from temporary scanning memory. Ideal to get rid of those not wanted "noisy" freqs in the middle of a range scan. Also, some code optimizations thrown in. --- firmware/application/apps/ui_scanner.cpp | 123 ++++++++++++++++------- firmware/application/apps/ui_scanner.hpp | 40 ++++++-- 2 files changed, 114 insertions(+), 49 deletions(-) diff --git a/firmware/application/apps/ui_scanner.cpp b/firmware/application/apps/ui_scanner.cpp index 26c5c776..eafdf4d1 100644 --- a/firmware/application/apps/ui_scanner.cpp +++ b/firmware/application/apps/ui_scanner.cpp @@ -24,8 +24,6 @@ #include "portapack_persistent_memory.hpp" #include "baseband_api.hpp" #include "string_format.hpp" -#include "audio.hpp" - using namespace portapack; @@ -58,14 +56,6 @@ bool ScannerThread::is_scanning() { return _scanning; } -void ScannerThread::set_userpause(const bool v) { - _userpause = v; -} - -bool ScannerThread::is_userpause() { - return _userpause; -} - void ScannerThread::set_freq_lock(const uint32_t v) { _freq_lock = v; } @@ -74,6 +64,10 @@ uint32_t ScannerThread::is_freq_lock() { return _freq_lock; } +void ScannerThread::set_freq_del(const uint32_t v) { + _freq_del = v; +} + msg_t ScannerThread::static_fn(void* arg) { auto obj = static_cast(arg); obj->run(); @@ -81,25 +75,42 @@ msg_t ScannerThread::static_fn(void* arg) { } void ScannerThread::run() { - if (frequency_list_.size()) { //IF THERE IS A FREQUENCY LIST ... + if (frequency_list_.size()) { //IF THERE IS A FREQUENCY LIST ... RetuneMessage message { }; uint32_t frequency_index = frequency_list_.size(); - uint32_t freqlock_counter=0; while( !chThdShouldTerminate() ) { - if (_scanning) { - if (_freq_lock == 0) { //normal scanning + if (_scanning) + { //Scanning + if (_freq_lock == 0) { //normal scanning (not performing freq_lock) frequency_index++; if (frequency_index >= frequency_list_.size()) frequency_index = 0; receiver_model.set_tuning_frequency(frequency_list_[frequency_index]); // Retune - } else { - chThdSleepMilliseconds(25); //Extra time ? } - message.range = frequency_index; //Inform freq (for coloring purposes also!) EventDispatcher::send_message(message); + } + else + { //If not scanning, check for user asking to delete a freq: + if (_freq_del != 0) { //There is a frequency to delete + for (uint16_t i = 0; i < frequency_list_.size(); i++) { //Search for the freq to delete + if (frequency_list_[i] == _freq_del) + { //found: Erase it + frequency_list_.erase(frequency_list_.begin() + i); + if (i==0) //set scan index one place back to compensate + i=frequency_list_.size(); + else + i--; + + break; + } + } + _freq_del = 0; //deleted. + } + } - chThdSleepMilliseconds(50); + chThdSleepMilliseconds(60); //This value on 50, when scan resume, it does not stabilize for the next freq in list, it jumped one more ahead. + //With 100 it worked fine but scanner is slow. This may need fixing } } } @@ -107,9 +118,10 @@ void ScannerThread::run() { void ScannerView::handle_retune(uint32_t i) { switch (scan_thread->is_freq_lock()) { - case 0: //NO FREQ LOCK, ONGOING STANDARD SCANNING + case 0: //NO FREQ LOCK, ONGOING STANDARD SCANNING text_cycle.set( to_string_dec_uint(i + 1,3) ); - if (description_list[i].size() > 0) desc_cycle.set( description_list[i] ); //If this is a new description: show + current_index = i; //since it is an ongoing scan, this is a new index + if (description_list[current_index].size() > 0) desc_cycle.set( description_list[current_index] ); //Show new description break; case 1: big_display.set_style(&style_yellow); //STARTING LOCK FREQ @@ -120,7 +132,7 @@ void ScannerView::handle_retune(uint32_t i) { default: //freq lock is checking the signal, do not update display return; } - big_display.set(frequency_list[i]); //UPDATE the big Freq after 0, 1 or MAX_FREQ_LOCK (at least, for color synching) + big_display.set(frequency_list[current_index]); //UPDATE the big Freq after 0, 1 or MAX_FREQ_LOCK (at least, for color synching) } void ScannerView::focus() { @@ -164,7 +176,9 @@ ScannerView::ScannerView( &step_mode, &button_manual_scan, &button_pause, - &button_audio_app + &button_audio_app, + &button_remove, + &button_mic_app }); def_step = change_mode(AM); //Start on AM @@ -196,25 +210,47 @@ ScannerView::ScannerView( }; button_pause.on_select = [this](Button&) { - if (scan_thread->is_userpause()) { - timer = wait * 10; //Unlock timer pause on_statistics_update - button_pause.set_text("PAUSE"); //resume scanning (show button for pause) - scan_thread->set_userpause(false); //Signal user's will - } else { + if ( userpause ) + user_resume(); + else { scan_pause(); - scan_thread->set_userpause(true); - button_pause.set_text("RESUME"); //PAUSED, show resume + button_pause.set_text("RESUME"); //PAUSED, show resume + userpause=true; } }; button_audio_app.on_select = [this](Button&) { - if (scan_thread->is_scanning()) - scan_thread->set_scanning(false); + //if (scan_thread->is_scanning()) + // scan_thread->set_scanning(false); scan_thread->stop(); nav_.pop(); nav_.push(); }; + button_mic_app.on_select = [this](Button&) { + //if (scan_thread->is_scanning()) + // scan_thread->set_scanning(false); + scan_thread->stop(); + nav_.pop(); + nav_.push(); + }; + + button_remove.on_select = [this](Button&) { + if (frequency_list.size() > current_index) { + if (scan_thread->is_scanning()) //STOP Scanning if necessary + scan_thread->set_scanning(false); + scan_thread->set_freq_del(frequency_list[current_index]); + description_list.erase(description_list.begin() + current_index); + frequency_list.erase(frequency_list.begin() + current_index); + show_max(); //UPDATE new list size on screen + chThdSleepMilliseconds(300); //"debouncing" pause so user take finger off + timer = wait * 10; //Unlock timer pause on_statistics_update + scan_thread->set_freq_lock(0); //Reset the scanner lock + if ( userpause ) //If user-paused, resume + user_resume(); + } + }; + button_manual_scan.on_select = [this](Button&) { if (!frequency_range.min || !frequency_range.max) { nav_.display_modal("Error", "Both START and END freqs\nneed a value"); @@ -239,21 +275,25 @@ ScannerView::ScannerView( description_list.push_back(""); //If empty, will keep showing the last description frequency+=def_step; } - show_max(); + if ( userpause ) //If user-paused, resume + user_resume(); + big_display.set_style(&style_grey); //Back to grey color start_scan_thread(); //RESTART SCANNER THREAD } }; field_mode.on_change = [this](size_t, OptionsField::value_t v) { if (scan_thread->is_scanning()) - scan_thread->set_scanning(false); // WE STOP SCANNING + scan_thread->set_scanning(false); //STOP SCANNING audio::output::stop(); scan_thread->stop(); receiver_model.disable(); baseband::shutdown(); chThdSleepMilliseconds(50); change_mode(v); + if ( userpause ) //If user-paused, resume + user_resume(); start_scan_thread(); }; @@ -310,7 +350,7 @@ ScannerView::ScannerView( } void ScannerView::on_statistics_update(const ChannelStatistics& statistics) { - if (!scan_thread->is_userpause()) + if ( !userpause ) { if (timer >= (wait * 10) ) { @@ -349,11 +389,16 @@ void ScannerView::scan_pause() { } void ScannerView::scan_resume() { - if (!scan_thread->is_scanning()) { - audio::output::stop(); - big_display.set_style(&style_grey); //Back to grey color - scan_thread->set_scanning(true); // WE RESCAN - } + audio::output::stop(); + big_display.set_style(&style_grey); //Back to grey color + if (!scan_thread->is_scanning()) + scan_thread->set_scanning(true); // RESUME! +} + +void ScannerView::user_resume() { + timer = wait * 10; //Unlock timer pause on_statistics_update ( will trigger a scan_resume() ) + button_pause.set_text("PAUSE"); //Show button for pause + userpause=false; //Resume scanning } void ScannerView::on_headphone_volume_changed(int32_t v) { diff --git a/firmware/application/apps/ui_scanner.hpp b/firmware/application/apps/ui_scanner.hpp index f9ee3aa7..010a28fe 100644 --- a/firmware/application/apps/ui_scanner.hpp +++ b/firmware/application/apps/ui_scanner.hpp @@ -26,6 +26,8 @@ #include "ui_font_fixed_8x16.hpp" #include "freqman.hpp" #include "analog_audio_app.hpp" +#include "audio.hpp" +#include "ui_mictx.hpp" #define MAX_DB_ENTRY 500 @@ -46,12 +48,11 @@ public: void set_scanning(const bool v); bool is_scanning(); - void set_userpause(const bool v); - bool is_userpause(); - void set_freq_lock(const uint32_t v); uint32_t is_freq_lock(); + void set_freq_del(const uint32_t v); + void stop(); ScannerThread(const ScannerThread&) = delete; @@ -64,8 +65,8 @@ private: Thread* thread { nullptr }; bool _scanning { true }; - bool _userpause { false }; uint32_t _freq_lock { 0 }; + uint32_t _freq_del { 0 }; static msg_t static_fn(void* arg); void run(); }; @@ -97,6 +98,12 @@ public: .foreground = Color::green(), }; + const Style style_red { //erasing freq + .font = font::fixed_8x16, + .background = Color::black(), + .foreground = Color::red(), + }; + std::string title() const override { return "SCANNER"; }; std::vector frequency_list{ }; std::vector description_list { }; @@ -111,6 +118,7 @@ private: void show_max(); void scan_pause(); void scan_resume(); + void user_resume(); void on_statistics_update(const ChannelStatistics& statistics); void on_headphone_volume_changed(int32_t v); @@ -122,13 +130,15 @@ private: uint32_t wait { 0 }; size_t def_step { 0 }; freqman_db database { }; + uint32_t current_index { 0 }; + bool userpause { false }; Labels labels { { { 0 * 8, 0 * 16 }, "LNA: VGA: AMP: VOL:", Color::light_grey() }, { { 0 * 8, 1* 16 }, "BW: SQUELCH: /99 WAIT:", Color::light_grey() }, { { 3 * 8, 10 * 16 }, "START END MANUAL", Color::light_grey() }, - { { 0 * 8, 14 * 16 }, "MODE:", Color::light_grey() }, - { { 11 * 8, 14 * 16 }, "STEP:", Color::light_grey() }, + { { 0 * 8, 27 * 8 }, "MODE:", Color::light_grey() }, + { { 11 * 8, 27 * 8 }, "STEP:", Color::light_grey() }, }; LNAGainField field_lna { @@ -210,7 +220,7 @@ private: }; OptionsField field_mode { - { 5 * 8, 14 * 16 }, + { 5 * 8, 27 * 8 }, 6, { { " AM ", 0 }, @@ -220,7 +230,7 @@ private: }; OptionsField step_mode { - { 17 * 8, 14 * 16 }, + { 17 * 8, 27 * 8 }, 12, { { "5Khz (SA AM)", 5000 }, @@ -237,14 +247,24 @@ private: }; Button button_pause { - { 12, 17 * 16, 96, 24 }, + { 12, 15 * 16, 96, 24 }, "PAUSE" }; Button button_audio_app { - { 124, 17 * 16, 96, 24 }, + { 124, 15 * 16, 96, 24 }, "AUDIO APP" }; + + Button button_remove { + { 12, 17 * 16, 96, 24 }, + "DEL FREQ" + }; + + Button button_mic_app { + { 124, 17 * 16, 96, 24 }, + "MIC TX APP" + }; std::unique_ptr scan_thread { }; From ee67f74fa7e14225e4535846f9856b6a49b737ca Mon Sep 17 00:00:00 2001 From: euquiq <31453004+euquiq@users.noreply.github.com> Date: Tue, 28 Jul 2020 21:05:10 -0300 Subject: [PATCH 4/5] Added two new buttons and other enhancements Added buttons for: Change scanning direction (ascending / descending) Saving current freq into the SCANNER.TXT file (Please notice that, on the other hand -for safety issues- the DEL FQ button, deletes the frequency only from the temp memory on the actual scanning session, but does NOT erases the freq. inside the SCANNER.TXT) Also there are other bug fixes and scanning speed enhancements. --- firmware/application/apps/ui_scanner.cpp | 132 ++++++++++++++++------- firmware/application/apps/ui_scanner.hpp | 43 +++++--- 2 files changed, 125 insertions(+), 50 deletions(-) diff --git a/firmware/application/apps/ui_scanner.cpp b/firmware/application/apps/ui_scanner.cpp index eafdf4d1..63b5f9bb 100644 --- a/firmware/application/apps/ui_scanner.cpp +++ b/firmware/application/apps/ui_scanner.cpp @@ -21,9 +21,6 @@ */ #include "ui_scanner.hpp" -#include "portapack_persistent_memory.hpp" -#include "baseband_api.hpp" -#include "string_format.hpp" using namespace portapack; @@ -68,6 +65,12 @@ void ScannerThread::set_freq_del(const uint32_t v) { _freq_del = v; } +void ScannerThread::change_scanning_direction() { + _fwd = !_fwd; + chThdSleepMilliseconds(300); //Give some pause after reversing scanning direction + +} + msg_t ScannerThread::static_fn(void* arg) { auto obj = static_cast(arg); obj->run(); @@ -78,39 +81,47 @@ void ScannerThread::run() { if (frequency_list_.size()) { //IF THERE IS A FREQUENCY LIST ... RetuneMessage message { }; uint32_t frequency_index = frequency_list_.size(); + bool restart_scan = false; //Flag whenever scanning is restarting after a pause while( !chThdShouldTerminate() ) { - if (_scanning) - { //Scanning + if (_scanning) { //Scanning if (_freq_lock == 0) { //normal scanning (not performing freq_lock) - frequency_index++; - if (frequency_index >= frequency_list_.size()) - frequency_index = 0; - receiver_model.set_tuning_frequency(frequency_list_[frequency_index]); // Retune - } + if (!restart_scan) { //looping at full speed + if (_fwd) { //forward + frequency_index++; + if (frequency_index >= frequency_list_.size()) + frequency_index = 0; + + } else { //reverse + if (frequency_index < 1) + frequency_index = frequency_list_.size(); + frequency_index--; + } + receiver_model.set_tuning_frequency(frequency_list_[frequency_index]); // Retune + } + else + restart_scan=false; //Effectively skipping first retuning, giving system time + } message.range = frequency_index; //Inform freq (for coloring purposes also!) EventDispatcher::send_message(message); } - else - { //If not scanning, check for user asking to delete a freq: - if (_freq_del != 0) { //There is a frequency to delete + else { //NOT scanning + restart_scan=true; //Flag the need for skipping a cycle when restarting scan + if (_freq_del != 0) { //There is a frequency to delete for (uint16_t i = 0; i < frequency_list_.size(); i++) { //Search for the freq to delete if (frequency_list_[i] == _freq_del) - { //found: Erase it + { //found: Erase it frequency_list_.erase(frequency_list_.begin() + i); - if (i==0) //set scan index one place back to compensate + if (i==0) //set scan index one place back to compensate i=frequency_list_.size(); else i--; - break; } } - _freq_del = 0; //deleted. + _freq_del = 0; //deleted. } - } - chThdSleepMilliseconds(60); //This value on 50, when scan resume, it does not stabilize for the next freq in list, it jumped one more ahead. - //With 100 it worked fine but scanner is slow. This may need fixing + chThdSleepMilliseconds(50); //Needed to (eventually) stabilize the receiver into new freq } } } @@ -123,11 +134,11 @@ void ScannerView::handle_retune(uint32_t i) { current_index = i; //since it is an ongoing scan, this is a new index if (description_list[current_index].size() > 0) desc_cycle.set( description_list[current_index] ); //Show new description break; - case 1: - big_display.set_style(&style_yellow); //STARTING LOCK FREQ + case 1: //STARTING LOCK FREQ + big_display.set_style(&style_yellow); break; - case MAX_FREQ_LOCK: - big_display.set_style(&style_green); //FREQ LOCK FULL, GREEN! + case MAX_FREQ_LOCK: //FREQ IS STRONG: GREEN and scanner will pause when on_statistics_update() + big_display.set_style(&style_green); break; default: //freq lock is checking the signal, do not update display return; @@ -146,8 +157,10 @@ ScannerView::~ScannerView() { } void ScannerView::show_max() { //show total number of freqs to scan - if (frequency_list.size() == MAX_DB_ENTRY) + if (frequency_list.size() == MAX_DB_ENTRY) { + text_max.set_style(&style_red); text_max.set( "/ " + to_string_dec_uint(MAX_DB_ENTRY) + " (DB MAX!)"); + } else text_max.set( "/ " + to_string_dec_uint(frequency_list.size())); } @@ -176,15 +189,18 @@ ScannerView::ScannerView( &step_mode, &button_manual_scan, &button_pause, + &button_dir, &button_audio_app, - &button_remove, - &button_mic_app + &button_mic_app, + &button_add, + &button_remove + }); def_step = change_mode(AM); //Start on AM field_mode.set_by_value(AM); //Reflect the mode into the manual selector - big_display.set_style(&style_grey); //Start with gray color + //big_display.set_style(&style_grey); //Start with gray color //HELPER: Pre-setting a manual range, based on stored frequency rf::Frequency stored_freq = persistent_memory::tuned_frequency(); @@ -220,16 +236,12 @@ ScannerView::ScannerView( }; button_audio_app.on_select = [this](Button&) { - //if (scan_thread->is_scanning()) - // scan_thread->set_scanning(false); scan_thread->stop(); nav_.pop(); nav_.push(); }; - button_mic_app.on_select = [this](Button&) { - //if (scan_thread->is_scanning()) - // scan_thread->set_scanning(false); + button_mic_app.on_select = [this](Button&) { scan_thread->stop(); nav_.pop(); nav_.push(); @@ -290,13 +302,59 @@ ScannerView::ScannerView( scan_thread->stop(); receiver_model.disable(); baseband::shutdown(); - chThdSleepMilliseconds(50); change_mode(v); if ( userpause ) //If user-paused, resume user_resume(); start_scan_thread(); }; + button_dir.on_select = [this](Button&) { + scan_thread->change_scanning_direction(); + if ( userpause ) //If user-paused, resume + user_resume(); + big_display.set_style(&style_grey); //Back to grey color + }; + + button_add.on_select = [this](Button&) { //frequency_list[current_index] + File scanner_file; + auto result = scanner_file.open("FREQMAN/SCANNER.TXT"); //First search if freq is already in txt + if (!result.is_valid()) { + std::string frequency_to_add = "f=" + + to_string_dec_uint(frequency_list[current_index] / 1000) + + to_string_dec_uint(frequency_list[current_index] % 1000UL, 3, '0'); + 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 < scanner_file.size();pointer++) { + + scanner_file.seek(pointer); + scanner_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) { + nav_.display_modal("Error", "Frequency already exists"); + big_display.set(frequency_list[current_index]); //After showing an error + } + else { + auto result = scanner_file.append("FREQMAN/SCANNER.TXT"); //Second: append if it is not there + scanner_file.write_line(frequency_to_add + ",d=ADD FQ"); + } + } else + { + nav_.display_modal("Error", "Cannot open SCANNER.TXT\nfor appending freq."); + big_display.set(frequency_list[current_index]); //After showing an error + } + }; + //PRE-CONFIGURATION: field_wait.on_change = [this](int32_t v) { wait = v; }; field_wait.set_value(5); field_squelch.on_change = [this](int32_t v) { squelch = v; }; field_squelch.set_value(30); @@ -350,11 +408,11 @@ ScannerView::ScannerView( } void ScannerView::on_statistics_update(const ChannelStatistics& statistics) { - if ( !userpause ) + if ( !userpause ) //Scanning not user-paused { if (timer >= (wait * 10) ) { - timer=0; + timer = 0; scan_resume(); } else if (!timer) @@ -396,7 +454,7 @@ void ScannerView::scan_resume() { } void ScannerView::user_resume() { - timer = wait * 10; //Unlock timer pause on_statistics_update ( will trigger a scan_resume() ) + timer = wait * 10; //Will trigger a scan_resume() on_statistics_update, also advancing to next freq. button_pause.set_text("PAUSE"); //Show button for pause userpause=false; //Resume scanning } diff --git a/firmware/application/apps/ui_scanner.hpp b/firmware/application/apps/ui_scanner.hpp index 010a28fe..35598e12 100644 --- a/firmware/application/apps/ui_scanner.hpp +++ b/firmware/application/apps/ui_scanner.hpp @@ -28,6 +28,10 @@ #include "analog_audio_app.hpp" #include "audio.hpp" #include "ui_mictx.hpp" +#include "portapack_persistent_memory.hpp" +#include "baseband_api.hpp" +#include "string_format.hpp" +#include "file.hpp" #define MAX_DB_ENTRY 500 @@ -53,6 +57,8 @@ public: void set_freq_del(const uint32_t v); + void change_scanning_direction(); + void stop(); ScannerThread(const ScannerThread&) = delete; @@ -65,6 +71,7 @@ private: Thread* thread { nullptr }; bool _scanning { true }; + bool _fwd { true }; uint32_t _freq_lock { 0 }; uint32_t _freq_del { 0 }; static msg_t static_fn(void* arg); @@ -137,8 +144,8 @@ private: { { 0 * 8, 0 * 16 }, "LNA: VGA: AMP: VOL:", Color::light_grey() }, { { 0 * 8, 1* 16 }, "BW: SQUELCH: /99 WAIT:", Color::light_grey() }, { { 3 * 8, 10 * 16 }, "START END MANUAL", Color::light_grey() }, - { { 0 * 8, 27 * 8 }, "MODE:", Color::light_grey() }, - { { 11 * 8, 27 * 8 }, "STEP:", Color::light_grey() }, + { { 0 * 8, (26 * 8) + 4 }, "MODE:", Color::light_grey() }, + { { 11 * 8, (26 * 8) + 4 }, "STEP:", Color::light_grey() }, }; LNAGainField field_lna { @@ -220,7 +227,7 @@ private: }; OptionsField field_mode { - { 5 * 8, 27 * 8 }, + { 5 * 8, (26 * 8) + 4 }, 6, { { " AM ", 0 }, @@ -230,7 +237,7 @@ private: }; OptionsField step_mode { - { 17 * 8, 27 * 8 }, + { 17 * 8, (26 * 8) + 4 }, 12, { { "5Khz (SA AM)", 5000 }, @@ -247,23 +254,33 @@ private: }; Button button_pause { - { 12, 15 * 16, 96, 24 }, + { 0, (15 * 16) - 4, 72, 28 }, "PAUSE" }; - Button button_audio_app { - { 124, 15 * 16, 96, 24 }, - "AUDIO APP" + Button button_dir { + { 0, (35 * 8) - 4, 72, 28 }, + "FW> scan_thread { }; From 1b2c68b3c0099f09dcd9fc374101bc2f98f2749a Mon Sep 17 00:00:00 2001 From: euquiq <31453004+euquiq@users.noreply.github.com> Date: Sat, 1 Aug 2020 00:58:34 -0300 Subject: [PATCH 5/5] New squelch behavior and fixes Squelch value now goes from -90 to +20 and it's directly compared against the max_db parameter returned from each freq scanned by the radio subsystem, with no adjusts or manipulation (you adjust the number as will be used). Less squelch means weaker signals will trigger it. (as expected). There was a tiny cosmetic bug when you deleted a frequency from the scanning memory: The description was not erased from screen and you could see it while the scan did not resume. There was another bug on the pause button: If you asked for another manual scan range when paused, the button kept the text "RESUME" (its text was not reset to "PAUSE" again). --- firmware/application/apps/ui_scanner.cpp | 28 ++++++++++-------------- firmware/application/apps/ui_scanner.hpp | 6 ++--- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/firmware/application/apps/ui_scanner.cpp b/firmware/application/apps/ui_scanner.cpp index 63b5f9bb..65c4788d 100644 --- a/firmware/application/apps/ui_scanner.cpp +++ b/firmware/application/apps/ui_scanner.cpp @@ -105,7 +105,6 @@ void ScannerThread::run() { EventDispatcher::send_message(message); } else { //NOT scanning - restart_scan=true; //Flag the need for skipping a cycle when restarting scan if (_freq_del != 0) { //There is a frequency to delete for (uint16_t i = 0; i < frequency_list_.size(); i++) { //Search for the freq to delete if (frequency_list_[i] == _freq_del) @@ -120,6 +119,9 @@ void ScannerThread::run() { } _freq_del = 0; //deleted. } + else { + restart_scan=true; //Flag the need for skipping a cycle when restarting scan + } } chThdSleepMilliseconds(50); //Needed to (eventually) stabilize the receiver into new freq } @@ -161,8 +163,10 @@ void ScannerView::show_max() { //show total number of freqs to scan text_max.set_style(&style_red); text_max.set( "/ " + to_string_dec_uint(MAX_DB_ENTRY) + " (DB MAX!)"); } - else + else { + text_max.set_style(&style_grey); text_max.set( "/ " + to_string_dec_uint(frequency_list.size())); + } } ScannerView::ScannerView( @@ -200,8 +204,6 @@ ScannerView::ScannerView( def_step = change_mode(AM); //Start on AM field_mode.set_by_value(AM); //Reflect the mode into the manual selector - //big_display.set_style(&style_grey); //Start with gray color - //HELPER: Pre-setting a manual range, based on stored frequency rf::Frequency stored_freq = persistent_memory::tuned_frequency(); frequency_range.min = stored_freq - 1000000; @@ -255,8 +257,7 @@ ScannerView::ScannerView( description_list.erase(description_list.begin() + current_index); frequency_list.erase(frequency_list.begin() + current_index); show_max(); //UPDATE new list size on screen - chThdSleepMilliseconds(300); //"debouncing" pause so user take finger off - timer = wait * 10; //Unlock timer pause on_statistics_update + desc_cycle.set(" "); //Clean up description (cosmetic detail) scan_thread->set_freq_lock(0); //Reset the scanner lock if ( userpause ) //If user-paused, resume user_resume(); @@ -296,16 +297,12 @@ ScannerView::ScannerView( }; field_mode.on_change = [this](size_t, OptionsField::value_t v) { - if (scan_thread->is_scanning()) - scan_thread->set_scanning(false); //STOP SCANNING - audio::output::stop(); - scan_thread->stop(); receiver_model.disable(); baseband::shutdown(); change_mode(v); - if ( userpause ) //If user-paused, resume - user_resume(); - start_scan_thread(); + if ( !scan_thread->is_scanning() ) //for some motive, audio output gets stopped. + audio::output::start(); //So if scan was stopped we resume audio + receiver_model.enable(); }; button_dir.on_select = [this](Button&) { @@ -357,7 +354,7 @@ ScannerView::ScannerView( //PRE-CONFIGURATION: field_wait.on_change = [this](int32_t v) { wait = v; }; field_wait.set_value(5); - field_squelch.on_change = [this](int32_t v) { squelch = v; }; field_squelch.set_value(30); + field_squelch.on_change = [this](int32_t v) { squelch = v; }; field_squelch.set_value(-10); field_volume.set_value((receiver_model.headphone_volume() - audio::headphone::volume_range().max).decibel() + 99); field_volume.on_change = [this](int32_t v) { this->on_headphone_volume_changed(v); }; // LEARN FREQUENCIES @@ -417,7 +414,7 @@ void ScannerView::on_statistics_update(const ChannelStatistics& statistics) { } else if (!timer) { - if (statistics.max_db > -squelch) { //There is something on the air... + if (statistics.max_db > squelch ) { //There is something on the air...(statistics.max_db > -squelch) if (scan_thread->is_freq_lock() >= MAX_FREQ_LOCK) { //checking time reached scan_pause(); timer++; @@ -511,7 +508,6 @@ size_t ScannerView::change_mode(uint8_t new_mod) { //Before this, do a scan_thre } return mod_step[new_mod]; - } void ScannerView::start_scan_thread() { diff --git a/firmware/application/apps/ui_scanner.hpp b/firmware/application/apps/ui_scanner.hpp index 35598e12..d2befbfe 100644 --- a/firmware/application/apps/ui_scanner.hpp +++ b/firmware/application/apps/ui_scanner.hpp @@ -142,7 +142,7 @@ private: Labels labels { { { 0 * 8, 0 * 16 }, "LNA: VGA: AMP: VOL:", Color::light_grey() }, - { { 0 * 8, 1* 16 }, "BW: SQUELCH: /99 WAIT:", Color::light_grey() }, + { { 0 * 8, 1* 16 }, "BW: SQUELCH: db WAIT:", Color::light_grey() }, { { 3 * 8, 10 * 16 }, "START END MANUAL", Color::light_grey() }, { { 0 * 8, (26 * 8) + 4 }, "MODE:", Color::light_grey() }, { { 11 * 8, (26 * 8) + 4 }, "STEP:", Color::light_grey() }, @@ -176,8 +176,8 @@ private: NumberField field_squelch { { 15 * 8, 1 * 16 }, - 2, - { 0, 99 }, + 3, + { -90, 20 }, 1, ' ', };