2017-05-18 06:06:11 -04:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
2018-04-19 15:50:32 -04:00
|
|
|
* Copyright (C) 2018 Furrtek
|
2017-05-18 06:06:11 -04:00
|
|
|
*
|
|
|
|
* This file is part of PortaPack.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; see the file COPYING. If not, write to
|
|
|
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ui_scanner.hpp"
|
2023-07-29 18:36:00 -04:00
|
|
|
|
|
|
|
#include "optional.hpp"
|
2020-09-11 15:11:42 -04:00
|
|
|
#include "ui_fileman.hpp"
|
2023-07-17 14:43:37 -04:00
|
|
|
#include "ui_freqman.hpp"
|
scanner-enhanced-version
New ui_scanner, inspired on AlainD's (alain00091) PR: https://github.com/eried/portapack-mayhem/pull/80
It includes the following:
1) A big frequency numbers display.
2) A Manual scan section (you can input a frequency range (START / END), choose a STEP value from an available of standard frequency intervals, and press SCAN button.
3) An AM / WFM / NFM scan mode selector, changing "on the fly".
4) A PAUSE / RESUME button, which will make the scanner to stop upon you listening something of interest
5) AUDIO APP button, a quick shortcut into the analog audio visualizing / recording app, with the mode, frequency, amp, LNA, VGA settings already in tune with the scanner.
6) Two enums are added to freqman.hpp, reserved for compatibility with AlainD's proposed freqman's app and / or further enhancement. More on this topic:
ORIGINAL scanner just used one frequency step, when creating scanning frequency ranges, which was unacceptable. AlainD enhanced freqman in order to pass different steppings along with ranges. This seems an excellent idea, and I preserved that aspect on my current implementation of thisscanner, while adding those enums into the freqman just to keep the door open for AlainD's freqman in the future.
7) I did eliminate the extra blank spaces added by function to_string_short_freq() which created unnecessary spacing in every app where there is need for a SHORT string, from a frequency number. (SHORT!, no extra spaces!!)
8) I also maintained AlainD idea of capping the number of frequencies which are dynamically created for each range and stored inside a memory based db. While AlainD capped the number into 400 frequencies, I was able to up that value a bit more, into 500.
Cheers!
2020-07-20 15:43:24 -04:00
|
|
|
|
2017-05-18 06:06:11 -04:00
|
|
|
using namespace portapack;
|
2023-07-29 18:36:00 -04:00
|
|
|
namespace fs = std::filesystem;
|
2017-05-18 06:06:11 -04:00
|
|
|
|
|
|
|
namespace ui {
|
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
ScannerThread::ScannerThread(std::vector<rf::Frequency> frequency_list)
|
|
|
|
: frequency_list_{std::move(frequency_list)} {
|
|
|
|
_manual_search = false;
|
|
|
|
create_thread();
|
2022-12-26 17:18:30 -05:00
|
|
|
}
|
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
ScannerThread::ScannerThread(const scanner_range_t& frequency_range, size_t def_step_hz)
|
2023-05-18 16:16:05 -04:00
|
|
|
: frequency_range_(frequency_range), def_step_hz_(def_step_hz) {
|
|
|
|
_manual_search = true;
|
|
|
|
create_thread();
|
2018-04-19 15:50:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
ScannerThread::~ScannerThread() {
|
2023-05-18 16:16:05 -04:00
|
|
|
stop();
|
scanner-enhanced-version
New ui_scanner, inspired on AlainD's (alain00091) PR: https://github.com/eried/portapack-mayhem/pull/80
It includes the following:
1) A big frequency numbers display.
2) A Manual scan section (you can input a frequency range (START / END), choose a STEP value from an available of standard frequency intervals, and press SCAN button.
3) An AM / WFM / NFM scan mode selector, changing "on the fly".
4) A PAUSE / RESUME button, which will make the scanner to stop upon you listening something of interest
5) AUDIO APP button, a quick shortcut into the analog audio visualizing / recording app, with the mode, frequency, amp, LNA, VGA settings already in tune with the scanner.
6) Two enums are added to freqman.hpp, reserved for compatibility with AlainD's proposed freqman's app and / or further enhancement. More on this topic:
ORIGINAL scanner just used one frequency step, when creating scanning frequency ranges, which was unacceptable. AlainD enhanced freqman in order to pass different steppings along with ranges. This seems an excellent idea, and I preserved that aspect on my current implementation of thisscanner, while adding those enums into the freqman just to keep the door open for AlainD's freqman in the future.
7) I did eliminate the extra blank spaces added by function to_string_short_freq() which created unnecessary spacing in every app where there is need for a SHORT string, from a frequency number. (SHORT!, no extra spaces!!)
8) I also maintained AlainD idea of capping the number of frequencies which are dynamically created for each range and stored inside a memory based db. While AlainD capped the number into 400 frequencies, I was able to up that value a bit more, into 500.
Cheers!
2020-07-20 15:43:24 -04:00
|
|
|
}
|
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
void ScannerThread::create_thread() {
|
|
|
|
thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, ScannerThread::static_fn, this);
|
2022-12-26 17:18:30 -05:00
|
|
|
}
|
|
|
|
|
scanner-enhanced-version
New ui_scanner, inspired on AlainD's (alain00091) PR: https://github.com/eried/portapack-mayhem/pull/80
It includes the following:
1) A big frequency numbers display.
2) A Manual scan section (you can input a frequency range (START / END), choose a STEP value from an available of standard frequency intervals, and press SCAN button.
3) An AM / WFM / NFM scan mode selector, changing "on the fly".
4) A PAUSE / RESUME button, which will make the scanner to stop upon you listening something of interest
5) AUDIO APP button, a quick shortcut into the analog audio visualizing / recording app, with the mode, frequency, amp, LNA, VGA settings already in tune with the scanner.
6) Two enums are added to freqman.hpp, reserved for compatibility with AlainD's proposed freqman's app and / or further enhancement. More on this topic:
ORIGINAL scanner just used one frequency step, when creating scanning frequency ranges, which was unacceptable. AlainD enhanced freqman in order to pass different steppings along with ranges. This seems an excellent idea, and I preserved that aspect on my current implementation of thisscanner, while adding those enums into the freqman just to keep the door open for AlainD's freqman in the future.
7) I did eliminate the extra blank spaces added by function to_string_short_freq() which created unnecessary spacing in every app where there is need for a SHORT string, from a frequency number. (SHORT!, no extra spaces!!)
8) I also maintained AlainD idea of capping the number of frequencies which are dynamically created for each range and stored inside a memory based db. While AlainD capped the number into 400 frequencies, I was able to up that value a bit more, into 500.
Cheers!
2020-07-20 15:43:24 -04:00
|
|
|
void ScannerThread::stop() {
|
2023-05-18 16:16:05 -04:00
|
|
|
if (thread) {
|
|
|
|
chThdTerminate(thread);
|
|
|
|
chThdWait(thread);
|
|
|
|
thread = nullptr;
|
|
|
|
}
|
2018-04-19 15:50:32 -04:00
|
|
|
}
|
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
// Set by "userpause"
|
2018-04-19 15:50:32 -04:00
|
|
|
void ScannerThread::set_scanning(const bool v) {
|
2023-05-18 16:16:05 -04:00
|
|
|
_scanning = v;
|
2018-04-19 15:50:32 -04:00
|
|
|
}
|
|
|
|
|
scanner-enhanced-version
New ui_scanner, inspired on AlainD's (alain00091) PR: https://github.com/eried/portapack-mayhem/pull/80
It includes the following:
1) A big frequency numbers display.
2) A Manual scan section (you can input a frequency range (START / END), choose a STEP value from an available of standard frequency intervals, and press SCAN button.
3) An AM / WFM / NFM scan mode selector, changing "on the fly".
4) A PAUSE / RESUME button, which will make the scanner to stop upon you listening something of interest
5) AUDIO APP button, a quick shortcut into the analog audio visualizing / recording app, with the mode, frequency, amp, LNA, VGA settings already in tune with the scanner.
6) Two enums are added to freqman.hpp, reserved for compatibility with AlainD's proposed freqman's app and / or further enhancement. More on this topic:
ORIGINAL scanner just used one frequency step, when creating scanning frequency ranges, which was unacceptable. AlainD enhanced freqman in order to pass different steppings along with ranges. This seems an excellent idea, and I preserved that aspect on my current implementation of thisscanner, while adding those enums into the freqman just to keep the door open for AlainD's freqman in the future.
7) I did eliminate the extra blank spaces added by function to_string_short_freq() which created unnecessary spacing in every app where there is need for a SHORT string, from a frequency number. (SHORT!, no extra spaces!!)
8) I also maintained AlainD idea of capping the number of frequencies which are dynamically created for each range and stored inside a memory based db. While AlainD capped the number into 400 frequencies, I was able to up that value a bit more, into 500.
Cheers!
2020-07-20 15:43:24 -04:00
|
|
|
bool ScannerThread::is_scanning() {
|
2023-05-18 16:16:05 -04:00
|
|
|
return _scanning;
|
scanner-enhanced-version
New ui_scanner, inspired on AlainD's (alain00091) PR: https://github.com/eried/portapack-mayhem/pull/80
It includes the following:
1) A big frequency numbers display.
2) A Manual scan section (you can input a frequency range (START / END), choose a STEP value from an available of standard frequency intervals, and press SCAN button.
3) An AM / WFM / NFM scan mode selector, changing "on the fly".
4) A PAUSE / RESUME button, which will make the scanner to stop upon you listening something of interest
5) AUDIO APP button, a quick shortcut into the analog audio visualizing / recording app, with the mode, frequency, amp, LNA, VGA settings already in tune with the scanner.
6) Two enums are added to freqman.hpp, reserved for compatibility with AlainD's proposed freqman's app and / or further enhancement. More on this topic:
ORIGINAL scanner just used one frequency step, when creating scanning frequency ranges, which was unacceptable. AlainD enhanced freqman in order to pass different steppings along with ranges. This seems an excellent idea, and I preserved that aspect on my current implementation of thisscanner, while adding those enums into the freqman just to keep the door open for AlainD's freqman in the future.
7) I did eliminate the extra blank spaces added by function to_string_short_freq() which created unnecessary spacing in every app where there is need for a SHORT string, from a frequency number. (SHORT!, no extra spaces!!)
8) I also maintained AlainD idea of capping the number of frequencies which are dynamically created for each range and stored inside a memory based db. While AlainD capped the number into 400 frequencies, I was able to up that value a bit more, into 500.
Cheers!
2020-07-20 15:43:24 -04:00
|
|
|
}
|
|
|
|
|
2020-07-25 13:07:03 -04:00
|
|
|
void ScannerThread::set_freq_lock(const uint32_t v) {
|
2023-05-18 16:16:05 -04:00
|
|
|
_freq_lock = v;
|
2020-07-25 13:07:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t ScannerThread::is_freq_lock() {
|
2023-05-18 16:16:05 -04:00
|
|
|
return _freq_lock;
|
2020-07-25 13:07:03 -04:00
|
|
|
}
|
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
// Delete an entry from frequency list
|
|
|
|
// Caller must pause scan_thread AND can't delete a second one until this field is cleared
|
2023-05-18 11:01:39 -04:00
|
|
|
void ScannerThread::set_freq_del(const rf::Frequency v) {
|
2023-05-18 16:16:05 -04:00
|
|
|
_freq_del = v;
|
2020-07-28 00:21:52 -04:00
|
|
|
}
|
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
// Force a one-time forward or reverse frequency index change; OK to do this without pausing scan thread
|
2023-07-29 18:36:00 -04:00
|
|
|
// (used when rotary encoder is turned)
|
2023-05-18 11:01:39 -04:00
|
|
|
void ScannerThread::set_index_stepper(const int32_t v) {
|
2023-05-18 16:16:05 -04:00
|
|
|
_index_stepper = v;
|
2023-05-18 11:01:39 -04:00
|
|
|
}
|
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
// Set scanning direction; OK to do this without pausing scan_thread
|
2023-05-18 11:01:39 -04:00
|
|
|
void ScannerThread::set_scanning_direction(bool fwd) {
|
2023-05-18 16:16:05 -04:00
|
|
|
int32_t new_stepper = fwd ? 1 : -1;
|
2020-07-28 20:05:10 -04:00
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
if (_stepper != new_stepper) {
|
|
|
|
_stepper = new_stepper;
|
|
|
|
chThdSleepMilliseconds(300); // Give some pause after reversing scanning direction
|
|
|
|
}
|
2020-07-28 20:05:10 -04:00
|
|
|
}
|
|
|
|
|
2018-04-19 15:50:32 -04:00
|
|
|
msg_t ScannerThread::static_fn(void* arg) {
|
2023-05-18 16:16:05 -04:00
|
|
|
auto obj = static_cast<ScannerThread*>(arg);
|
|
|
|
obj->run();
|
|
|
|
return 0;
|
2018-04-19 15:50:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScannerThread::run() {
|
2023-05-18 16:16:05 -04:00
|
|
|
RetuneMessage message{};
|
|
|
|
|
|
|
|
if (!_manual_search && frequency_list_.size()) { // IF NOT MANUAL MODE AND THERE IS A FREQUENCY LIST ...
|
|
|
|
int32_t size = frequency_list_.size();
|
|
|
|
int32_t frequency_index = (_stepper > 0) ? size : 0; // Forcing wraparound to starting frequency on 1st pass
|
|
|
|
|
|
|
|
while (!chThdShouldTerminate()) {
|
|
|
|
bool force_one_step = (_index_stepper != 0);
|
|
|
|
int32_t step = force_one_step ? _index_stepper : _stepper; //_index_stepper direction takes priority
|
|
|
|
|
|
|
|
if (_scanning || force_one_step) { // Scanning, or paused and using rotary encoder
|
|
|
|
if ((_freq_lock == 0) || force_one_step) { // normal scanning (not performing freq_lock)
|
|
|
|
frequency_index += step;
|
|
|
|
if (frequency_index >= size) // Wrap
|
|
|
|
frequency_index = 0;
|
|
|
|
else if (frequency_index < 0)
|
|
|
|
frequency_index = size - 1;
|
|
|
|
|
|
|
|
if (force_one_step)
|
|
|
|
_index_stepper = 0;
|
|
|
|
|
2023-06-11 14:47:13 -04:00
|
|
|
receiver_model.set_target_frequency(frequency_list_[frequency_index]); // Retune
|
2023-05-18 16:16:05 -04:00
|
|
|
}
|
|
|
|
message.freq = frequency_list_[frequency_index];
|
|
|
|
message.range = frequency_index; // Inform freq (for coloring purposes also!)
|
|
|
|
EventDispatcher::send_message(message);
|
|
|
|
} else if (_freq_del != 0) { // There is a frequency to delete
|
|
|
|
for (int32_t i = 0; i < size; i++) { // Search for the freq to delete
|
|
|
|
if (frequency_list_[i] == _freq_del) { // found: Erase it
|
|
|
|
frequency_list_.erase(frequency_list_.begin() + i);
|
|
|
|
size = frequency_list_.size();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_freq_del = 0; // deleted.
|
|
|
|
}
|
|
|
|
|
|
|
|
chThdSleepMilliseconds(SCANNER_SLEEP_MS); // Needed to (eventually) stabilize the receiver into new freq
|
|
|
|
}
|
|
|
|
} else if (_manual_search && (def_step_hz_ > 0)) // manual search range mode
|
|
|
|
{
|
|
|
|
int64_t size = (frequency_range_.max - frequency_range_.min) / def_step_hz_;
|
|
|
|
int64_t frequency_index = (_stepper > 0) ? size : 0; // Forcing wraparound to starting frequency on 1st pass
|
|
|
|
|
|
|
|
while (!chThdShouldTerminate()) {
|
|
|
|
bool force_one_step = (_index_stepper != 0);
|
|
|
|
int32_t step = force_one_step ? _index_stepper : _stepper; //_index_stepper direction takes priority
|
|
|
|
|
|
|
|
if (_scanning || force_one_step) { // Scanning, or paused and using rotary encoder
|
|
|
|
if ((_freq_lock == 0) || force_one_step) { // normal scanning (not performing freq_lock)
|
|
|
|
frequency_index += step;
|
|
|
|
if (frequency_index >= size) // Wrap
|
|
|
|
frequency_index = 0;
|
|
|
|
else if (frequency_index < 0)
|
|
|
|
frequency_index = size - 1;
|
|
|
|
|
|
|
|
if (force_one_step)
|
|
|
|
_index_stepper = 0;
|
|
|
|
|
2023-06-11 14:47:13 -04:00
|
|
|
receiver_model.set_target_frequency(frequency_range_.min + frequency_index * def_step_hz_); // Retune
|
2023-05-18 16:16:05 -04:00
|
|
|
}
|
|
|
|
message.freq = frequency_range_.min + frequency_index * def_step_hz_;
|
|
|
|
message.range = 0; // Inform freq (for coloring purposes also!)
|
|
|
|
EventDispatcher::send_message(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
chThdSleepMilliseconds(SCANNER_SLEEP_MS); // Needed to (eventually) stabilize the receiver into new freq
|
|
|
|
}
|
|
|
|
}
|
2018-04-19 15:50:32 -04:00
|
|
|
}
|
|
|
|
|
2023-05-18 11:01:39 -04:00
|
|
|
void ScannerView::bigdisplay_update(int32_t v) {
|
2023-05-18 16:16:05 -04:00
|
|
|
if (v != bigdisplay_current_color) {
|
|
|
|
if (v != -1)
|
|
|
|
bigdisplay_current_color = v; // -1 means refresh display but keep current color
|
|
|
|
|
|
|
|
switch (bigdisplay_current_color) {
|
|
|
|
case BDC_GREY:
|
2023-06-07 11:33:32 -04:00
|
|
|
big_display.set_style(&Styles::grey);
|
2023-05-18 16:16:05 -04:00
|
|
|
break;
|
|
|
|
case BDC_YELLOW:
|
2023-06-07 11:33:32 -04:00
|
|
|
big_display.set_style(&Styles::yellow);
|
2023-05-18 16:16:05 -04:00
|
|
|
break;
|
|
|
|
case BDC_GREEN:
|
2023-06-07 11:33:32 -04:00
|
|
|
big_display.set_style(&Styles::green);
|
2023-05-18 16:16:05 -04:00
|
|
|
break;
|
|
|
|
case BDC_RED:
|
2023-06-07 11:33:32 -04:00
|
|
|
big_display.set_style(&Styles::red);
|
2023-05-18 16:16:05 -04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// update frequency display
|
|
|
|
bigdisplay_current_frequency = current_frequency;
|
|
|
|
big_display.set(bigdisplay_current_frequency);
|
|
|
|
} else {
|
|
|
|
// no style change, but update frequency display if it's changed
|
|
|
|
if (current_frequency != bigdisplay_current_frequency) {
|
|
|
|
bigdisplay_current_frequency = current_frequency;
|
|
|
|
big_display.set(bigdisplay_current_frequency);
|
|
|
|
}
|
|
|
|
}
|
2023-05-18 11:01:39 -04:00
|
|
|
}
|
2022-12-26 17:18:30 -05:00
|
|
|
|
2023-05-18 11:01:39 -04:00
|
|
|
void ScannerView::handle_retune(int64_t freq, uint32_t freq_idx) {
|
2023-05-18 16:16:05 -04:00
|
|
|
current_index = freq_idx; // since it is an ongoing scan, this is a new index
|
|
|
|
current_frequency = freq;
|
|
|
|
|
|
|
|
if (scan_thread) {
|
|
|
|
switch (scan_thread->is_freq_lock()) {
|
|
|
|
case 0: // NO FREQ LOCK, ONGOING STANDARD SCANNING
|
|
|
|
bigdisplay_update(BDC_GREY);
|
|
|
|
break;
|
|
|
|
case 1: // STARTING LOCK FREQ
|
|
|
|
bigdisplay_update(BDC_YELLOW);
|
|
|
|
break;
|
|
|
|
case MAX_FREQ_LOCK: // FREQ IS STRONG: GREEN and scanner will pause when on_statistics_update()
|
|
|
|
bigdisplay_update(BDC_GREEN);
|
|
|
|
break;
|
|
|
|
default: // freq lock is checking the signal, do not update display
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!manual_search) {
|
2023-07-29 18:36:00 -04:00
|
|
|
if (entries.size() > 0)
|
2023-08-23 14:51:28 -04:00
|
|
|
field_current_index.set_text(to_string_dec_uint(freq_idx + 1, 3));
|
2023-05-18 16:16:05 -04:00
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
if (freq_idx < entries.size() && entries[freq_idx].description.size() > 1)
|
|
|
|
text_current_desc.set(entries[freq_idx].description); // Show description from file
|
2023-05-18 16:16:05 -04:00
|
|
|
else
|
2023-07-29 18:36:00 -04:00
|
|
|
text_current_desc.set(loaded_filename()); // Show Scan file name (no description in file)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-23 14:51:28 -04:00
|
|
|
void ScannerView::handle_encoder(EncoderEvent delta) {
|
|
|
|
auto index_step = delta > 0 ? 1 : -1;
|
|
|
|
|
|
|
|
if (scan_thread)
|
|
|
|
scan_thread->set_index_stepper(index_step);
|
|
|
|
|
|
|
|
// Restart browse timer when frequency changes.
|
|
|
|
if (browse_timer != 0)
|
|
|
|
browse_timer = 1;
|
|
|
|
}
|
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
std::string ScannerView::loaded_filename() const {
|
2023-08-23 14:51:28 -04:00
|
|
|
auto filename = freqman_file;
|
|
|
|
if (filename.length() > 23) { // Truncate long file name.
|
2023-07-29 18:36:00 -04:00
|
|
|
filename.resize(22);
|
|
|
|
filename = filename + "+";
|
2023-05-18 16:16:05 -04:00
|
|
|
}
|
2023-07-29 18:36:00 -04:00
|
|
|
|
|
|
|
return filename;
|
2018-04-19 15:50:32 -04:00
|
|
|
}
|
|
|
|
|
2017-05-18 06:06:11 -04:00
|
|
|
void ScannerView::focus() {
|
2023-06-18 02:14:29 -04:00
|
|
|
button_load.focus();
|
2017-05-18 06:06:11 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
ScannerView::~ScannerView() {
|
2023-05-18 16:16:05 -04:00
|
|
|
// make sure to stop the thread before shutting down the receiver
|
|
|
|
scan_thread.reset();
|
|
|
|
audio::output::stop();
|
|
|
|
receiver_model.disable();
|
|
|
|
baseband::shutdown();
|
2017-05-18 06:06:11 -04:00
|
|
|
}
|
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
void ScannerView::show_max_index() { // show total number of freqs to scan
|
2023-08-23 14:51:28 -04:00
|
|
|
field_current_index.set_text("---");
|
2023-05-18 16:16:05 -04:00
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
if (entries.size() == FREQMAN_MAX_PER_FILE) {
|
2023-06-07 11:33:32 -04:00
|
|
|
text_max_index.set_style(&Styles::red);
|
2023-05-18 16:16:05 -04:00
|
|
|
text_max_index.set("/ " + to_string_dec_uint(FREQMAN_MAX_PER_FILE) + " (DB MAX!)");
|
|
|
|
} else {
|
2023-06-07 11:33:32 -04:00
|
|
|
text_max_index.set_style(&Styles::grey);
|
2023-07-29 18:36:00 -04:00
|
|
|
text_max_index.set("/ " + to_string_dec_uint(entries.size()));
|
2023-05-18 16:16:05 -04:00
|
|
|
}
|
scanner-enhanced-version
New ui_scanner, inspired on AlainD's (alain00091) PR: https://github.com/eried/portapack-mayhem/pull/80
It includes the following:
1) A big frequency numbers display.
2) A Manual scan section (you can input a frequency range (START / END), choose a STEP value from an available of standard frequency intervals, and press SCAN button.
3) An AM / WFM / NFM scan mode selector, changing "on the fly".
4) A PAUSE / RESUME button, which will make the scanner to stop upon you listening something of interest
5) AUDIO APP button, a quick shortcut into the analog audio visualizing / recording app, with the mode, frequency, amp, LNA, VGA settings already in tune with the scanner.
6) Two enums are added to freqman.hpp, reserved for compatibility with AlainD's proposed freqman's app and / or further enhancement. More on this topic:
ORIGINAL scanner just used one frequency step, when creating scanning frequency ranges, which was unacceptable. AlainD enhanced freqman in order to pass different steppings along with ranges. This seems an excellent idea, and I preserved that aspect on my current implementation of thisscanner, while adding those enums into the freqman just to keep the door open for AlainD's freqman in the future.
7) I did eliminate the extra blank spaces added by function to_string_short_freq() which created unnecessary spacing in every app where there is need for a SHORT string, from a frequency number. (SHORT!, no extra spaces!!)
8) I also maintained AlainD idea of capping the number of frequencies which are dynamically created for each range and stored inside a memory based db. While AlainD capped the number into 400 frequencies, I was able to up that value a bit more, into 500.
Cheers!
2020-07-20 15:43:24 -04:00
|
|
|
}
|
|
|
|
|
2017-05-18 06:06:11 -04:00
|
|
|
ScannerView::ScannerView(
|
2023-05-18 16:16:05 -04:00
|
|
|
NavigationView& nav)
|
2023-07-29 18:36:00 -04:00
|
|
|
: nav_{nav} {
|
|
|
|
add_children({
|
|
|
|
&labels,
|
|
|
|
&field_lna,
|
|
|
|
&field_vga,
|
|
|
|
&field_rf_amp,
|
|
|
|
&field_volume,
|
|
|
|
&field_bw,
|
|
|
|
&field_squelch,
|
|
|
|
&field_browse_wait,
|
|
|
|
&field_lock_wait,
|
|
|
|
&button_load,
|
|
|
|
&button_clear,
|
|
|
|
&rssi,
|
2023-08-23 14:51:28 -04:00
|
|
|
&field_current_index,
|
2023-07-29 18:36:00 -04:00
|
|
|
&text_max_index,
|
|
|
|
&text_current_desc,
|
|
|
|
&big_display,
|
|
|
|
&button_manual_start,
|
|
|
|
&button_manual_end,
|
|
|
|
&field_mode,
|
|
|
|
&field_step,
|
|
|
|
&button_manual_search,
|
|
|
|
&button_pause,
|
|
|
|
&button_dir,
|
|
|
|
&button_audio_app,
|
|
|
|
&button_mic_app,
|
|
|
|
&button_add,
|
|
|
|
&button_remove,
|
2023-05-18 16:16:05 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
// Populate option text for these fields
|
|
|
|
freqman_set_modulation_option(field_mode);
|
|
|
|
freqman_set_step_option(field_step);
|
|
|
|
|
2023-06-14 10:54:19 -04:00
|
|
|
// Default starting modulation (from saved App Settings if enabled, and may be overridden in SCANNER.TXT)
|
|
|
|
field_mode.set_by_value((OptionsField::value_t)receiver_model.modulation()); // Reflect the mode into the manual selector
|
|
|
|
field_step.set_by_value(receiver_model.frequency_step()); // Default step interval (Hz)
|
|
|
|
change_mode((freqman_index_t)field_mode.selected_index_value());
|
2023-05-18 16:16:05 -04:00
|
|
|
|
|
|
|
button_manual_start.set_text(to_string_short_freq(frequency_range.min));
|
|
|
|
button_manual_end.set_text(to_string_short_freq(frequency_range.max));
|
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
// Button to load a Freqman file.
|
2023-05-18 16:16:05 -04:00
|
|
|
button_load.on_select = [this, &nav](Button&) {
|
|
|
|
auto open_view = nav.push<FileLoadView>(".TXT");
|
2023-07-11 16:48:36 -04:00
|
|
|
open_view->push_dir(freqman_dir);
|
|
|
|
open_view->on_changed = [this, &nav](std::filesystem::path new_file_path) {
|
|
|
|
if (new_file_path.native().find(freqman_dir.native()) == 0) {
|
2023-05-18 16:16:05 -04:00
|
|
|
scan_pause();
|
2023-07-29 18:36:00 -04:00
|
|
|
frequency_file_load(new_file_path);
|
2023-05-18 16:16:05 -04:00
|
|
|
} else {
|
2023-07-11 16:48:36 -04:00
|
|
|
nav.display_modal("LOAD ERROR", "A valid file from\nFREQMAN directory is\nrequired.");
|
2023-05-18 16:16:05 -04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2023-08-23 14:51:28 -04:00
|
|
|
// Button to clear in-memory frequency list.
|
2023-05-18 16:16:05 -04:00
|
|
|
button_clear.on_select = [this, &nav](Button&) {
|
2023-07-29 18:36:00 -04:00
|
|
|
if (scan_thread && entries.size()) {
|
2023-05-18 16:16:05 -04:00
|
|
|
scan_thread->stop(); // STOP SCANNER THREAD
|
2023-07-29 18:36:00 -04:00
|
|
|
entries.clear();
|
2023-05-18 16:16:05 -04:00
|
|
|
|
|
|
|
show_max_index(); // UPDATE new list size on screen
|
2023-08-23 14:51:28 -04:00
|
|
|
field_current_index.set_text("");
|
2023-07-29 18:36:00 -04:00
|
|
|
text_current_desc.set(loaded_filename());
|
2023-05-18 16:16:05 -04:00
|
|
|
scan_thread->set_freq_lock(0); // Reset the scanner lock
|
|
|
|
|
|
|
|
// FUTURE: Consider switching to manual search mode automatically after clear (but would need to validate freq range)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-08-23 14:51:28 -04:00
|
|
|
// Button to configure starting frequency for a manual range search.
|
2023-05-18 16:16:05 -04:00
|
|
|
button_manual_start.on_select = [this, &nav](Button& button) {
|
|
|
|
auto new_view = nav_.push<FrequencyKeypadView>(frequency_range.min);
|
|
|
|
new_view->on_changed = [this, &button](rf::Frequency f) {
|
|
|
|
frequency_range.min = f;
|
|
|
|
button_manual_start.set_text(to_string_short_freq(f));
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2023-08-23 14:51:28 -04:00
|
|
|
// Button to configure ending frequency for a manual range search.
|
2023-05-18 16:16:05 -04:00
|
|
|
button_manual_end.on_select = [this, &nav](Button& button) {
|
|
|
|
auto new_view = nav.push<FrequencyKeypadView>(frequency_range.max);
|
|
|
|
new_view->on_changed = [this, &button](rf::Frequency f) {
|
|
|
|
frequency_range.max = f;
|
|
|
|
button_manual_end.set_text(to_string_short_freq(f));
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2023-08-23 14:51:28 -04:00
|
|
|
// Button to pause/resume scan (note that some other buttons will trigger resume also).
|
2023-05-18 16:16:05 -04:00
|
|
|
button_pause.on_select = [this](ButtonWithEncoder&) {
|
|
|
|
if (userpause)
|
|
|
|
user_resume();
|
|
|
|
else {
|
|
|
|
scan_pause();
|
|
|
|
button_pause.set_text("<RESUME>"); // PAUSED, show resume
|
|
|
|
userpause = true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-08-23 14:51:28 -04:00
|
|
|
// Encoder dial causes frequency change when focus is on pause button or current index.
|
2023-05-18 16:16:05 -04:00
|
|
|
button_pause.on_change = [this]() {
|
2023-08-23 14:51:28 -04:00
|
|
|
handle_encoder(button_pause.get_encoder_delta());
|
2023-05-18 16:16:05 -04:00
|
|
|
button_pause.set_encoder_delta(0);
|
|
|
|
};
|
2023-08-23 14:51:28 -04:00
|
|
|
field_current_index.on_encoder_change = [this](TextField&, EncoderEvent delta) {
|
|
|
|
handle_encoder(delta);
|
|
|
|
};
|
2023-05-18 16:16:05 -04:00
|
|
|
|
|
|
|
// Button to switch to Audio app
|
|
|
|
button_audio_app.on_select = [this](Button&) {
|
|
|
|
if (scan_thread)
|
|
|
|
scan_thread->stop();
|
2023-07-04 19:26:26 -04:00
|
|
|
auto settings = receiver_model.settings();
|
|
|
|
settings.frequency_step = field_step.selected_index_value();
|
|
|
|
nav_.replace<AnalogAudioView>(settings);
|
2023-05-18 16:16:05 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
// Button to switch to Mic app
|
|
|
|
button_mic_app.on_select = [this](Button&) {
|
|
|
|
if (scan_thread)
|
|
|
|
scan_thread->stop();
|
2023-07-04 19:26:26 -04:00
|
|
|
// MicTX wants Modulation and Bandwidth overrides, but that's only stored on the RX model.
|
|
|
|
nav_.replace<MicTXView>(receiver_model.settings());
|
2023-05-18 16:16:05 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
// Button to delete current frequency from scan Freq List
|
|
|
|
button_remove.on_select = [this](Button&) {
|
2023-07-29 18:36:00 -04:00
|
|
|
if (scan_thread && (entries.size() > current_index)) {
|
2023-05-18 16:16:05 -04:00
|
|
|
scan_thread->set_scanning(false); // PAUSE Scanning if necessary
|
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
// Remove frequency from the Freq List in memory (it is not removed from the file).
|
|
|
|
scan_thread->set_freq_del(entries[current_index].freq);
|
|
|
|
entries.erase(entries.begin() + current_index);
|
2023-05-18 16:16:05 -04:00
|
|
|
|
|
|
|
show_max_index(); // UPDATE new list size on screen
|
2023-07-29 18:36:00 -04:00
|
|
|
text_current_desc.set(""); // Clean up description (cosmetic detail)
|
2023-05-18 16:16:05 -04:00
|
|
|
scan_thread->set_freq_lock(0); // Reset the scanner lock
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Button to toggle between Manual Search and Freq List Scan modes
|
|
|
|
button_manual_search.on_select = [this](Button&) {
|
|
|
|
if (!manual_search) {
|
|
|
|
if (!frequency_range.min || !frequency_range.max) {
|
|
|
|
nav_.display_modal("Error", "Both START and END freqs\nneed a value");
|
|
|
|
} else if (frequency_range.min > frequency_range.max) {
|
|
|
|
nav_.display_modal("Error", "END freq\nis lower than START");
|
|
|
|
} else {
|
|
|
|
manual_search = true; // Switch to Manual Search mode
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
manual_search = false; // Switch to List Scan mode
|
|
|
|
}
|
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
restart_scan();
|
2023-05-18 16:16:05 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
// Mode field was changed (AM/NFM/WFM)
|
|
|
|
field_mode.on_change = [this](size_t, OptionsField::value_t v) {
|
2023-06-25 02:16:49 -04:00
|
|
|
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;
|
2023-05-18 16:16:05 -04:00
|
|
|
receiver_model.disable();
|
|
|
|
baseband::shutdown();
|
|
|
|
change_mode((freqman_index_t)v);
|
|
|
|
if (scan_thread && !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();
|
|
|
|
};
|
|
|
|
|
|
|
|
// Step field was changed (Hz) -- only affects manual Search mode
|
|
|
|
field_step.on_change = [this](size_t, OptionsField::value_t v) {
|
2023-06-14 10:54:19 -04:00
|
|
|
receiver_model.set_frequency_step(v);
|
2023-05-18 16:16:05 -04:00
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
if (manual_search && scan_thread)
|
|
|
|
restart_scan();
|
2023-05-18 16:16:05 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
// Button to toggle Forward/Reverse
|
|
|
|
button_dir.on_select = [this](Button&) {
|
|
|
|
fwd = !fwd;
|
|
|
|
if (scan_thread)
|
|
|
|
scan_thread->set_scanning_direction(fwd);
|
|
|
|
if (userpause) // If user-paused, resume
|
|
|
|
user_resume();
|
|
|
|
button_dir.set_text(fwd ? "REVERSE" : "FORWARD");
|
|
|
|
bigdisplay_update(BDC_GREY); // Back to grey color
|
|
|
|
};
|
|
|
|
|
|
|
|
// Button to add current frequency (found during Search) to the Scan Frequency List
|
|
|
|
button_add.on_select = [this](Button&) {
|
2023-07-29 18:36:00 -04:00
|
|
|
FreqmanDB db;
|
2023-08-23 14:51:28 -04:00
|
|
|
if (db.open(get_freqman_path(freqman_file), /*create*/ true)) {
|
2023-07-29 18:36:00 -04:00
|
|
|
freqman_entry entry{
|
|
|
|
.frequency_a = current_frequency,
|
|
|
|
.type = freqman_type::Single,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Look for existing entry with same frequency.
|
|
|
|
auto it = db.find_entry([&entry](const auto& e) {
|
|
|
|
return e.frequency_a == entry.frequency_a;
|
|
|
|
});
|
|
|
|
auto found = (it != db.end());
|
2023-05-18 16:16:05 -04:00
|
|
|
|
|
|
|
if (found) {
|
|
|
|
nav_.display_modal("Error", "Frequency already exists");
|
2023-07-29 18:36:00 -04:00
|
|
|
bigdisplay_update(-1); // Need to poke this control after displaying modal?
|
2023-05-18 16:16:05 -04:00
|
|
|
} else {
|
2023-07-29 18:36:00 -04:00
|
|
|
db.append_entry(entry);
|
2023-05-18 16:16:05 -04:00
|
|
|
// Add to frequency_list in memory too, since we can now switch back from manual mode
|
2023-07-29 18:36:00 -04:00
|
|
|
// Note that we are allowing freqs to be added to file (code above) that exceed the
|
|
|
|
// max count we can load into memory.
|
|
|
|
if (entries.size() < FREQMAN_MAX_PER_FILE) {
|
|
|
|
entries.push_back({current_frequency, ""});
|
2023-05-18 16:16:05 -04:00
|
|
|
show_max_index(); // Display updated frequency list size
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2023-08-23 14:51:28 -04:00
|
|
|
nav_.display_modal("Error", "Cannot open " + freqman_file + ".TXT\nfor appending freq.");
|
2023-07-29 18:36:00 -04:00
|
|
|
bigdisplay_update(-1); // Need to poke this control after displaying modal?
|
2023-05-18 16:16:05 -04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// PRE-CONFIGURATION:
|
|
|
|
field_browse_wait.on_change = [this](int32_t v) { browse_wait = v; };
|
2023-08-20 16:28:02 -04:00
|
|
|
field_browse_wait.set_value(browse_wait);
|
2023-05-18 16:16:05 -04:00
|
|
|
|
|
|
|
field_lock_wait.on_change = [this](int32_t v) { lock_wait = v; };
|
2023-08-20 16:28:02 -04:00
|
|
|
field_lock_wait.set_value(lock_wait);
|
2023-05-18 16:16:05 -04:00
|
|
|
|
|
|
|
field_squelch.on_change = [this](int32_t v) { squelch = v; };
|
2023-08-20 16:28:02 -04:00
|
|
|
field_squelch.set_value(squelch);
|
|
|
|
|
|
|
|
// Disable squelch on the model because RSSI handler is where the
|
|
|
|
// actual squelching is applied for this app.
|
|
|
|
receiver_model.set_squelch_level(0);
|
2023-05-18 16:16:05 -04:00
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
// LOAD FREQUENCIES
|
2023-08-23 14:51:28 -04:00
|
|
|
frequency_file_load(get_freqman_path(freqman_file));
|
2020-09-11 15:11:42 -04:00
|
|
|
}
|
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
void ScannerView::frequency_file_load(const fs::path& path) {
|
2023-07-08 16:04:12 -04:00
|
|
|
freqman_index_t def_mod_index{freqman_invalid_index};
|
|
|
|
freqman_index_t def_bw_index{freqman_invalid_index};
|
|
|
|
freqman_index_t def_step_index{freqman_invalid_index};
|
2023-05-18 16:16:05 -04:00
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
FreqmanDB db;
|
|
|
|
if (!db.open(path)) {
|
|
|
|
text_current_desc.set("NO " + path.filename().string());
|
|
|
|
return;
|
2023-05-18 16:16:05 -04:00
|
|
|
}
|
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
entries.clear();
|
2023-08-23 14:51:28 -04:00
|
|
|
freqman_file = path.stem().string();
|
2023-07-29 18:36:00 -04:00
|
|
|
Optional<scanner_range_t> range;
|
2023-07-08 16:04:12 -04:00
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
for (auto entry : db) {
|
|
|
|
if (is_invalid(def_mod_index))
|
|
|
|
def_mod_index = entry.modulation;
|
|
|
|
|
|
|
|
if (is_invalid(def_bw_index))
|
|
|
|
def_bw_index = entry.bandwidth;
|
|
|
|
|
|
|
|
if (is_invalid(def_step_index))
|
|
|
|
def_step_index = entry.step;
|
|
|
|
|
|
|
|
switch (entry.type) {
|
2023-12-28 05:25:53 -05:00
|
|
|
case freqman_type::Repeater:
|
2023-07-29 18:36:00 -04:00
|
|
|
case freqman_type::Single:
|
|
|
|
entries.push_back({entry.frequency_a, entry.description});
|
|
|
|
break;
|
|
|
|
case freqman_type::HamRadio:
|
|
|
|
entries.push_back({entry.frequency_a, "R: " + entry.description});
|
|
|
|
entries.push_back({entry.frequency_b, "T: " + entry.description});
|
|
|
|
break;
|
|
|
|
case freqman_type::Range:
|
|
|
|
// NB: Only the first range will be loaded.
|
|
|
|
if (!range)
|
|
|
|
range = {entry.frequency_a, entry.frequency_b};
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2023-05-18 16:16:05 -04:00
|
|
|
}
|
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
if (entries.size() >= FREQMAN_MAX_PER_FILE)
|
|
|
|
break;
|
2023-05-18 16:16:05 -04:00
|
|
|
}
|
|
|
|
|
2023-07-08 16:04:12 -04:00
|
|
|
if (is_valid(def_mod_index) && def_mod_index != (freqman_index_t)field_mode.selected_index_value())
|
2023-07-29 18:36:00 -04:00
|
|
|
field_mode.set_by_value(def_mod_index);
|
2023-05-18 16:16:05 -04:00
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
if (is_valid(def_bw_index))
|
2023-05-18 16:16:05 -04:00
|
|
|
field_bw.set_selected_index(def_bw_index);
|
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
if (is_valid(def_step_index))
|
2023-05-18 16:16:05 -04:00
|
|
|
field_step.set_selected_index(def_step_index);
|
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
// Found range, set it and update UI.
|
|
|
|
if (range) {
|
|
|
|
frequency_range = *range;
|
|
|
|
button_manual_start.set_text(to_string_short_freq(frequency_range.min));
|
|
|
|
button_manual_end.set_text(to_string_short_freq(frequency_range.max));
|
|
|
|
}
|
2023-05-18 16:16:05 -04:00
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
// Scan entries if any, otherwise do manual range search.
|
|
|
|
manual_search = entries.empty();
|
|
|
|
restart_scan();
|
2018-04-19 15:50:32 -04:00
|
|
|
}
|
|
|
|
|
2023-05-18 11:01:39 -04:00
|
|
|
void ScannerView::update_squelch_while_paused(int32_t max_db) {
|
2023-05-18 16:16:05 -04:00
|
|
|
// Update audio & color based on signal level even if paused
|
|
|
|
if (++color_timer > 2) { // Counter to reduce color toggling when weak signal
|
|
|
|
if (max_db > squelch) {
|
2023-06-04 15:56:46 -04:00
|
|
|
audio::output::start(); // Re-enable audio when signal goes above squelch
|
|
|
|
receiver_model.set_headphone_volume(receiver_model.headphone_volume()); // quick fix to make sure WM8731S chips don't stay silent after pause
|
2023-05-18 16:16:05 -04:00
|
|
|
bigdisplay_update(BDC_GREEN);
|
|
|
|
} else {
|
|
|
|
audio::output::stop(); // Silence audio when signal drops below squelch
|
|
|
|
bigdisplay_update(BDC_GREY); // Back to grey color
|
|
|
|
}
|
|
|
|
|
|
|
|
color_timer = 0;
|
|
|
|
}
|
2023-05-18 11:01:39 -04:00
|
|
|
}
|
|
|
|
|
2018-04-19 15:50:32 -04:00
|
|
|
void ScannerView::on_statistics_update(const ChannelStatistics& statistics) {
|
2023-05-18 16:16:05 -04:00
|
|
|
if (userpause) {
|
|
|
|
update_squelch_while_paused(statistics.max_db);
|
|
|
|
} else if (scan_thread) // Scanning not user-paused
|
|
|
|
{
|
|
|
|
// Resume regardless of signal strength if browse time reached
|
|
|
|
if ((browse_wait != 0) && (browse_timer >= (browse_wait * STATISTICS_UPDATES_PER_SEC))) {
|
|
|
|
browse_timer = 0;
|
|
|
|
scan_resume(); // Resume scanning
|
|
|
|
} else {
|
|
|
|
if (statistics.max_db > squelch) { // There is something on the air...(statistics.max_db > -squelch)
|
|
|
|
if (scan_thread->is_freq_lock() >= MAX_FREQ_LOCK) { // Pause scanning when signal checking time reached
|
|
|
|
if (!browse_timer) // Don't bother pausing if already paused
|
|
|
|
scan_pause();
|
|
|
|
browse_timer++; // browse_timer!=0 is also an indication that we've paused the scan
|
|
|
|
update_squelch_while_paused(statistics.max_db);
|
|
|
|
} else {
|
|
|
|
scan_thread->set_freq_lock(scan_thread->is_freq_lock() + 1); // in lock period, still analyzing the signal
|
|
|
|
if (browse_timer) // Continue incrementing browse timer while paused
|
|
|
|
browse_timer++;
|
|
|
|
}
|
|
|
|
lock_timer = 0; // Keep resetting lock timer while signal remains
|
|
|
|
} else { // There is NOTHING on the air
|
|
|
|
if (!browse_timer) {
|
|
|
|
// Signal lost and scan was never paused
|
|
|
|
if (scan_thread->is_freq_lock() > 0) { // But are we already in freq_lock ?
|
|
|
|
bigdisplay_update(BDC_GREY); // Back to grey color
|
|
|
|
scan_thread->set_freq_lock(0); // Reset the scanner lock, since there is no sig
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Signal lost and scan is still paused
|
|
|
|
lock_timer++; // Bump paused time
|
|
|
|
if (lock_timer >= (lock_wait * STATISTICS_UPDATES_PER_SEC)) { // Stay on freq until lock_wait time elapses
|
|
|
|
browse_timer = 0;
|
|
|
|
scan_resume();
|
|
|
|
} else {
|
|
|
|
browse_timer++; // Bump browse time too (may hit that limit before lock_timer reached)
|
|
|
|
update_squelch_while_paused(statistics.max_db);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
scanner-enhanced-version
New ui_scanner, inspired on AlainD's (alain00091) PR: https://github.com/eried/portapack-mayhem/pull/80
It includes the following:
1) A big frequency numbers display.
2) A Manual scan section (you can input a frequency range (START / END), choose a STEP value from an available of standard frequency intervals, and press SCAN button.
3) An AM / WFM / NFM scan mode selector, changing "on the fly".
4) A PAUSE / RESUME button, which will make the scanner to stop upon you listening something of interest
5) AUDIO APP button, a quick shortcut into the analog audio visualizing / recording app, with the mode, frequency, amp, LNA, VGA settings already in tune with the scanner.
6) Two enums are added to freqman.hpp, reserved for compatibility with AlainD's proposed freqman's app and / or further enhancement. More on this topic:
ORIGINAL scanner just used one frequency step, when creating scanning frequency ranges, which was unacceptable. AlainD enhanced freqman in order to pass different steppings along with ranges. This seems an excellent idea, and I preserved that aspect on my current implementation of thisscanner, while adding those enums into the freqman just to keep the door open for AlainD's freqman in the future.
7) I did eliminate the extra blank spaces added by function to_string_short_freq() which created unnecessary spacing in every app where there is need for a SHORT string, from a frequency number. (SHORT!, no extra spaces!!)
8) I also maintained AlainD idea of capping the number of frequencies which are dynamically created for each range and stored inside a memory based db. While AlainD capped the number into 400 frequencies, I was able to up that value a bit more, into 500.
Cheers!
2020-07-20 15:43:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScannerView::scan_pause() {
|
2023-05-18 16:16:05 -04:00
|
|
|
if (scan_thread && 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();
|
2023-06-04 15:56:46 -04:00
|
|
|
receiver_model.set_headphone_volume(receiver_model.headphone_volume()); // quick fix to make sure WM8731S chips don't stay silent after pause
|
scanner-enhanced-version
New ui_scanner, inspired on AlainD's (alain00091) PR: https://github.com/eried/portapack-mayhem/pull/80
It includes the following:
1) A big frequency numbers display.
2) A Manual scan section (you can input a frequency range (START / END), choose a STEP value from an available of standard frequency intervals, and press SCAN button.
3) An AM / WFM / NFM scan mode selector, changing "on the fly".
4) A PAUSE / RESUME button, which will make the scanner to stop upon you listening something of interest
5) AUDIO APP button, a quick shortcut into the analog audio visualizing / recording app, with the mode, frequency, amp, LNA, VGA settings already in tune with the scanner.
6) Two enums are added to freqman.hpp, reserved for compatibility with AlainD's proposed freqman's app and / or further enhancement. More on this topic:
ORIGINAL scanner just used one frequency step, when creating scanning frequency ranges, which was unacceptable. AlainD enhanced freqman in order to pass different steppings along with ranges. This seems an excellent idea, and I preserved that aspect on my current implementation of thisscanner, while adding those enums into the freqman just to keep the door open for AlainD's freqman in the future.
7) I did eliminate the extra blank spaces added by function to_string_short_freq() which created unnecessary spacing in every app where there is need for a SHORT string, from a frequency number. (SHORT!, no extra spaces!!)
8) I also maintained AlainD idea of capping the number of frequencies which are dynamically created for each range and stored inside a memory based db. While AlainD capped the number into 400 frequencies, I was able to up that value a bit more, into 500.
Cheers!
2020-07-20 15:43:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScannerView::scan_resume() {
|
2023-05-18 16:16:05 -04:00
|
|
|
audio::output::stop();
|
|
|
|
bigdisplay_update(BDC_GREY); // Back to grey color
|
2023-05-18 11:01:39 -04:00
|
|
|
|
2023-05-18 16:16:05 -04:00
|
|
|
if (scan_thread) {
|
|
|
|
scan_thread->set_index_stepper(fwd ? 1 : -1);
|
|
|
|
scan_thread->set_scanning(true); // RESUME!
|
|
|
|
}
|
2020-07-28 00:21:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScannerView::user_resume() {
|
2023-05-22 17:21:00 -04:00
|
|
|
browse_timer = browse_wait * STATISTICS_UPDATES_PER_SEC + 1; // Will trigger a scan_resume() on_statistics_update, also advancing to next freq.
|
|
|
|
button_pause.set_text("<PAUSE>"); // Show button for pause, arrows indicate rotary encoder enabled for freq change
|
|
|
|
userpause = false; // Resume scanning
|
2018-04-19 15:50:32 -04:00
|
|
|
}
|
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
// Before this, do a scan_thread->stop(); After this do a start_scan_thread()
|
|
|
|
void ScannerView::change_mode(freqman_index_t new_mod) {
|
2023-05-18 16:16:05 -04:00
|
|
|
using option_t = std::pair<std::string, int32_t>;
|
|
|
|
using options_t = std::vector<option_t>;
|
|
|
|
options_t bw;
|
|
|
|
field_bw.on_change = [this](size_t n, OptionsField::value_t) {
|
|
|
|
(void)n; // avoid unused warning
|
|
|
|
};
|
|
|
|
|
|
|
|
switch (new_mod) {
|
|
|
|
case AM_MODULATION:
|
|
|
|
freqman_set_bandwidth_option(new_mod, field_bw);
|
|
|
|
baseband::run_image(portapack::spi_flash::image_tag_am_audio);
|
|
|
|
receiver_model.set_modulation(ReceiverModel::Mode::AMAudio);
|
2023-06-14 10:54:19 -04:00
|
|
|
field_bw.set_by_value(receiver_model.am_configuration());
|
2023-06-06 12:46:08 -04:00
|
|
|
field_bw.on_change = [this](size_t, OptionsField::value_t n) { receiver_model.set_am_configuration(n); };
|
2023-05-18 16:16:05 -04:00
|
|
|
break;
|
2023-06-14 10:54:19 -04:00
|
|
|
case NFM_MODULATION:
|
2023-05-18 16:16:05 -04:00
|
|
|
freqman_set_bandwidth_option(new_mod, field_bw);
|
|
|
|
baseband::run_image(portapack::spi_flash::image_tag_nfm_audio);
|
|
|
|
receiver_model.set_modulation(ReceiverModel::Mode::NarrowbandFMAudio);
|
2023-06-14 10:54:19 -04:00
|
|
|
field_bw.set_by_value(receiver_model.nbfm_configuration());
|
2023-06-06 12:46:08 -04:00
|
|
|
field_bw.on_change = [this](size_t, OptionsField::value_t n) { receiver_model.set_nbfm_configuration(n); };
|
2023-05-18 16:16:05 -04:00
|
|
|
break;
|
|
|
|
case WFM_MODULATION:
|
|
|
|
freqman_set_bandwidth_option(new_mod, field_bw);
|
|
|
|
baseband::run_image(portapack::spi_flash::image_tag_wfm_audio);
|
|
|
|
receiver_model.set_modulation(ReceiverModel::Mode::WidebandFMAudio);
|
2023-06-14 10:54:19 -04:00
|
|
|
field_bw.set_by_value(receiver_model.wfm_configuration());
|
2023-06-06 12:46:08 -04:00
|
|
|
field_bw.on_change = [this](size_t, OptionsField::value_t n) { receiver_model.set_wfm_configuration(n); };
|
2023-05-18 16:16:05 -04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
scanner-enhanced-version
New ui_scanner, inspired on AlainD's (alain00091) PR: https://github.com/eried/portapack-mayhem/pull/80
It includes the following:
1) A big frequency numbers display.
2) A Manual scan section (you can input a frequency range (START / END), choose a STEP value from an available of standard frequency intervals, and press SCAN button.
3) An AM / WFM / NFM scan mode selector, changing "on the fly".
4) A PAUSE / RESUME button, which will make the scanner to stop upon you listening something of interest
5) AUDIO APP button, a quick shortcut into the analog audio visualizing / recording app, with the mode, frequency, amp, LNA, VGA settings already in tune with the scanner.
6) Two enums are added to freqman.hpp, reserved for compatibility with AlainD's proposed freqman's app and / or further enhancement. More on this topic:
ORIGINAL scanner just used one frequency step, when creating scanning frequency ranges, which was unacceptable. AlainD enhanced freqman in order to pass different steppings along with ranges. This seems an excellent idea, and I preserved that aspect on my current implementation of thisscanner, while adding those enums into the freqman just to keep the door open for AlainD's freqman in the future.
7) I did eliminate the extra blank spaces added by function to_string_short_freq() which created unnecessary spacing in every app where there is need for a SHORT string, from a frequency number. (SHORT!, no extra spaces!!)
8) I also maintained AlainD idea of capping the number of frequencies which are dynamically created for each range and stored inside a memory based db. While AlainD capped the number into 400 frequencies, I was able to up that value a bit more, into 500.
Cheers!
2020-07-20 15:43:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScannerView::start_scan_thread() {
|
2023-05-18 16:16:05 -04:00
|
|
|
receiver_model.enable();
|
|
|
|
show_max_index();
|
|
|
|
|
|
|
|
// Start Scanner Thread
|
|
|
|
if (manual_search) {
|
|
|
|
button_manual_search.set_text("SCAN"); // Update meaning of Manual Scan button
|
2023-07-29 18:36:00 -04:00
|
|
|
text_current_desc.set("SEARCHING...");
|
2023-05-18 16:16:05 -04:00
|
|
|
scan_thread = std::make_unique<ScannerThread>(frequency_range, field_step.selected_index_value());
|
|
|
|
} else {
|
|
|
|
button_manual_search.set_text("SRCH"); // Update meaning of Manual Scan button
|
2023-07-29 18:36:00 -04:00
|
|
|
text_current_desc.set(loaded_filename());
|
|
|
|
|
|
|
|
// TODO: just pass ref to the thread?
|
|
|
|
std::vector<rf::Frequency> frequency_list;
|
|
|
|
frequency_list.reserve(entries.size());
|
|
|
|
for (const auto& entry : entries)
|
|
|
|
frequency_list.push_back(entry.freq);
|
|
|
|
|
|
|
|
scan_thread = std::make_unique<ScannerThread>(std::move(frequency_list));
|
2023-05-18 16:16:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
scan_thread->set_scanning_direction(fwd);
|
2022-12-26 17:18:30 -05:00
|
|
|
}
|
|
|
|
|
2023-07-29 18:36:00 -04:00
|
|
|
void ScannerView::restart_scan() {
|
|
|
|
audio::output::stop();
|
|
|
|
if (scan_thread) // STOP SCANNER THREAD
|
|
|
|
scan_thread->stop();
|
|
|
|
|
|
|
|
if (userpause) // If user-paused, resume
|
|
|
|
user_resume();
|
|
|
|
|
|
|
|
start_scan_thread(); // RESTART SCANNER THREAD in selected mode
|
|
|
|
}
|
|
|
|
|
2021-01-27 11:03:20 -05:00
|
|
|
} /* namespace ui */
|