Compare commits

...

13 Commits

Author SHA1 Message Date
Mark Thompson d5c8525afc Declare all folder names in a single source file (#2039) 2024-03-25 08:44:49 +01:00
ImDroided d9bbd1b9ff SSTV Freqs (#2038)
* Added and fixed freqs

Figured I would clean these up and add a bit.

* Create SSTV.TXT

SSTV Frequencies for SSTV app
2024-03-25 01:21:05 -05:00
gullradriel b47cee435e fix typo (#2037) 2024-03-24 18:50:42 -05:00
gullradriel c078bac0e7 Looking glass beep (#2036)
* first draft of looking beep
* fixed beep squelch range in percent
* took out steps 
* gui adjustements
* uniformize calculation and beep squelch in db
* uniformisation, fix 24/48 error
2024-03-24 22:32:13 +01:00
gullradriel 6177b08632 fixing level beep, bad copy paste on special SPEC mode (#2035)
Co-authored-by: gullradriel <gullradriel@no-mail.com>
2024-03-24 18:47:15 +08:00
Mark Thompson 53a1bacd46 Revert "Add cmake dependency on baseband for external APPS" (#2034)
This reverts commit abb9b6c8ad.
2024-03-24 10:39:20 +08:00
ImDroided 4c012a9493 Added and fixed freqs (#2033)
Figured I would clean these up and add a bit.
2024-03-23 21:16:27 -05:00
Mark Thompson abb9b6c8ad Add make dependency on baseband for external APPS (#2031) 2024-03-23 21:34:15 +01:00
gullradriel 6e2507d609 fix gui glitch on beep squelch (#2030) 2024-03-23 21:01:48 +01:00
gullradriel 536981998b Level fix and beep, RSSI avg fix (#2027)
* fix average value being overflow'd
* fix audio and mod changes, preps for beep mode
* fixed beep_freq range, added a stop and set a variable sooner
* added support for audio beep messages
* better scaler for beep
* added bip squelch and saving of bip squelch and audio mode
* saving modulation, fixing audio
* added save and restore of bandwidth
* simpler ctcss clean on change mode
2024-03-23 19:27:05 +01:00
Mark Thompson 1a87f2d701 Revert accidental newbutton bg color change (#2029) 2024-03-23 13:26:46 -05:00
Mark Thompson 81e24d582d More debug Audio Beep Test tweaks (#2028) 2024-03-23 13:25:36 -05:00
Mark Thompson 28a5fc5915 Improved Audio Beep Test (#2026) 2024-03-23 08:21:35 +01:00
78 changed files with 617 additions and 197 deletions
+1
View File
@@ -190,6 +190,7 @@ set(CPPSRC
event_m0.cpp
file_reader.cpp
file.cpp
file_path.cpp
freqman_db.cpp
freqman.cpp
io_convert.cpp
+3 -2
View File
@@ -30,6 +30,7 @@
#include "portapack.hpp"
#include "portapack_persistent_memory.hpp"
#include "utility.hpp"
#include "file_path.hpp"
#include <algorithm>
#include <cstring>
@@ -40,7 +41,7 @@ using namespace portapack;
namespace {
fs::path get_settings_path(const std::string& app_name) {
return fs::path{SETTINGS_DIR} / app_name + u".ini";
return settings_dir / app_name + u".ini";
}
} // namespace
@@ -156,7 +157,7 @@ bool save_settings(std::string_view store_name, const SettingBindings& bindings)
File f;
auto path = get_settings_path(std::string{store_name});
ensure_directory(SETTINGS_DIR);
ensure_directory(settings_dir);
auto error = f.create(path);
if (error)
return false;
-3
View File
@@ -36,9 +36,6 @@
#include "max283x.hpp"
#include "string_format.hpp"
// Folder to store app settings, pmem_fileflag, and date_fileflag
#define SETTINGS_DIR u"/SETTINGS"
// Bring in the string_view literal.
using std::literals::operator""sv;
+2 -1
View File
@@ -24,6 +24,7 @@
#include "baseband_api.hpp"
#include "portapack_persistent_memory.hpp"
#include "file_path.hpp"
using namespace portapack;
using namespace acars;
@@ -77,7 +78,7 @@ ACARSAppView::ACARSAppView(NavigationView& nav)
logger = std::make_unique<ACARSLogger>();
if (logger)
logger->append(LOG_ROOT_DIR "/ACARS.TXT");
logger->append(logs_dir / u"ACARS.TXT");
}
ACARSAppView::~ACARSAppView() {
+1 -1
View File
@@ -35,7 +35,7 @@
class ACARSLogger {
public:
Optional<File::Error> append(const std::string& filename) {
Optional<File::Error> append(const std::filesystem::path& filename) {
return log_file.append(filename);
}
+2 -1
View File
@@ -23,6 +23,7 @@
#include "string_format.hpp"
#include "database.hpp"
#include "file_path.hpp"
#include "baseband_api.hpp"
@@ -399,7 +400,7 @@ AISAppView::AISAppView(NavigationView& nav)
logger = std::make_unique<AISLogger>();
if (logger) {
logger->append(LOG_ROOT_DIR "/AIS.TXT");
logger->append(logs_dir / u"AIS.TXT");
}
}
+2 -1
View File
@@ -32,6 +32,7 @@
#include "string_format.hpp"
#include "portapack_persistent_memory.hpp"
#include "ui_text.hpp"
#include "file_path.hpp"
using namespace portapack;
using namespace modems;
@@ -100,7 +101,7 @@ BLECommView::BLECommView(NavigationView& nav)
logging = v;
if (logger && logging)
logger->append(LOG_ROOT_DIR "/BLELOG_" + to_string_timestamp(rtc_time::now()) + ".TXT");
logger->append(logs_dir.string() + "/BLELOG_" + to_string_timestamp(rtc_time::now()) + ".TXT");
};
options_channel.on_change = [this](size_t, int32_t i) {
+1 -1
View File
@@ -42,7 +42,7 @@
class BLECommLogger {
public:
Optional<File::Error> append(const std::string& filename) {
Optional<File::Error> append(const std::filesystem::path& filename) {
return log_file.append(filename);
}
+1 -4
View File
@@ -470,10 +470,7 @@ BLERxView::BLERxView(NavigationView& nav)
logging = v;
if (logger && logging)
logger->append(
"BLERX/Logs"
"/BLELOG_" +
to_string_timestamp(rtc_time::now()) + ".TXT");
logger->append(blerx_dir.string() + "/Logs/BLELOG_" + to_string_timestamp(rtc_time::now()) + ".TXT");
};
check_log.set_value(logging);
+6 -5
View File
@@ -36,12 +36,13 @@
#include "log_file.hpp"
#include "utility.hpp"
#include "usb_serial_thread.hpp"
#include "file_path.hpp"
#include "recent_entries.hpp"
class BLELogger {
public:
Optional<File::Error> append(const std::string& filename) {
Optional<File::Error> append(const std::filesystem::path& filename) {
return log_file.append(filename);
}
@@ -133,7 +134,7 @@ class BleRecentEntryDetailView : public View {
void on_save_file(const std::string value, BLETxPacket packetToSave);
bool saveFile(const std::filesystem::path& path, BLETxPacket packetToSave);
std::string packetFileBuffer{};
std::filesystem::path packet_save_path{u"BLERX/Lists/????.csv"};
std::filesystem::path packet_save_path{blerx_dir / u"Lists/????.csv"};
static constexpr uint8_t total_data_lines{5};
@@ -250,9 +251,9 @@ class BLERxView : public View {
uint64_t total_count = 0;
std::vector<std::string> searchList{};
std::filesystem::path find_packet_path{u"BLERX/Find/????.TXT"};
std::filesystem::path log_packets_path{u"BLERX/Logs/????.TXT"};
std::filesystem::path packet_save_path{u"BLERX/Lists/????.csv"};
std::filesystem::path find_packet_path{blerx_dir / u"Find/????.TXT"};
std::filesystem::path log_packets_path{blerx_dir / u"Logs/????.TXT"};
std::filesystem::path packet_save_path{blerx_dir / u"Lists/????.csv"};
static constexpr auto header_height = 4 * 16;
static constexpr auto switch_button_height = 3 * 16;
+1
View File
@@ -34,6 +34,7 @@
#include "portapack_persistent_memory.hpp"
#include "rtc_time.hpp"
#include "string_format.hpp"
#include "file_path.hpp"
using namespace portapack;
using namespace modems;
+4 -3
View File
@@ -36,6 +36,7 @@
#include "replay_thread.hpp"
#include "log_file.hpp"
#include "utility.hpp"
#include "file_path.hpp"
#include "recent_entries.hpp"
@@ -44,7 +45,7 @@
class BLELoggerTx {
public:
Optional<File::Error> append(const std::string& filename) {
Optional<File::Error> append(const std::filesystem::path& filename) {
return log_file.append(filename);
}
@@ -138,7 +139,7 @@ class BLETxView : public View {
uint32_t prev_value{0};
std::filesystem::path file_path{};
std::filesystem::path packet_save_path{u"BLETX/BLETX_????.TXT"};
std::filesystem::path packet_save_path{bletx_dir / u"BLETX_????.TXT"};
uint8_t channel_number = 37;
bool auto_channel = false;
@@ -165,7 +166,7 @@ class BLETxView : public View {
std::unique_ptr<FileWrapper> dataFileWrapper{};
File dataFile{};
std::filesystem::path dataTempFilePath{u"BLETX/dataFileTemp.TXT"};
std::filesystem::path dataTempFilePath{bletx_dir / u"dataFileTemp.TXT"};
std::vector<uint16_t> markedBytes{};
CursorPos cursor_pos{};
uint8_t marked_counter = 0;
+2 -1
View File
@@ -31,6 +31,7 @@
#include "ui_spectrum.hpp"
#include "app_settings.hpp"
#include "radio_state.hpp"
#include "file_path.hpp"
namespace ui {
@@ -101,7 +102,7 @@ class CaptureAppView : public View {
RecordView record_view{
{0 * 8, 2 * 16, 30 * 8, 1 * 16},
u"BBD_????.*",
u"CAPTURES",
captures_dir,
RecordView::FileType::RawS16,
16384,
3};
+2 -1
View File
@@ -31,6 +31,7 @@ using namespace portapack;
#include "crc.hpp"
#include "string_format.hpp"
#include "file_path.hpp"
namespace ert {
@@ -129,7 +130,7 @@ ERTAppView::ERTAppView(NavigationView& nav)
logger = std::make_unique<ERTLogger>();
if (logger) {
logger->append(LOG_ROOT_DIR "/ERT.TXT");
logger->append(logs_dir / u"ERT.TXT");
}
}
+2 -1
View File
@@ -27,6 +27,7 @@
#include "portapack_persistent_memory.hpp"
#include "string_format.hpp"
#include "utility.hpp"
#include "file_path.hpp"
using namespace portapack;
using namespace pocsag;
@@ -115,7 +116,7 @@ POCSAGAppView::POCSAGAppView(NavigationView& nav)
: FILTER_DROP;
}
logger.append(LOG_ROOT_DIR "/POCSAG.TXT");
logger.append(logs_dir / u"POCSAG.TXT");
field_squelch.set_value(receiver_model.squelch_level());
field_squelch.on_change = [this](int32_t v) {
+1 -1
View File
@@ -39,7 +39,7 @@
class POCSAGLogger {
public:
Optional<File::Error> append(const std::string& filename) {
Optional<File::Error> append(const std::filesystem::path& filename) {
return log_file.append(filename);
}
+3 -2
View File
@@ -28,6 +28,7 @@
#include "tonesets.hpp"
#include "ui_tone_key.hpp"
#include "audio.hpp"
#include "file_path.hpp"
using namespace tonekey;
using namespace portapack;
@@ -164,7 +165,7 @@ void SoundBoardView::refresh_list() {
// List directories and files, put directories up top
uint32_t count = 0;
for (const auto& entry : std::filesystem::directory_iterator(u"WAV", u"*")) {
for (const auto& entry : std::filesystem::directory_iterator(wav_dir, u"*")) {
if (std::filesystem::is_regular_file(entry.status())) {
if (entry.path().string().length()) {
auto entry_extension = entry.path().extension().string();
@@ -173,7 +174,7 @@ void SoundBoardView::refresh_list() {
c = toupper(c);
if (entry_extension == ".WAV") {
if (reader->open(u"/WAV/" + entry.path().native())) {
if (reader->open(wav_dir / entry.path())) {
if ((reader->channels() == 1) && ((reader->bits_per_sample() == 8) || (reader->bits_per_sample() == 16))) {
// sounds[c].ms_duration = reader->ms_duration();
// sounds[c].path = u"WAV/" + entry.path().native();
+2 -1
View File
@@ -30,6 +30,7 @@ using namespace portapack;
#include "string_format.hpp"
#include "utility.hpp"
#include "file_path.hpp"
namespace tpms {
@@ -176,7 +177,7 @@ TPMSAppView::TPMSAppView(NavigationView&) {
logger = std::make_unique<TPMSLogger>();
if (logger) {
logger->append(LOG_ROOT_DIR "/TPMS.TXT");
logger->append(logs_dir / u"TPMS.TXT");
}
}
+2 -1
View File
@@ -31,6 +31,7 @@
#include "portapack_persistent_memory.hpp"
#include "rtc_time.hpp"
#include "string_format.hpp"
#include "file_path.hpp"
using namespace portapack;
@@ -390,7 +391,7 @@ ADSBRxView::ADSBRxView(NavigationView& nav) {
};
logger = std::make_unique<ADSBLogger>();
logger->append(LOG_ROOT_DIR "/ADSB.TXT");
logger->append(logs_dir / u"ADSB.TXT");
receiver_model.enable();
baseband::set_adsb();
+2 -1
View File
@@ -27,6 +27,7 @@
#include "baseband_api.hpp"
#include "string_format.hpp"
#include "portapack_persistent_memory.hpp"
#include "file_path.hpp"
using namespace portapack;
@@ -111,7 +112,7 @@ APRSRxView::APRSRxView(NavigationView& nav, Rect parent_rect)
logger = std::make_unique<APRSLogger>();
if (logger)
logger->append(LOG_ROOT_DIR "/APRS.TXT");
logger->append(logs_dir / u"APRS.TXT");
baseband::set_aprs(1200);
+3 -2
View File
@@ -36,10 +36,11 @@
#include "log_file.hpp"
#include "utility.hpp"
#include "file_path.hpp"
class APRSLogger {
public:
Optional<File::Error> append(const std::string& filename) {
Optional<File::Error> append(const std::filesystem::path& filename) {
return log_file.append(filename);
}
@@ -232,7 +233,7 @@ class APRSRxView : public View {
RecordView record_view{
{0 * 8, 1 * 16, 30 * 8, 1 * 16},
u"AFS_????.WAV",
u"APRS",
aprs_dir,
RecordView::FileType::WAV,
4096,
4};
+1 -1
View File
@@ -694,7 +694,7 @@ FileManagerView::FileManagerView(
button_show_hidden_files.on_select = [this]() {
show_hidden_files = !show_hidden_files;
button_show_hidden_files.set_color(show_hidden_files ? Color::dark_green() : Color::dark_grey());
button_show_hidden_files.set_color(show_hidden_files ? Color::green() : Color::dark_grey());
reload_current();
};
}
+4 -4
View File
@@ -261,19 +261,19 @@ class FileManagerView : public FileManBaseView {
{22 * 8, 29 * 8, 4 * 8, 32},
{},
&bitmap_icon_new_dir,
Color::dark_green()};
Color::green()};
NewButton button_new_file{
{26 * 8, 29 * 8, 4 * 8, 32},
{},
&bitmap_icon_new_file,
Color::dark_green()};
Color::green()};
NewButton button_open_notepad{
{0 * 8, 34 * 8, 4 * 8, 32},
{},
&bitmap_icon_notepad,
Color::dark_orange()};
Color::orange()};
NewButton button_rename_timestamp{
@@ -288,7 +288,7 @@ class FileManagerView : public FileManBaseView {
{4 * 8, 34 * 8, 4 * 8, 32},
{},
&bitmap_icon_trim,
Color::dark_orange()};
Color::orange()};
NewButton button_show_hidden_files{
{17 * 8, 34 * 8, 4 * 8, 32},
@@ -23,11 +23,10 @@
#include "ui_flash_utility.hpp"
#include "ui_styles.hpp"
#include "portapack_shared_memory.hpp"
#include "file_path.hpp"
namespace ui {
static const std::filesystem::path firmware_path = u"/FIRMWARE";
// Firmware image validation
static const char* hackrf_magic = "HACKRFFW";
#define FIRMWARE_INFO_AREA_OFFSET 0x400
@@ -84,7 +83,7 @@ FlashUtilityView::FlashUtilityView(NavigationView& nav)
menu_view.set_parent_rect({0, 3 * 8, 240, 33 * 8});
ensure_directory(firmware_path);
ensure_directory(firmware_dir);
auto add_firmware_items = [&](
const std::filesystem::path& folder_path,
@@ -103,8 +102,8 @@ FlashUtilityView::FlashUtilityView(NavigationView& nav)
}
};
add_firmware_items(firmware_path, u"*.bin", ui::Color::red());
add_firmware_items(firmware_path, u"*.tar", ui::Color::purple());
add_firmware_items(firmware_dir, u"*.bin", ui::Color::red());
add_firmware_items(firmware_dir, u"*.tar", ui::Color::purple());
// add_firmware_items(user_firmware_folder,u"*.bin", ui::Color::purple());
}
@@ -116,7 +115,7 @@ void FlashUtilityView::firmware_selected(std::filesystem::path::string_type path
YESNO,
[this, path](bool choice) {
if (choice) {
std::u16string full_path = std::u16string(u"FIRMWARE/") + path;
std::filesystem::path::string_type full_path = firmware_dir.native() + u"/" + path;
this->flash_firmware(full_path);
}
});
+1
View File
@@ -31,6 +31,7 @@
#include "ui_receiver.hpp"
#include "ui_styles.hpp"
#include "utility.hpp"
#include "file_path.hpp"
#include <memory>
+2 -1
View File
@@ -27,6 +27,7 @@
#include "portapack_persistent_memory.hpp"
#include "string_format.hpp"
#include "utility.hpp"
#include "file_path.hpp"
#include "ui_freqman.hpp"
@@ -134,7 +135,7 @@ FskxRxMainView::FskxRxMainView(NavigationView& nav)
field_frequency.set_value(initial_target_frequency);
deviation_frequency.set_value(initial_deviation);
logger.append(LOG_ROOT_DIR "/FSKRX.TXT");
logger.append(logs_dir / u"FSKRX.TXT");
baseband::set_fsk(initial_deviation);
+1 -1
View File
@@ -42,7 +42,7 @@
class FskRxLogger {
public:
Optional<File::Error> append(const std::string& filename) {
Optional<File::Error> append(const std::filesystem::path& filename) {
return log_file.append(filename);
}
+2 -1
View File
@@ -25,6 +25,7 @@
#include "complex.hpp"
#include "portapack.hpp"
#include "ui_fileman.hpp"
#include "file_path.hpp"
using namespace portapack;
namespace fs = std::filesystem;
@@ -47,7 +48,7 @@ IQTrimView::IQTrimView(NavigationView& nav)
field_path.on_select = [this](TextField&) {
auto open_view = nav_.push<FileLoadView>(".C*");
open_view->push_dir(u"CAPTURES");
open_view->push_dir(captures_dir);
open_view->on_changed = [this](fs::path path) {
open_file(path);
};
+88 -26
View File
@@ -35,6 +35,30 @@ using portapack::memory::map::backup_ram;
namespace ui {
// Function to map the value from one range to another
int32_t LevelView::map(int32_t value, int32_t fromLow, int32_t fromHigh, int32_t toLow, int32_t toHigh) {
return toLow + (value - fromLow) * (toHigh - toLow) / (fromHigh - fromLow);
}
void LevelView::m4_manage_stat_update() {
if (audio_mode) {
if (radio_mode == WFM_MODULATION || radio_mode == SPEC_MODULATION) {
shared_memory.request_m4_performance_counter = 1;
} else {
shared_memory.request_m4_performance_counter = 2;
}
if (radio_mode == SPEC_MODULATION) {
beep = true;
}
} else {
shared_memory.request_m4_performance_counter = 2;
if (radio_mode == SPEC_MODULATION) {
beep = false;
baseband::request_beep_stop();
}
}
}
void LevelView::focus() {
button_frequency.focus();
}
@@ -62,18 +86,15 @@ LevelView::LevelView(NavigationView& nav)
&freq_stats_rssi,
&freq_stats_db,
&freq_stats_rx,
&audio_mode,
&text_beep_squelch,
&field_beep_squelch,
&field_audio_mode,
&peak_mode,
&rssi,
&rssi_graph});
// activate vertical bar mode
rssi.set_vertical_rssi(true);
// activate counters for RxSat
shared_memory.request_m4_performance_counter = 2;
change_mode(NFM_MODULATION); // Start on AM
field_mode.set_by_value(NFM_MODULATION); // Reflect the mode into the manual selector
freq_ = receiver_model.target_frequency();
button_frequency.set_text("<" + to_string_short_freq(freq_) + " MHz>");
@@ -87,6 +108,11 @@ LevelView::LevelView(NavigationView& nav)
};
};
field_beep_squelch.set_value(beep_squelch);
field_beep_squelch.on_change = [this](int32_t v) {
beep_squelch = v;
};
button_frequency.on_change = [this]() {
int64_t def_step = freqman_entry_get_step_value(step_mode.selected_index());
freq_ = freq_ + (button_frequency.get_encoder_delta() * def_step);
@@ -102,17 +128,14 @@ LevelView::LevelView(NavigationView& nav)
button_frequency.set_text("<" + to_string_short_freq(freq_) + " MHz>");
};
freqman_set_modulation_option(field_mode);
field_mode.on_change = [this](size_t, OptionsField::value_t v) {
if (v != -1) {
receiver_model.disable();
baseband::shutdown();
change_mode(v);
if (audio_mode.selected_index() != 0) {
audio::output::start();
}
receiver_model.enable();
}
};
field_mode.set_by_value(radio_mode); // Reflect the mode into the manual selector
field_bw.set_selected_index(radio_bw);
rssi_resolution.on_change = [this](size_t, OptionsField::value_t v) {
if (v != -1) {
@@ -120,15 +143,18 @@ LevelView::LevelView(NavigationView& nav)
}
};
audio_mode.on_change = [this](size_t, OptionsField::value_t v) {
field_audio_mode.on_change = [this](size_t, OptionsField::value_t v) {
audio_mode = v;
if (v == 0) {
audio::output::stop();
} else if (v == 1) {
audio::set_rate(audio_sampling_rate);
audio::output::start();
receiver_model.set_headphone_volume(receiver_model.headphone_volume()); // WM8731 hack.
} else {
}
m4_manage_stat_update(); // rx_sat hack
};
field_audio_mode.set_selected_index(audio_mode);
peak_mode.on_change = [this](size_t, OptionsField::value_t v) {
if (v == 0) {
@@ -142,7 +168,6 @@ LevelView::LevelView(NavigationView& nav)
peak_mode.set_selected_index(2);
rssi_resolution.set_selected_index(1);
// FILL STEP OPTIONS
freqman_set_modulation_option(field_mode);
freqman_set_step_option_short(step_mode);
freq_stats_rssi.set_style(&Styles::white);
freq_stats_db.set_style(&Styles::white);
@@ -168,13 +193,28 @@ void LevelView::on_statistics_update(const ChannelStatistics& statistics) {
last_min_rssi = rssi_graph.get_graph_min();
last_avg_rssi = rssi_graph.get_graph_avg();
last_max_rssi = rssi_graph.get_graph_max();
freq_stats_rssi.set("RSSI: " + to_string_dec_uint(last_min_rssi) + "/" + to_string_dec_uint(last_avg_rssi) + "/" + to_string_dec_uint(last_max_rssi) + ", dt: " + to_string_dec_uint(rssi_graph.get_graph_delta()));
freq_stats_rssi.set("RSSI: " + to_string_dec_uint(last_min_rssi) + "/" + to_string_dec_uint(last_avg_rssi) + "/" + to_string_dec_uint(last_max_rssi));
}
if (beep && statistics.max_db > beep_squelch) {
baseband::request_audio_beep(map(statistics.max_db, -100, 20, 400, 2600), 24000, 150);
}
// refresh sat
if (radio_mode == SPEC_MODULATION || (radio_mode == WFM_MODULATION && audio_mode == 1)) {
Style style_freq_stats_rx{
.font = font::fixed_8x16,
.background = {55, 55, 55},
.foreground = {155, 155, 155},
};
freq_stats_rx.set_style(&style_freq_stats_rx);
freq_stats_rx.set("RxSat off");
return;
}
uint8_t rx_sat = ((uint32_t)shared_memory.m4_performance_counter) * 100 / 127;
if (last_rx_sat != rx_sat) {
last_rx_sat = rx_sat;
freq_stats_rx.set("RxSat: " + to_string_dec_uint(rx_sat) + "%");
uint8_t br = 0;
uint8_t bg = 0;
uint8_t bb = 0;
@@ -191,6 +231,7 @@ void LevelView::on_statistics_update(const ChannelStatistics& statistics) {
.foreground = {255, 255, 255},
};
freq_stats_rx.set_style(&style_freq_stats_rx);
freq_stats_rx.set("RxSat: " + to_string_dec_uint(rx_sat) + "%");
}
} /* on_statistic_updates */
@@ -198,44 +239,53 @@ void LevelView::on_statistics_update(const ChannelStatistics& statistics) {
size_t LevelView::change_mode(freqman_index_t new_mod) {
field_bw.on_change = [this](size_t n, OptionsField::value_t) { (void)n; };
radio_mode = new_mod;
audio::output::stop();
receiver_model.disable();
baseband::shutdown();
switch (new_mod) {
case AM_MODULATION:
audio_sampling_rate = audio::Rate::Hz_12000;
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);
receiver_model.set_am_configuration(field_bw.selected_index_value());
field_bw.on_change = [this](size_t, OptionsField::value_t n) { receiver_model.set_am_configuration(n); };
// bw DSB (0) default
field_bw.set_by_value(0);
text_ctcss.set(" ");
receiver_model.set_am_configuration(0);
field_bw.on_change = [this](size_t index, OptionsField::value_t n) { radio_bw = index ; receiver_model.set_am_configuration(n); };
break;
case NFM_MODULATION:
audio_sampling_rate = audio::Rate::Hz_24000;
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);
receiver_model.set_nbfm_configuration(field_bw.selected_index_value());
field_bw.on_change = [this](size_t, OptionsField::value_t n) { receiver_model.set_nbfm_configuration(n); };
// bw 16k (2) default
field_bw.set_by_value(2);
field_bw.on_change = [this](size_t index, OptionsField::value_t n) { radio_bw = index ; receiver_model.set_nbfm_configuration(n); };
break;
case WFM_MODULATION:
audio_sampling_rate = audio::Rate::Hz_48000;
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);
receiver_model.set_wfm_configuration(field_bw.selected_index_value());
field_bw.on_change = [this](size_t, OptionsField::value_t n) { receiver_model.set_wfm_configuration(n); };
// bw 200k (0) only/default
// bw 200k (0) default
field_bw.set_by_value(0);
text_ctcss.set(" ");
field_bw.on_change = [this](size_t index, OptionsField::value_t n) { radio_bw = index ; receiver_model.set_wfm_configuration(n); };
break;
case SPEC_MODULATION:
audio_sampling_rate = audio::Rate::Hz_24000;
freqman_set_bandwidth_option(new_mod, field_bw);
baseband::run_image(portapack::spi_flash::image_tag_capture);
receiver_model.set_modulation(ReceiverModel::Mode::Capture);
field_bw.on_change = [this](size_t, OptionsField::value_t sampling_rate) {
// 12k5 (0) default
field_bw.on_change = [this](size_t index, OptionsField::value_t sampling_rate) {
radio_bw = index;
// Baseband needs to know the desired sampling and oversampling rates.
baseband::set_sample_rate(sampling_rate, get_oversample_rate(sampling_rate));
// The radio needs to know the effective sampling rate.
auto actual_sampling_rate = get_actual_sample_rate(sampling_rate);
receiver_model.set_sampling_rate(actual_sampling_rate);
@@ -250,6 +300,18 @@ size_t LevelView::change_mode(freqman_index_t new_mod) {
receiver_model.set_sampling_rate(3072000);
receiver_model.set_baseband_bandwidth(1750000);
}
if (new_mod != NFM_MODULATION) {
text_ctcss.set(" ");
}
m4_manage_stat_update(); // rx_sat hack
if (audio_mode) {
audio::set_rate(audio_sampling_rate);
audio::output::start();
receiver_model.set_headphone_volume(receiver_model.headphone_volume()); // WM8731 hack.
}
receiver_model.enable();
return step_mode.selected_index();
}
+40 -16
View File
@@ -55,14 +55,30 @@ class LevelView : public View {
NavigationView& nav_;
RxRadioState radio_state_{};
app_settings::SettingsManager settings_{
"rx_level", app_settings::Mode::RX};
int32_t map(int32_t value, int32_t fromLow, int32_t fromHigh, int32_t toLow, int32_t toHigh);
size_t change_mode(freqman_index_t mod_type);
void on_statistics_update(const ChannelStatistics& statistics);
void set_display_freq(int64_t freq);
void m4_manage_stat_update(); // to finely adjust the RxSaturation usage
rf::Frequency freq_ = {0};
bool beep = false;
uint8_t radio_mode = 0;
uint8_t radio_bw = 0;
uint8_t audio_mode = 0;
int32_t beep_squelch = 0;
audio::Rate audio_sampling_rate = audio::Rate::Hz_48000;
app_settings::SettingsManager settings_{
"rx_level",
app_settings::Mode::RX,
{
{"beep_squelch"sv, &beep_squelch},
{"audio_mode"sv, &audio_mode},
{"radio_mode"sv, &radio_mode},
{"radio_bw"sv, &radio_bw},
}};
Labels labels{
{{0 * 8, 0 * 16}, "LNA: VGA: AMP: VOL: ", Color::light_grey()},
@@ -100,23 +116,27 @@ class LevelView : public View {
{0 * 8, 2 * 16 + 8, 15 * 8, 1 * 8},
""};
OptionsField audio_mode{
OptionsField field_audio_mode{
{21 * 8, 1 * 16},
9,
{
{"audio off", 0},
{"audio on", 1}
//{"tone on", 2},
//{"tone off", 3},
}};
{{"audio off", 0},
{"audio on", 1}}};
Text text_ctcss{
{22 * 8, 3 * 16 + 4, 8 * 8, 1 * 8},
""};
Text text_beep_squelch{
{21 * 8, 3 * 16 + 4, 4 * 8, 1 * 8},
"Bip>"};
// RSSI: XX/XX/XXX,dt: XX
NumberField field_beep_squelch{
{25 * 8, 3 * 16 + 4},
4,
{-100, 20},
1,
' ',
};
// RSSI: XX/XX/XXX
Text freq_stats_rssi{
{0 * 8, 3 * 16 + 4, 22 * 8, 1 * 16},
{0 * 8, 3 * 16 + 4, 15 * 8, 1 * 16},
};
// Power: -XXX db
@@ -153,14 +173,18 @@ class LevelView : public View {
{0 * 8, 5 * 16 + 4, 10 * 8, 1 * 16},
};
Text text_ctcss{
{12 * 8, 5 * 16 + 4, 8 * 8, 1 * 8},
""};
RSSIGraph rssi_graph{
// 240x320 =>
{0, 6 * 16 + 4, 240 - 5 * 8, 320 - (6 * 16 + 4)},
{0, 6 * 16 + 8, 240 - 5 * 8, 320 - (6 * 16)},
};
RSSI rssi{
// 240x320 =>
{240 - 5 * 8, 6 * 16 + 4, 5 * 8, 320 - (6 * 16 + 4)},
{240 - 5 * 8, 6 * 16 + 8, 5 * 8, 320 - (6 * 16)},
};
void handle_coded_squelch(const uint32_t value);
@@ -25,6 +25,8 @@
#include "convert.hpp"
#include "file_reader.hpp"
#include "string_format.hpp"
#include "audio.hpp"
#include "file_path.hpp"
using namespace portapack;
@@ -34,11 +36,39 @@ void GlassView::focus() {
}
GlassView::~GlassView() {
audio::output::stop();
receiver_model.set_sampling_rate(3072000); // Just a hack to avoid hanging other apps
receiver_model.disable();
baseband::shutdown();
}
// Function to map the value from one range to another
int32_t GlassView::map(int32_t value, int32_t fromLow, int32_t fromHigh, int32_t toLow, int32_t toHigh) {
return toLow + (value - fromLow) * (toHigh - toLow) / (fromHigh - fromLow);
}
void GlassView::update_display_beep() {
if (beep_enabled) {
button_beep_squelch.set_style(&Styles::green);
// <bip:-XXXdb>
button_beep_squelch.set_text("[bip>" + to_string_dec_int(beep_squelch, 4) + "db]");
receiver_model.set_headphone_volume(receiver_model.headphone_volume()); // WM8731 hack.
} else {
button_beep_squelch.set_style(&Styles::white);
button_beep_squelch.set_text("[ beep OFF ]");
}
}
void GlassView::manage_beep_audio() {
if (beep_enabled) {
audio::set_rate(audio::Rate::Hz_24000);
audio::output::start();
} else {
baseband::request_beep_stop();
audio::output::stop();
}
}
void GlassView::get_max_power(const ChannelSpectrum& spectrum, uint8_t bin, uint8_t& max_power) {
if (mode == LOOKING_GLASS_SINGLEPASS) {
// <20MHz spectrum mode
@@ -173,6 +203,8 @@ void GlassView::on_channel_spectrum(const ChannelSpectrum& spectrum) {
// we actually need SCREEN_W (240) of those bins
for (uint8_t bin = 0; bin < bin_length; bin++) {
get_max_power(spectrum, bin, max_power);
if (max_power > range_max_power)
range_max_power = max_power;
// process dc spike if enable
if (bin == 119) {
uint8_t next_max_power = 0;
@@ -184,14 +216,21 @@ void GlassView::on_channel_spectrum(const ChannelSpectrum& spectrum) {
}
}
// process actual bin
if (process_bins(&max_power) == true)
if (process_bins(&max_power)) {
int8_t power = map(range_max_power, 0, 255, -100, 20);
if (power >= beep_squelch) {
baseband::request_audio_beep(map(range_max_power, 0, 256, 400, 2600), 24000, 250);
}
range_max_power = 0;
return; // new line signaled, return
}
}
if (mode != LOOKING_GLASS_SINGLEPASS) {
f_center += looking_glass_step;
retune();
} else
} else {
baseband::spectrum_streaming_start();
}
}
void GlassView::on_hide() {
@@ -327,13 +366,15 @@ GlassView::GlassView(
&field_lna,
&field_vga,
&field_range,
&steps_config,
//&steps_config,
&scan_type,
&view_config,
&level_integration,
&field_volume,
&filter_config,
&field_rf_amp,
&range_presets,
&button_beep_squelch,
&field_marker,
&field_trigger,
&button_jump,
@@ -370,12 +411,12 @@ GlassView::GlassView(
};
};
steps_config.on_change = [this](size_t, OptionsField::value_t v) {
/*steps_config.on_change = [this](size_t, OptionsField::value_t v) {
field_frequency_min.set_step(v);
field_frequency_max.set_step(v);
steps = v;
};
steps_config.set_selected_index(0); // 1 Mhz step.
steps_config.set_selected_index(0); // 1 Mhz step.*/
scan_type.on_change = [this](size_t, OptionsField::value_t v) {
mode = v;
@@ -497,6 +538,27 @@ GlassView::GlassView(
receiver_model.set_baseband_bandwidth(looking_glass_bandwidth); // possible values: 1.75/2.5/3.5/5/5.5/6/7/8/9/10/12/14/15/20/24/28MHz
receiver_model.set_squelch_level(0);
receiver_model.enable();
button_beep_squelch.on_select = [this](ButtonWithEncoder& button) {
(void)button;
beep_enabled = 1 - beep_enabled;
manage_beep_audio();
update_display_beep();
};
button_beep_squelch.on_change = [this]() {
int new_beep_squelch = beep_squelch + button_beep_squelch.get_encoder_delta();
if (new_beep_squelch < -100)
new_beep_squelch = -100;
if (new_beep_squelch > 20)
new_beep_squelch = 20;
beep_squelch = new_beep_squelch;
button_beep_squelch.set_encoder_delta(0);
update_display_beep();
};
manage_beep_audio();
update_display_beep();
}
uint8_t GlassView::get_spec_iq_phase_calibration_value() { // define accessor functions inside AnalogAudioView to read & write real iq_phase_calibration_value
@@ -510,7 +572,7 @@ void GlassView::set_spec_iq_phase_calibration_value(uint8_t cal_value) { // def
void GlassView::load_presets() {
File presets_file;
auto error = presets_file.open("LOOKINGGLASS/PRESETS.TXT");
auto error = presets_file.open(looking_glass_dir / u"PRESETS.TXT");
presets_db.clear();
// Add the "Manual" entry.
@@ -85,6 +85,8 @@ class GlassView : public View {
uint8_t live_frequency_view = 0; // Spectrum
uint8_t live_frequency_integrate = 3; // Default (3 * old value + new_value) / 4
uint8_t iq_phase_calibration_value{15}; // initial default RX IQ phase calibration value , used for both max2837 & max2839
int32_t beep_squelch = 20; // range from -100 to +20, >=20 disabled
bool beep_enabled = false; // activate on bip button click
app_settings::SettingsManager settings_{
"rx_glass"sv,
app_settings::Mode::RX,
@@ -98,6 +100,8 @@ class GlassView : public View {
{"freq_view"sv, &live_frequency_view},
{"freq_integrate"sv, &live_frequency_integrate},
{"iq_phase_calibration"sv, &iq_phase_calibration_value}, // we are saving and restoring that CAL from Settings.
{"beep_squelch"sv, &beep_squelch},
{"beep_enabled"sv, &beep_enabled},
}};
struct preset_entry {
@@ -106,7 +110,10 @@ class GlassView : public View {
std::string label{};
};
int32_t map(int32_t value, int32_t fromLow, int32_t fromHigh, int32_t toLow, int32_t toHigh);
std::vector<preset_entry> presets_db{};
void manage_beep_audio();
void update_display_beep();
void update_min(int32_t v);
void update_max(int32_t v);
void update_range_field();
@@ -153,6 +160,8 @@ class GlassView : public View {
int32_t steps = 1;
bool locked_range = false;
uint8_t range_max_power = 0;
uint8_t range_max_power_counter = 0;
uint8_t max_power = 0;
rf::Frequency max_freq_hold = 0;
rf::Frequency last_max_freq = 0;
@@ -166,7 +175,8 @@ class GlassView : public View {
{{0, 1 * 16}, "RANGE: FILTER: AMP:", Color::light_grey()},
{{0, 2 * 16}, "PRESET:", Color::light_grey()},
{{0, 3 * 16}, "MARKER: MHz RXIQCAL", Color::light_grey()},
{{0, 4 * 16}, "RES: STEP:", Color::light_grey()}};
//{{0, 4 * 16}, "RES: STEPS:", Color::light_grey()}};
{{0, 4 * 16}, "RES: VOL:", Color::light_grey()}};
NumberField field_frequency_min{
{4 * 8, 0 * 16},
@@ -206,9 +216,13 @@ class GlassView : public View {
OptionsField range_presets{
{7 * 8, 2 * 16},
20,
10,
{}};
ButtonWithEncoder button_beep_squelch{
{18 * 8, 2 * 16 + 4, 12 * 8, 1 * 8},
""};
TextField field_marker{
{7 * 8, 3 * 16, 9 * 8, 16},
""};
@@ -228,7 +242,10 @@ class GlassView : public View {
2,
' '};
OptionsField steps_config{
AudioVolumeField field_volume{
{13 * 8, 4 * 16}};
/*OptionsField steps_config{
{13 * 8, 4 * 16},
3,
{
@@ -238,7 +255,7 @@ class GlassView : public View {
{"100", 100},
{"250", 250},
{"500", 500},
}};
}};*/
OptionsField scan_type{
{17 * 8, 4 * 16},
+5 -4
View File
@@ -36,6 +36,7 @@
#include "string_format.hpp"
#include "ui_fileman.hpp"
#include "utility.hpp"
#include "file_path.hpp"
#include <unistd.h>
#include <fstream>
@@ -130,7 +131,7 @@ void PlaylistView::open_file(bool prompt_save) {
}
auto open_view = nav_.push<FileLoadView>(".PPL");
open_view->push_dir(u"PLAYLIST");
open_view->push_dir(playlist_dir);
open_view->on_changed = [this](fs::path new_file_path) {
on_file_changed(new_file_path);
};
@@ -169,7 +170,7 @@ void PlaylistView::save_file(bool show_dialogs) {
void PlaylistView::add_entry(fs::path&& path) {
if (playlist_path_.empty()) {
playlist_path_ = next_filename_matching_pattern(u"/PLAYLIST/PLAY_????.PPL");
playlist_path_ = next_filename_matching_pattern(playlist_dir / u"PLAY_????.PPL");
// Hack around focus getting called by ctor before parent is set.
if (parent())
@@ -387,7 +388,7 @@ PlaylistView::PlaylistView(
&waterfall,
});
ensure_directory(u"PLAYLIST");
ensure_directory(playlist_dir);
waterfall.show_audio_spectrum_view(false);
field_frequency.set_value(transmitter_model.target_frequency());
@@ -410,7 +411,7 @@ PlaylistView::PlaylistView(
if (is_active())
return;
auto open_view = nav_.push<FileLoadView>(".C*");
open_view->push_dir(u"CAPTURES");
open_view->push_dir(captures_dir);
open_view->on_changed = [this](fs::path path) {
add_entry(std::move(path));
};
+4 -4
View File
@@ -337,7 +337,7 @@ ReconView::ReconView(NavigationView& nav)
// set record View
record_view = std::make_unique<RecordView>(Rect{0, 0, 30 * 8, 1 * 16},
u"AUTO_AUDIO", u"AUDIO",
u"AUTO_AUDIO", audio_dir,
RecordView::FileType::WAV, 4096, 4);
record_view->set_filename_date_frequency(true);
record_view->set_auto_trim(false);
@@ -1170,18 +1170,18 @@ size_t ReconView::change_mode(freqman_index_t new_mod) {
if (new_mod == SPEC_MODULATION) {
if (persistent_memory::recon_repeat_recorded()) {
record_view = std::make_unique<RecordView>(Rect{0, 0, 30 * 8, 1 * 16},
u"RECON_REPEAT.C16", u"CAPTURES",
u"RECON_REPEAT.C16", captures_dir,
RecordView::FileType::RawS16, 16384, 3);
record_view->set_filename_as_is(true);
} else {
record_view = std::make_unique<RecordView>(Rect{0, 0, 30 * 8, 1 * 16},
u"AUTO_RAW", u"CAPTURES",
u"AUTO_RAW", captures_dir,
RecordView::FileType::RawS16, 16384, 3);
record_view->set_filename_date_frequency(true);
}
} else {
record_view = std::make_unique<RecordView>(Rect{0, 0, 30 * 8, 1 * 16},
u"AUTO_AUDIO", u"AUDIO",
u"AUTO_AUDIO", audio_dir,
RecordView::FileType::WAV, 4096, 4);
record_view->set_filename_date_frequency(true);
}
+1 -1
View File
@@ -38,6 +38,7 @@
#include "baseband_api.hpp"
#include "string_format.hpp"
#include "file.hpp"
#include "file_path.hpp"
#include "app_settings.hpp"
#include "radio_state.hpp"
#include "ui_recon_settings.hpp"
@@ -181,7 +182,6 @@ class ReconView : public View {
const std::filesystem::path repeat_rec_file = u"RECON_REPEAT.C16";
const std::filesystem::path repeat_rec_meta = u"RECON_REPEAT.TXT";
const std::filesystem::path repeat_rec_path = u"CAPTURES";
const size_t repeat_read_size{16384};
const size_t repeat_buffer_count{3};
int8_t repeat_cur_rep = 0;
@@ -30,6 +30,7 @@
#include "freqman_db.hpp"
#include "portapack.hpp"
#include "portapack_persistent_memory.hpp"
#include "file_path.hpp"
using namespace std;
using namespace portapack;
+5 -4
View File
@@ -32,6 +32,7 @@
#include "ui_receiver.hpp"
#include "ui_textentry.hpp"
#include "utility.hpp"
#include "file_path.hpp"
using namespace portapack;
namespace fs = std::filesystem;
@@ -246,7 +247,7 @@ RemoteEntryEditView::RemoteEntryEditView(
field_path.on_select = [this, &nav](TextField&) {
auto open_view = nav.push<FileLoadView>(".C*");
open_view->push_dir(u"CAPTURES");
open_view->push_dir(captures_dir);
open_view->on_changed = [this](fs::path path) {
load_path(std::move(path));
refresh_ui();
@@ -355,7 +356,7 @@ RemoteView::RemoteView(
Dim waterfall_height = waterfall_bottom - waterfall_top;
waterfall.set_parent_rect({0, waterfall_top, screen_width, waterfall_height});
ensure_directory(u"REMOTES");
ensure_directory(remotes_dir);
// Load the previously loaded remote if exists.
if (!load_remote(settings_.remote_path))
@@ -527,7 +528,7 @@ void RemoteView::new_remote() {
void RemoteView::open_remote() {
auto open_view = nav_.push<FileLoadView>(".REM");
open_view->push_dir(u"REMOTES");
open_view->push_dir(remotes_dir);
open_view->on_changed = [this](fs::path path) {
save_remote();
load_remote(std::move(path));
@@ -538,7 +539,7 @@ void RemoteView::open_remote() {
void RemoteView::init_remote() {
model_ = {"<Unnamed Remote>", {}};
reset_buttons();
set_remote_path(next_filename_matching_pattern(u"/REMOTES/REMOTE_????.REM"));
set_remote_path(next_filename_matching_pattern(remotes_dir / u"REMOTE_????.REM"));
set_needs_save(false);
if (remote_path_.empty())
+1
View File
@@ -26,6 +26,7 @@
#include "optional.hpp"
#include "ui_fileman.hpp"
#include "ui_freqman.hpp"
#include "file_path.hpp"
using namespace portapack;
namespace fs = std::filesystem;
+7 -6
View File
@@ -41,6 +41,7 @@ using namespace lpc43xx;
using namespace portapack;
#include "file.hpp"
#include "file_path.hpp"
namespace fs = std::filesystem;
#include "string_format.hpp"
@@ -571,17 +572,17 @@ SetPersistentMemoryView::SetPersistentMemoryView(NavigationView& nav) {
check_use_sdcard_for_pmem.on_select = [this](Checkbox&, bool v) {
File pmem_flag_file_handle;
if (v) {
if (fs::file_exists(PMEM_FILEFLAG)) {
if (fs::file_exists(settings_dir / PMEM_FILEFLAG)) {
text_pmem_status.set("P.Mem flag file present.");
} else {
auto error = pmem_flag_file_handle.create(PMEM_FILEFLAG);
auto error = pmem_flag_file_handle.create(settings_dir / PMEM_FILEFLAG);
if (error)
text_pmem_status.set("Error creating P.Mem File!");
else
text_pmem_status.set("P.Mem flag file created.");
}
} else {
auto result = delete_file(PMEM_FILEFLAG);
auto result = delete_file(settings_dir / PMEM_FILEFLAG);
if (result.code() != FR_OK)
text_pmem_status.set("Error deleting P.Mem flag!");
else
@@ -717,10 +718,10 @@ AppSettingsView::AppSettingsView(
menu_view.set_parent_rect({0, 3 * 8, 240, 33 * 8});
ensure_directory(SETTINGS_DIR);
ensure_directory(settings_dir);
for (const auto& entry : std::filesystem::directory_iterator(SETTINGS_DIR, u"*.ini")) {
auto path = (std::filesystem::path)SETTINGS_DIR / entry.path();
for (const auto& entry : std::filesystem::directory_iterator(settings_dir, u"*.ini")) {
auto path = settings_dir / entry.path();
menu_view.add_item({path.filename().string().substr(0, 26),
ui::Color::dark_cyan(),
+3 -2
View File
@@ -25,6 +25,7 @@
#include "baseband_api.hpp"
#include "audio.hpp"
#include "app_settings.hpp"
#include "file_path.hpp"
#include "portapack.hpp"
#include <cstring>
@@ -75,7 +76,7 @@ SondeView::SondeView(NavigationView& nav)
check_beep.on_select = [this](Checkbox&, bool v) {
beep = v;
if (beep)
baseband::request_audio_beep(1000, 60); // 1khz tone for 60ms to acknowledge enablement
baseband::request_audio_beep(1000, 24000, 60); // 1khz tone for 60ms to acknowledge enablement
};
check_log.set_value(logging);
@@ -112,7 +113,7 @@ SondeView::SondeView(NavigationView& nav)
logger = std::make_unique<SondeLogger>();
if (logger)
logger->append(LOG_ROOT_DIR "/SONDE.TXT");
logger->append(logs_dir / u"SONDE.TXT");
audio::output::start();
+1 -1
View File
@@ -38,7 +38,7 @@
class TestLogger {
public:
Optional<File::Error> append(const std::string& filename) {
Optional<File::Error> append(const std::filesystem::path& filename) {
return log_file.append(filename);
}
+2 -1
View File
@@ -27,6 +27,7 @@
#include "event_m0.hpp"
#include "file_reader.hpp"
#include "portapack.hpp"
#include "file_path.hpp"
#include <cstring>
@@ -142,7 +143,7 @@ WhipCalcView::WhipCalcView(NavigationView& nav)
void WhipCalcView::load_antenna_db() {
File antennas_file;
auto error = antennas_file.open("/WHIPCALC/ANTENNAS.TXT");
auto error = antennas_file.open(whipcalc_dir / u"ANTENNAS.TXT");
if (error)
return;
+2 -2
View File
@@ -445,8 +445,8 @@ void request_beep_stop() {
request_beep(RequestSignalMessage::Signal::BeepStopRequest);
}
void request_audio_beep(uint32_t freq, uint32_t duration_ms) {
AudioBeepMessage message{freq, duration_ms};
void request_audio_beep(uint32_t freq, uint32_t sample_rate, uint32_t duration_ms) {
AudioBeepMessage message{freq, sample_rate, duration_ms};
send_message(&message);
}
+1 -1
View File
@@ -93,7 +93,7 @@ void set_subghzd_config(uint8_t modulation, uint32_t sampling_rate);
void request_roger_beep();
void request_rssi_beep();
void request_beep_stop();
void request_audio_beep(uint32_t freq, uint32_t duration_ms);
void request_audio_beep(uint32_t freq, uint32_t sample_rate, uint32_t duration_ms);
void run_image(const portapack::spi_flash::image_tag_t image_tag);
void run_prepared_image(const uint32_t m4_code);
+5 -4
View File
@@ -23,10 +23,11 @@
#include "database.hpp"
#include "file.hpp"
#include "file_path.hpp"
#include <cstring>
int database::retrieve_mid_record(MidDBRecord* record, std::string search_term) {
file_path = "AIS/mids.db";
file_path = ais_dir / u"mids.db";
index_item_length = 4;
record_length = 32;
@@ -36,7 +37,7 @@ int database::retrieve_mid_record(MidDBRecord* record, std::string search_term)
}
int database::retrieve_airline_record(AirlinesDBRecord* record, std::string search_term) {
file_path = "ADSB/airlines.db";
file_path = adsb_dir / u"airlines.db";
index_item_length = 4;
record_length = 64;
@@ -46,7 +47,7 @@ int database::retrieve_airline_record(AirlinesDBRecord* record, std::string sear
}
int database::retrieve_aircraft_record(AircraftDBRecord* record, std::string search_term) {
file_path = "ADSB/icao24.db";
file_path = adsb_dir / u"icao24.db";
index_item_length = 7;
record_length = 146;
@@ -55,7 +56,7 @@ int database::retrieve_aircraft_record(AircraftDBRecord* record, std::string sea
return (result);
}
int database::retrieve_record(std::string file_path, int index_item_length, int record_length, void* record, std::string search_term) {
int database::retrieve_record(std::filesystem::path file_path, int index_item_length, int record_length, void* record, std::string search_term) {
if (search_term.empty())
return DATABASE_RECORD_NOT_FOUND;
+4 -4
View File
@@ -61,9 +61,9 @@ class database {
int retrieve_aircraft_record(AircraftDBRecord* record, std::string search_term);
private:
std::string file_path = ""; // path inclusing filename
int index_item_length = 0; // length of index item
int record_length = 0; // length of record
std::filesystem::path file_path = ""; // path including filename
int index_item_length = 0; // length of index item
int record_length = 0; // length of record
File db_file{};
int number_of_records = 0;
@@ -74,7 +74,7 @@ class database {
int result = 0;
int retrieve_record(std::string file_path, int index_item_length, int record_length, void* record, std::string search_term);
int retrieve_record(std::filesystem::path file_path, int index_item_length, int record_length, void* record, std::string search_term);
};
#endif /*__DATABASE_H__*/
+2 -2
View File
@@ -32,6 +32,7 @@
#include "string_format.hpp"
#include "ui_styles.hpp"
#include "irq_controls.hpp"
#include "file_path.hpp"
using namespace ui;
@@ -266,7 +267,6 @@ bool stack_dump() {
bool memory_dump(uint32_t* addr_start, uint32_t num_words, bool stack_flag) {
Painter painter;
std::string debug_dir = "DEBUG";
std::filesystem::path filename{};
File dump_file{};
bool error;
@@ -277,7 +277,7 @@ bool memory_dump(uint32_t* addr_start, uint32_t num_words, bool stack_flag) {
bool data_found{false};
ensure_directory(debug_dir);
filename = next_filename_matching_pattern(debug_dir + "/" + (stack_flag ? "STACK" : "MEMORY") + "_DUMP_????.TXT");
filename = next_filename_matching_pattern(debug_dir + (stack_flag ? u"/STACK" : u"/MEMORY") + u"_DUMP_????.TXT");
error = filename.empty();
if (!error)
error = dump_file.create(filename) != 0;
+2 -1
View File
@@ -29,6 +29,7 @@
#include "baseband_api.hpp"
#include "string_format.hpp"
#include "portapack_persistent_memory.hpp"
#include "file_path.hpp"
using namespace portapack;
using namespace modems;
@@ -84,7 +85,7 @@ AFSKRxView::AFSKRxView(NavigationView& nav)
logger = std::make_unique<AFSKLogger>();
if (logger)
logger->append(LOG_ROOT_DIR "/AFSK.TXT");
logger->append(logs_dir / u"AFSK.TXT");
// Auto-configure modem for LCR RX (will be removed later)
baseband::set_afsk(persistent_memory::modem_baudrate(), 8, 0, false);
+1 -1
View File
@@ -40,7 +40,7 @@ namespace ui::external_app::afsk_rx {
class AFSKLogger {
public:
Optional<File::Error> append(const std::string& filename) {
Optional<File::Error> append(const std::filesystem::path& filename) {
return log_file.append(filename);
}
+31 -7
View File
@@ -33,29 +33,53 @@ AudioTestView::AudioTestView(NavigationView& nav)
baseband::run_prepared_image(portapack::memory::map::m4_code.base()); // proc_audio_beep baseband is external too
add_children({&labels,
&options_sample_rate,
&field_frequency,
&options_step,
&field_duration,
&field_volume,
&toggle_speaker});
field_frequency.set_value(1000);
field_frequency.on_change = [this](int32_t v) {
(void)v;
audio::set_rate(audio::Rate::Hz_24000);
options_sample_rate.on_change = [this](size_t, int32_t v) {
switch (v) {
case 12000:
audio::set_rate(audio::Rate::Hz_12000);
break;
case 24000:
audio::set_rate(audio::Rate::Hz_24000);
break;
case 48000:
audio::set_rate(audio::Rate::Hz_48000);
break;
}
field_frequency.set_range(v / 128, v / 2);
update_audio_beep();
};
options_sample_rate.set_selected_index(0, 1);
field_frequency.on_change = [this](int32_t) {
update_audio_beep();
};
field_frequency.set_value(1000);
options_step.on_change = [this](size_t, int32_t v) {
field_frequency.set_step(v);
};
options_step.set_by_value(100);
field_duration.set_value(100);
field_duration.on_change = [this](int32_t v) {
(void)v;
update_audio_beep();
};
field_duration.set_value(100);
toggle_speaker.on_change = [this](bool v) {
beep = v;
update_audio_beep();
};
field_volume.set_value(0);
field_volume.set_value(0); // seems that a change is required to force update, so setting to 0 first
field_volume.set_value(80);
audio::set_rate(audio::Rate::Hz_24000);
@@ -69,12 +93,12 @@ AudioTestView::~AudioTestView() {
}
void AudioTestView::focus() {
field_frequency.focus();
toggle_speaker.focus();
}
void AudioTestView::update_audio_beep() {
if (beep)
baseband::request_audio_beep(field_frequency.value(), field_duration.value());
baseband::request_audio_beep(field_frequency.value(), options_sample_rate.selected_index_value(), field_duration.value());
else
baseband::request_beep_stop();
}
+26 -8
View File
@@ -45,20 +45,38 @@ class AudioTestView : public View {
Labels labels{
{{7 * 8, 3 * 16}, "Audio Beep Test", Color::light_grey()},
{{0 * 8, 6 * 16}, "Frequency (Hz):", Color::light_grey()},
{{0 * 8, 8 * 16}, "Duration (ms):", Color::light_grey()},
{{0 * 8, 10 * 16}, "Volume:", Color::light_grey()}};
{{0 * 8, 6 * 16}, "Sample Rate (Hz):", Color::light_grey()},
{{25 * 8, 7 * 16}, "Step:", Color::light_grey()},
{{0 * 8, 8 * 16}, "Frequency (Hz):", Color::light_grey()},
{{0 * 8, 10 * 16}, "Duration (ms):", Color::light_grey()},
{{25 * 8, 10 * 16}, "0=con", Color::light_grey()},
{{0 * 8, 12 * 16}, "Volume:", Color::light_grey()}};
OptionsField options_sample_rate{
{18 * 8, 6 * 16},
5,
{{"24000", 24000},
{"48000", 48000},
{"12000", 12000}}};
OptionsField options_step{
{26 * 8, 8 * 16},
4,
{{" 1", 1},
{" 10", 10},
{" 100", 100},
{"1000", 1000}}};
NumberField field_frequency{
{16 * 8, 6 * 16},
{18 * 8, 8 * 16},
5,
{100, 24000},
{},
100,
' ',
true};
NumberField field_duration{
{16 * 8, 8 * 16},
{18 * 8, 10 * 16},
5,
{0, 60000},
50,
@@ -66,10 +84,10 @@ class AudioTestView : public View {
true};
AudioVolumeField field_volume{
{19 * 8, 10 * 16}};
{21 * 8, 12 * 16}};
ImageToggle toggle_speaker{
{19 * 8, 12 * 16, 2 * 8, 1 * 16},
{21 * 8, 14 * 16, 2 * 8, 1 * 16},
&bitmap_icon_speaker_mute,
&bitmap_icon_speaker,
Color::light_grey(),
@@ -76,15 +76,15 @@ SpectrumPainterView::SpectrumPainterView(
transmitter_model.set_rf_amp(rf_amp);
};
input_image.on_input_avaliable = [this]() {
image_input_avaliable = true;
input_image.on_input_available = [this]() {
image_input_available = true;
};
button_play.on_select = [this](ImageButton&) {
if (tx_active == false) {
tx_mode = tab_view.selected();
if (tx_mode == 0 && image_input_avaliable == false)
if (tx_mode == 0 && image_input_available == false)
return;
/* By experimental test measurement, we got a good painted spectrum quality when selecting
a BW GUI App range from 100k ... 2M aprox. In that range , the best TX LPF filter = 1M75 (the min)
@@ -61,7 +61,7 @@ class SpectrumPainterView : public View {
app_settings::SettingsManager settings_{
"tx_painter", app_settings::Mode::TX};
bool image_input_avaliable{false};
bool image_input_available{false};
bool tx_active{false};
uint32_t tx_mode{0};
uint16_t tx_current_line{0};
@@ -28,6 +28,7 @@
#include "io_file.hpp"
#include "file.hpp"
#include "portapack_persistent_memory.hpp"
#include "file_path.hpp"
namespace ui::external_app::spainter {
@@ -39,15 +40,14 @@ SpectrumInputImageView::SpectrumInputImageView(NavigationView& nav) {
button_load_image.on_select = [this, &nav](Button&) {
auto open_view = nav.push<FileLoadView>(".bmp");
constexpr auto data_directory = u"SPECTRUM";
ensure_directory(data_directory);
open_view->push_dir(data_directory);
ensure_directory(spectrum_dir);
open_view->push_dir(spectrum_dir);
open_view->on_changed = [this](std::filesystem::path new_file_path) {
this->file = new_file_path.string();
painted = false;
this->set_dirty();
this->on_input_avaliable();
this->on_input_available();
};
};
}
@@ -46,7 +46,7 @@ class SpectrumInputImageView : public View {
uint16_t get_height();
std::vector<uint8_t> get_line(uint16_t);
std::function<void()> on_input_avaliable{};
std::function<void()> on_input_available{};
private:
bool painted{false};
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2024 Mark Thompson
*
* 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 "file_path.hpp"
#include "file.hpp"
const std::filesystem::path adsb_dir = u"ADSB";
const std::filesystem::path ais_dir = u"AIS";
const std::filesystem::path aprs_dir = u"APRS";
const std::filesystem::path audio_dir = u"AUDIO";
const std::filesystem::path blerx_dir = u"BLERX";
const std::filesystem::path bletx_dir = u"BLETX";
const std::filesystem::path captures_dir = u"CAPTURES";
const std::filesystem::path debug_dir = u"DEBUG";
const std::filesystem::path firmware_dir = u"FIRMWARE";
const std::filesystem::path freqman_dir = u"FREQMAN";
const std::filesystem::path logs_dir = u"LOGS";
const std::filesystem::path looking_glass_dir = u"LOOKINGGLASS";
const std::filesystem::path playlist_dir = u"PLAYLIST";
const std::filesystem::path remotes_dir = u"REMOTES";
const std::filesystem::path repeat_rec_path = u"CAPTURES";
const std::filesystem::path screenshots_dir = u"SCREENSHOTS";
const std::filesystem::path settings_dir = u"SETTINGS";
const std::filesystem::path spectrum_dir = u"SPECTRUM";
const std::filesystem::path splash_dir = u"SPLASH";
const std::filesystem::path sstv_dir = u"SSTV";
const std::filesystem::path wav_dir = u"WAV";
const std::filesystem::path whipcalc_dir = u"WHIPCALC";
+50
View File
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2024 Mark Thompson
*
* 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.
*/
#ifndef __FILE_PATH_H__
#define __FILE_PATH_H__
#include "file.hpp"
extern const std::filesystem::path adsb_dir;
extern const std::filesystem::path ais_dir;
extern const std::filesystem::path aprs_dir;
extern const std::filesystem::path audio_dir;
extern const std::filesystem::path blerx_dir;
extern const std::filesystem::path bletx_dir;
extern const std::filesystem::path captures_dir;
extern const std::filesystem::path debug_dir;
extern const std::filesystem::path firmware_dir;
extern const std::filesystem::path freqman_dir;
extern const std::filesystem::path logs_dir;
extern const std::filesystem::path looking_glass_dir;
extern const std::filesystem::path playlist_dir;
extern const std::filesystem::path remotes_dir;
extern const std::filesystem::path repeat_rec_path;
extern const std::filesystem::path screenshots_dir;
extern const std::filesystem::path settings_dir;
extern const std::filesystem::path spectrum_dir;
extern const std::filesystem::path splash_dir;
extern const std::filesystem::path sstv_dir;
extern const std::filesystem::path wav_dir;
extern const std::filesystem::path whipcalc_dir;
#endif /* __FILE_PATH_H__ */
+1 -1
View File
@@ -29,6 +29,7 @@
#include "string_format.hpp"
#include "tone_key.hpp"
#include "utility.hpp"
#include "file_path.hpp"
#include <array>
#include <cctype>
@@ -37,7 +38,6 @@
namespace fs = std::filesystem;
const std::filesystem::path freqman_dir{u"/FREQMAN"};
const std::filesystem::path freqman_extension{u".TXT"};
// NB: Don't include UI headers to keep this code unit testable.
-1
View File
@@ -36,7 +36,6 @@
#include <vector>
/* Defined in freqman_db.cpp */
extern const std::filesystem::path freqman_dir;
extern const std::filesystem::path freqman_extension;
using freqman_index_t = uint8_t;
-2
View File
@@ -27,8 +27,6 @@
#include "file.hpp"
#include "rtc_time.hpp"
#define LOG_ROOT_DIR "LOGS"
class LogFile {
public:
Optional<File::Error> append(const std::filesystem::path& filename) {
+3 -2
View File
@@ -34,6 +34,7 @@ using namespace portapack;
#include "complex.hpp"
#include "ui_styles.hpp"
#include "ui_font_fixed_5x8.hpp"
#include "file_path.hpp"
namespace ui {
@@ -447,7 +448,7 @@ void GeoMap::move(const float lon, const float lat) {
}
bool GeoMap::init() {
auto result = map_file.open("ADSB/world_map.bin");
auto result = map_file.open(adsb_dir / u"world_map.bin");
map_opened = !result.is_valid();
if (map_opened) {
@@ -613,7 +614,7 @@ void GeoMapView::focus() {
geopos.focus();
if (!geomap.map_file_opened())
nav_.display_modal("No map", "No world_map.bin file in\n/ADSB/ directory", ABORT);
nav_.display_modal("No map", "No world_map.bin file in\n/" + adsb_dir.string() + "/ directory", ABORT);
}
void GeoMapView::update_my_position(float lat, float lon, int32_t altitude) {
+4 -3
View File
@@ -106,6 +106,7 @@
#include "file.hpp"
#include "file_reader.hpp"
#include "png_writer.hpp"
#include "file_path.hpp"
using portapack::receiver_model;
using portapack::transmitter_model;
@@ -473,8 +474,8 @@ void SystemStatusView::on_bias_tee() {
}
void SystemStatusView::on_camera() {
ensure_directory("SCREENSHOTS");
auto path = next_filename_matching_pattern(u"SCREENSHOTS/SCR_????.PNG");
ensure_directory(screenshots_dir);
auto path = next_filename_matching_pattern(screenshots_dir / u"SCR_????.PNG");
if (path.empty())
return;
@@ -535,7 +536,7 @@ void SystemStatusView::rtc_battery_workaround() {
}
}
} else {
ensure_directory(SETTINGS_DIR);
ensure_directory(settings_dir);
make_new_file(DATE_FILEFLAG);
year = 1980;
+5 -4
View File
@@ -44,6 +44,7 @@
#include "ui_flash_utility.hpp"
#include "untar.hpp"
#include "ui_widget.hpp"
#include "file_path.hpp"
#include "ui_navigation.hpp"
#include "usb_serial_shell_filesystem.hpp"
@@ -167,8 +168,8 @@ static void cmd_screenshot(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)argc;
(void)argv;
ensure_directory("SCREENSHOTS");
auto path = next_filename_matching_pattern(u"SCREENSHOTS/SCR_????.PNG");
ensure_directory(screenshots_dir);
auto path = next_filename_matching_pattern(screenshots_dir / u"SCR_????.PNG");
if (path.empty())
return;
@@ -1037,9 +1038,9 @@ static void cmd_settingsreset(BaseSequentialStream* chp, int argc, char* argv[])
if (!nav) return;
nav->home(true); // to exit all running apps
for (const auto& entry : std::filesystem::directory_iterator(SETTINGS_DIR, u"*.ini")) {
for (const auto& entry : std::filesystem::directory_iterator(settings_dir, u"*.ini")) {
if (std::filesystem::is_regular_file(entry.status())) {
std::filesystem::path pth = SETTINGS_DIR;
std::filesystem::path pth = settings_dir;
pth += u"/" + entry.path();
chprintf(chp, pth.string().c_str());
chprintf(chp, "\r\n");
+1 -1
View File
@@ -52,7 +52,7 @@ void AudioBeepProcessor::on_signal_message(const RequestSignalMessage& message)
}
void AudioBeepProcessor::on_beep_message(const AudioBeepMessage& message) {
audio::dma::beep_start(message.freq, AUDIO_SAMPLE_RATE, message.duration_ms);
audio::dma::beep_start(message.freq, message.sample_rate, message.duration_ms);
}
int main() {
+21 -2
View File
@@ -21,7 +21,7 @@
*/
#include "proc_capture.hpp"
#include "audio_dma.hpp"
#include "dsp_fir_taps.hpp"
#include "event_m4.hpp"
#include "utility.hpp"
@@ -55,6 +55,16 @@ void CaptureProcessor::execute(const buffer_c8_t& buffer) {
}
}
void CaptureProcessor::on_signal_message(const RequestSignalMessage& message) {
if (message.signal == RequestSignalMessage::Signal::BeepStopRequest) {
audio::dma::beep_stop();
}
}
void CaptureProcessor::on_beep_message(const AudioBeepMessage& message) {
audio::dma::beep_start(message.freq, message.sample_rate, message.duration_ms);
}
void CaptureProcessor::on_message(const Message* const message) {
switch (message->id) {
case Message::ID::UpdateSpectrum:
@@ -70,6 +80,14 @@ void CaptureProcessor::on_message(const Message* const message) {
capture_config(*reinterpret_cast<const CaptureConfigMessage*>(message));
break;
case Message::ID::RequestSignal:
on_signal_message(*reinterpret_cast<const RequestSignalMessage*>(message));
break;
case Message::ID::AudioBeep:
on_beep_message(*reinterpret_cast<const AudioBeepMessage*>(message));
break;
default:
break;
}
@@ -152,7 +170,8 @@ void CaptureProcessor::capture_config(const CaptureConfigMessage& message) {
}
int main() {
audio::dma::init_audio_out();
EventDispatcher event_dispatcher{std::make_unique<CaptureProcessor>()};
event_dispatcher.run();
return 0;
}
}
+4
View File
@@ -30,6 +30,7 @@
#include "dsp_decimate.hpp"
#include "spectrum_collector.hpp"
#include "stream_input.hpp"
#include "message.hpp"
#include <array>
#include <memory>
@@ -92,6 +93,9 @@ class CaptureProcessor : public BasebandProcessor {
void on_message(const Message* const message) override;
private:
void on_signal_message(const RequestSignalMessage& message);
void on_beep_message(const AudioBeepMessage& message);
size_t baseband_fs = 3072000; // aka: sample_rate
static constexpr auto spectrum_rate_hz = 50.0f;
+2 -2
View File
@@ -86,12 +86,12 @@ void SondeProcessor::on_signal_message(const RequestSignalMessage& message) {
beep_duration = BEEP_DURATION_RANGE + BEEP_MIN_DURATION;
}
audio::dma::beep_start(beep_freq, AUDIO_SAMPLE_RATE, beep_duration);
audio::dma::beep_start(beep_freq, DEFAULT_AUDIO_SAMPLE_RATE, beep_duration);
}
}
void SondeProcessor::on_beep_message(const AudioBeepMessage& message) {
audio::dma::beep_start(message.freq, AUDIO_SAMPLE_RATE, message.duration_ms);
audio::dma::beep_start(message.freq, message.sample_rate, message.duration_ms);
}
void SondeProcessor::on_pitch_rssi_config(const PitchRSSIConfigureMessage& message) {
+1 -1
View File
@@ -103,7 +103,7 @@
#define RSSI_CEILING 1000
#define PROPORTIONAL_BEEP_THRES 0.8
#define RSSI_PITCH_WEIGHT (float(BEEP_MAX_FREQ - BEEP_BASE_FREQ) / RSSI_CEILING)
#define AUDIO_SAMPLE_RATE 24000
#define DEFAULT_AUDIO_SAMPLE_RATE 24000
class SondeProcessor : public BasebandProcessor {
public:
+23 -1
View File
@@ -60,7 +60,30 @@ void WidebandSpectrum::execute(const buffer_c8_t& buffer) {
}
}
void WidebandSpectrum::on_signal_message(const RequestSignalMessage& message) {
if (message.signal == RequestSignalMessage::Signal::BeepStopRequest) {
audio::dma::beep_stop();
}
}
void WidebandSpectrum::on_beep_message(const AudioBeepMessage& message) {
audio::dma::beep_start(message.freq, message.sample_rate, message.duration_ms);
}
void WidebandSpectrum::on_message(const Message* const msg) {
switch (msg->id) {
case Message::ID::RequestSignal:
on_signal_message(*reinterpret_cast<const RequestSignalMessage*>(msg));
return;
case Message::ID::AudioBeep:
on_beep_message(*reinterpret_cast<const AudioBeepMessage*>(msg));
return;
default:
break;
}
const WidebandSpectrumConfigMessage message = *reinterpret_cast<const WidebandSpectrumConfigMessage*>(msg);
switch (msg->id) {
@@ -84,7 +107,6 @@ void WidebandSpectrum::on_message(const Message* const msg) {
int main() {
audio::dma::init_audio_out(); // for AudioRX app (enables audio output while this baseband image is running)
EventDispatcher event_dispatcher{std::make_unique<WidebandSpectrum>()};
event_dispatcher.run();
return 0;
@@ -43,6 +43,9 @@ class WidebandSpectrum : public BasebandProcessor {
bool configured = false;
size_t baseband_fs = 20000000;
void on_beep_message(const AudioBeepMessage& message);
void on_signal_message(const RequestSignalMessage& message);
SpectrumCollector channel_spectrum{};
std::array<complex16_t, 256> spectrum{};
+6
View File
@@ -28,6 +28,12 @@
void ToneGen::configure_beep(const uint32_t freq, const uint32_t sample_rate) {
f_delta_ = (float)(freq * sizeof(sine_table_i8)) / sample_rate;
f_tone_phase_ = 0.0;
// For higher frequencies, start at sine peak to handle case of freq=sample_rate/2;
// we don't want to sample the sine wave only when it's crossing 0!
// There is still an amplitude issue though depending on magnitude of selected sine sample deltas.
if (f_delta_ >= sizeof(sine_table_i8) / 4)
f_tone_phase_ = sizeof(sine_table_i8) / 4;
}
int16_t ToneGen::process_beep() {
+4 -1
View File
@@ -134,7 +134,7 @@ class Message {
};
struct RSSIStatistics {
uint16_t accumulator{0};
uint32_t accumulator{0};
uint8_t min{0};
uint8_t max{0};
uint16_t count{0};
@@ -1368,12 +1368,15 @@ class AudioBeepMessage : public Message {
public:
constexpr AudioBeepMessage(
uint32_t freq = 1000,
uint32_t sample_rate = 24000,
uint32_t duration_ms = 100)
: Message{ID::AudioBeep},
freq{freq},
sample_rate{sample_rate},
duration_ms{duration_ms} {
}
uint32_t freq = 1000;
uint32_t sample_rate = 24000;
uint32_t duration_ms = 100;
};
#endif /*__MESSAGE_H__*/
@@ -37,6 +37,7 @@
#include "ui_flash_utility.hpp"
#include "utility.hpp"
#include "rtc_time.hpp"
#include "file_path.hpp"
#include <algorithm>
#include <string>
@@ -1105,14 +1106,14 @@ void set_menu_color(Color v) {
// PMem to sdcard settings
bool should_use_sdcard_for_pmem() {
return std::filesystem::file_exists(PMEM_FILEFLAG);
return std::filesystem::file_exists(settings_dir / PMEM_FILEFLAG);
}
int save_persistent_settings_to_file() {
File outfile;
ensure_directory(SETTINGS_DIR);
auto error = outfile.create(PMEM_SETTING_FILE);
ensure_directory(settings_dir);
auto error = outfile.create(settings_dir / PMEM_SETTING_FILE);
if (error)
return false;
@@ -1122,7 +1123,7 @@ int save_persistent_settings_to_file() {
int load_persistent_settings_from_file() {
File infile;
auto error = infile.open(PMEM_SETTING_FILE);
auto error = infile.open(settings_dir / PMEM_SETTING_FILE);
if (error)
return false;
@@ -37,10 +37,10 @@
#include "ui.hpp"
// persistent memory from/to sdcard flag file
#define PMEM_FILEFLAG u"/SETTINGS/PMEM_FILEFLAG"
#define PMEM_FILEFLAG u"PMEM_FILEFLAG"
// persistent memory from/to sdcard flag file
#define PMEM_SETTING_FILE u"/SETTINGS/pmem_settings"
#define PMEM_SETTING_FILE u"pmem_settings"
#define PMEM_SIZE_BYTES 256 // total amount of pmem space in bytes, including checksum
#define PMEM_SIZE_WORDS (PMEM_SIZE_BYTES / 4)
+1 -1
View File
@@ -523,7 +523,7 @@ class NewButton : public Widget {
protected:
virtual Style paint_style();
Color color_;
Color bg_color_{Color::light_grey()};
Color bg_color_{Color::grey()};
private:
std::string text_;
+6 -5
View File
@@ -1,5 +1,6 @@
f=460125000,d=CPDCW1 CH1
f=460175000,d=CPDCW2 CH2
f=460275000,d=CPDCW3 CH3
f=460325000,d=CPDCW4 CH4
f=460350000,d=CPDCW5 CH5
# Chicago Police City Wide Dispatch
f=460125000,d=Chicago PD CW1
f=460175000,d=Chicago PD CW2
f=460275000,d=Chicago PD CW3
f=460325000,d=Chicago PD CW4
f=460350000,d=Chicago PD CW5
+15
View File
@@ -0,0 +1,15 @@
# Common SSTV frequencies
# frequencies marked Active have more frequent transmissions.
f=3640000,d=SSTV 80M
f=7043000,d=SSTV 40M - Active
f=7170000,d=SSTV 40M - Active
f=10132000,d=SSTV 30M
f=14230000,d=SSTV 20M - Active
f=14233000,d=SSTV 20M - Active
f=14236000,d=SSTV 20M
f=14240000,d=SSTV 20M
f=21340000,d=SSTV 15M - Active
f=28680000,d=SSTV 10M - Active
f=50950000,d=SSTV 6M
f=145625000,d=SSTV 2M
f=433775000,d=SSTV 70CM
+25 -3
View File
@@ -5,13 +5,22 @@
# 433 MHz BAND
423,443,433 BAND
# AVIATION
108,137,AVIATION 108
108,118,AVIATION 108 NAVAIDS
118,137,AVIATION 118 VOICE
960,1215,AVIATION 960
1089,1091,ADS-B 1090
128,137,ACARS
# BROADCAST RADIO
87,108,FM BROADCAST
87,108,FM BROADCAST USA
76,108,FM BROADCAST BRAZIL
76,95,FM BROADCAST JAPAN
65,74,FM BROADCAST RUSSIA
# CITIZENS BAND RADIO
26,28,CITIZENS BAND RADIO
# COMMON PUBLIC SERVICE BANDS
150,160, PUBLIC SERVICE 155
450,470,PUBLIC SERVICE 460
769,775,PUBLIC SERVICE 770
# DECT
1879,1931,DECT
# FRS/GMRS
@@ -25,7 +34,12 @@
902,928,HAM 33-CM
1240,1300,HAM 23-CM
# KEYFOBS
260,500,315/433 MHz KEYFOBS
305,325,315 MHz KEYFOBS
380,400,390 MHz KEYFOBS
423,443,433 MHz KEYFOBS
858,878,868 MHz KEYFOBS
902,929,915 MHz KEYFOBS
# 260,500,315/433 MHz KEYFOBS
# LoRa
433,435,LoRa 443EU
863,870,LoRa 868EU
@@ -36,14 +50,22 @@
# MICS
140,380,MICS (VHF) AND MARINE
420,660,MICS (UHF)
169,172,MICS COMMON
# MULTI-USE RADIO SERVICE - MURS
151,155,MULTI-USE RADIO SRVS
# NOAA WEATHER RADIO
161,164,NOAA WEATHER RADIO
# PAGERS https://www.fcc.gov/wireless/bureau-divisions/mobility-division/paging
34,36,USA PAGERS 35
43,45,USA PAGERS 44
151,153,USA PAGERS 152
157,159,USA PAGERS 158
453,454,USA PAGERS 454
929,931,USA PAGERS 930
# RADIOSONDES
390,420,RADIOSONDES
# RAILROAD
159,162,RAILROAD
# WATER METERS
850,900,Water meters
902,928,ISM 900MHz