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 { };