mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-08-22 15:39:04 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fcb681f4ae | |||
| 8530fa8194 | |||
| 89e8956df1 | |||
| 82ba35c162 | |||
| d750afe38f | |||
| 9b665a43c5 | |||
| 80c769b97d | |||
| 44dd8fd083 | |||
| 4e128e8930 |
@@ -114,6 +114,8 @@ ResultCode load_settings(const std::string& app_name, AppSettings& settings) {
|
||||
|
||||
if (flags_enabled(settings.mode, Mode::RX)) {
|
||||
read_setting(*data, setting::rx_frequency, settings.rx_frequency);
|
||||
read_setting(*data, setting::lna, settings.lna);
|
||||
read_setting(*data, setting::vga, settings.vga);
|
||||
read_setting(*data, setting::rx_amp, settings.rx_amp);
|
||||
read_setting(*data, setting::modulation, settings.modulation);
|
||||
read_setting(*data, setting::am_config_index, settings.am_config_index);
|
||||
@@ -124,8 +126,6 @@ ResultCode load_settings(const std::string& app_name, AppSettings& settings) {
|
||||
|
||||
read_setting(*data, setting::baseband_bandwidth, settings.baseband_bandwidth);
|
||||
read_setting(*data, setting::sampling_rate, settings.sampling_rate);
|
||||
read_setting(*data, setting::lna, settings.lna);
|
||||
read_setting(*data, setting::vga, settings.vga);
|
||||
read_setting(*data, setting::step, settings.step);
|
||||
read_setting(*data, setting::volume, settings.volume);
|
||||
|
||||
@@ -153,6 +153,8 @@ ResultCode save_settings(const std::string& app_name, AppSettings& settings) {
|
||||
|
||||
if (flags_enabled(settings.mode, Mode::RX)) {
|
||||
write_setting(settings_file, setting::rx_frequency, settings.rx_frequency);
|
||||
write_setting(settings_file, setting::lna, settings.lna);
|
||||
write_setting(settings_file, setting::vga, settings.vga);
|
||||
write_setting(settings_file, setting::rx_amp, settings.rx_amp);
|
||||
write_setting(settings_file, setting::modulation, settings.modulation);
|
||||
write_setting(settings_file, setting::am_config_index, settings.am_config_index);
|
||||
@@ -163,8 +165,6 @@ ResultCode save_settings(const std::string& app_name, AppSettings& settings) {
|
||||
|
||||
write_setting(settings_file, setting::baseband_bandwidth, settings.baseband_bandwidth);
|
||||
write_setting(settings_file, setting::sampling_rate, settings.sampling_rate);
|
||||
write_setting(settings_file, setting::lna, settings.lna);
|
||||
write_setting(settings_file, setting::vga, settings.vga);
|
||||
write_setting(settings_file, setting::step, settings.step);
|
||||
write_setting(settings_file, setting::volume, settings.volume);
|
||||
|
||||
@@ -173,6 +173,7 @@ ResultCode save_settings(const std::string& app_name, AppSettings& settings) {
|
||||
|
||||
void copy_to_radio_model(const AppSettings& settings) {
|
||||
// NB: Don't actually adjust the radio here or it will hang.
|
||||
// Specifically 'modulation' which requires a running baseband.
|
||||
|
||||
if (flags_enabled(settings.mode, Mode::TX)) {
|
||||
if (!flags_enabled(settings.options, Options::UseGlobalTargetFrequency))
|
||||
@@ -203,14 +204,10 @@ void copy_from_radio_model(AppSettings& settings) {
|
||||
if (flags_enabled(settings.mode, Mode::TX)) {
|
||||
settings.tx_frequency = transmitter_model.target_frequency();
|
||||
settings.baseband_bandwidth = transmitter_model.baseband_bandwidth();
|
||||
settings.sampling_rate = transmitter_model.sampling_rate();
|
||||
settings.tx_amp = transmitter_model.rf_amp();
|
||||
settings.tx_gain = transmitter_model.tx_gain();
|
||||
settings.channel_bandwidth = transmitter_model.channel_bandwidth();
|
||||
|
||||
// TODO: Do these make sense for TX?
|
||||
settings.sampling_rate = transmitter_model.sampling_rate();
|
||||
settings.lna = transmitter_model.lna();
|
||||
settings.vga = transmitter_model.vga();
|
||||
}
|
||||
|
||||
if (flags_enabled(settings.mode, Mode::RX)) {
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
#include "string_format.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include "debug.hpp"
|
||||
|
||||
using namespace portapack;
|
||||
using namespace tonekey;
|
||||
|
||||
@@ -135,8 +133,7 @@ SPECOptionsView::SPECOptionsView(
|
||||
AnalogAudioView::AnalogAudioView(
|
||||
NavigationView& nav)
|
||||
: nav_(nav) {
|
||||
// A baseband image _must_ be running before
|
||||
// interacting with the waterfall view.
|
||||
// A baseband image _must_ be running before add waterfall view.
|
||||
baseband::run_image(portapack::spi_flash::image_tag_wideband_spectrum);
|
||||
|
||||
add_children({&rssi,
|
||||
@@ -194,6 +191,15 @@ AnalogAudioView::AnalogAudioView(
|
||||
on_modulation_changed(modulation);
|
||||
}
|
||||
|
||||
AnalogAudioView::AnalogAudioView(
|
||||
NavigationView& nav,
|
||||
ReceiverModel::settings_t override)
|
||||
: AnalogAudioView(nav) {
|
||||
// TODO: Which other settings make sense to override?
|
||||
on_frequency_step_changed(override.frequency_step);
|
||||
options_modulation.set_by_value(toUType(override.mode));
|
||||
}
|
||||
|
||||
size_t AnalogAudioView::get_spec_bw_index() {
|
||||
return spec_bw_index;
|
||||
}
|
||||
@@ -404,11 +410,7 @@ void AnalogAudioView::update_modulation(ReceiverModel::Mode modulation) {
|
||||
}
|
||||
|
||||
void AnalogAudioView::handle_coded_squelch(uint32_t value) {
|
||||
tone_index idx = tone_key_index_by_value(value);
|
||||
if (idx >= 0)
|
||||
text_ctcss.set("CTCSS " + tone_key_string(idx));
|
||||
else
|
||||
text_ctcss.set("???");
|
||||
text_ctcss.set(tone_key_string_by_value(value, text_ctcss.parent_rect().width() / 8));
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -71,10 +71,10 @@ class NBFMOptionsView : public View {
|
||||
}};
|
||||
|
||||
Text text_squelch{
|
||||
{9 * 8, 0 * 16, 8 * 8, 1 * 16},
|
||||
{7 * 8, 0 * 16, 8 * 8, 1 * 16},
|
||||
"SQ /99"};
|
||||
NumberField field_squelch{
|
||||
{12 * 8, 0 * 16},
|
||||
{10 * 8, 0 * 16},
|
||||
2,
|
||||
{0, 99},
|
||||
1,
|
||||
@@ -138,6 +138,7 @@ class SPECOptionsView : public View {
|
||||
class AnalogAudioView : public View {
|
||||
public:
|
||||
AnalogAudioView(NavigationView& nav);
|
||||
AnalogAudioView(NavigationView& nav, ReceiverModel::settings_t override);
|
||||
~AnalogAudioView();
|
||||
|
||||
void set_parent_rect(Rect new_parent_rect) override;
|
||||
@@ -200,7 +201,7 @@ class AnalogAudioView : public View {
|
||||
{28 * 8, 0 * 16}};
|
||||
|
||||
Text text_ctcss{
|
||||
{19 * 8, 1 * 16, 11 * 8, 1 * 16},
|
||||
{16 * 8, 1 * 16, 14 * 8, 1 * 16},
|
||||
""};
|
||||
|
||||
std::unique_ptr<Widget> options_widget{};
|
||||
|
||||
@@ -71,8 +71,6 @@ CaptureAppView::CaptureAppView(NavigationView& nav)
|
||||
};
|
||||
|
||||
option_bandwidth.set_selected_index(7); // Preselected default option 500kHz.
|
||||
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::Capture);
|
||||
receiver_model.enable();
|
||||
|
||||
record_view.on_error = [&nav](std::string message) {
|
||||
@@ -81,8 +79,6 @@ CaptureAppView::CaptureAppView(NavigationView& nav)
|
||||
}
|
||||
|
||||
CaptureAppView::~CaptureAppView() {
|
||||
// Most other apps can't handle "Capture" mode, set to something standard.
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::WidebandFMAudio);
|
||||
receiver_model.disable();
|
||||
baseband::shutdown();
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ class CaptureAppView : public View {
|
||||
static constexpr ui::Dim header_height = 3 * 16;
|
||||
|
||||
NavigationView& nav_;
|
||||
RxRadioState radio_state_{};
|
||||
RxRadioState radio_state_{ReceiverModel::Mode::Capture};
|
||||
app_settings::SettingsManager settings_{
|
||||
"rx_capture", app_settings::Mode::RX,
|
||||
app_settings::Options::UseGlobalTargetFrequency};
|
||||
|
||||
@@ -130,8 +130,7 @@ class ERTAppView : public View {
|
||||
|
||||
RxRadioState radio_state_{
|
||||
2500000 /* bandwidth */,
|
||||
4194304 /* sampling rate */
|
||||
};
|
||||
4194304 /* sampling rate */};
|
||||
app_settings::SettingsManager settings_{
|
||||
"rx_ert", app_settings::Mode::RX};
|
||||
|
||||
|
||||
@@ -71,7 +71,6 @@ POCSAGAppView::POCSAGAppView(NavigationView& nav)
|
||||
if (!settings_.loaded())
|
||||
field_frequency.set_value(initial_target_frequency);
|
||||
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::NarrowbandFMAudio);
|
||||
receiver_model.enable();
|
||||
|
||||
// TODO: app setting instead?
|
||||
|
||||
@@ -106,8 +106,7 @@ class TPMSAppView : public View {
|
||||
|
||||
RxRadioState radio_state_{
|
||||
1750000 /* bandwidth */,
|
||||
2457600 /* sampling rate */
|
||||
};
|
||||
2457600 /* sampling rate */};
|
||||
app_settings::SettingsManager settings_{
|
||||
"rx_tpms", app_settings::Mode::RX};
|
||||
|
||||
|
||||
@@ -513,8 +513,7 @@ ADSBRxView::ADSBRxView(NavigationView& nav) {
|
||||
|
||||
baseband::set_adsb();
|
||||
|
||||
receiver_model.set_target_frequency(1090000000);
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::SpectrumAnalysis);
|
||||
receiver_model.set_target_frequency(1'090'000'000);
|
||||
receiver_model.enable();
|
||||
}
|
||||
|
||||
|
||||
@@ -343,8 +343,8 @@ class ADSBRxView : public View {
|
||||
private:
|
||||
RxRadioState radio_state_{
|
||||
2500000 /* bandwidth */,
|
||||
2000000 /* sampling rate */
|
||||
};
|
||||
2000000 /* sampling rate */,
|
||||
ReceiverModel::Mode::SpectrumAnalysis};
|
||||
app_settings::SettingsManager settings_{
|
||||
"rx_adsb", app_settings::Mode::RX};
|
||||
|
||||
|
||||
@@ -91,7 +91,6 @@ AFSKRxView::AFSKRxView(NavigationView& nav)
|
||||
audio::set_rate(audio::Rate::Hz_24000);
|
||||
audio::output::start();
|
||||
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::NarrowbandFMAudio);
|
||||
receiver_model.enable();
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,6 @@ APRSRxView::APRSRxView(NavigationView& nav, Rect parent_rect)
|
||||
audio::set_rate(audio::Rate::Hz_24000);
|
||||
audio::output::start();
|
||||
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::NarrowbandFMAudio);
|
||||
receiver_model.enable();
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,6 @@ BTLERxView::BTLERxView(NavigationView& nav)
|
||||
audio::set_rate(audio::Rate::Hz_24000);
|
||||
audio::output::start();
|
||||
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::WidebandFMAudio);
|
||||
receiver_model.enable();
|
||||
}
|
||||
|
||||
|
||||
@@ -51,8 +51,8 @@ class BTLERxView : public View {
|
||||
NavigationView& nav_;
|
||||
RxRadioState radio_state_{
|
||||
4000000 /* bandwidth */,
|
||||
4000000 /* sampling rate */
|
||||
};
|
||||
4000000 /* sampling rate */,
|
||||
ReceiverModel::Mode::WidebandFMAudio};
|
||||
app_settings::SettingsManager settings_{
|
||||
"rx_btle", app_settings::Mode::RX};
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ static const fs::path txt_ext{u".TXT"};
|
||||
static const fs::path ppl_ext{u".PPL"};
|
||||
static const fs::path c16_ext{u".C16"};
|
||||
static const fs::path png_ext{u".PNG"};
|
||||
static const fs::path bmp_ext{u".BMP"};
|
||||
} // namespace ui
|
||||
|
||||
namespace {
|
||||
@@ -503,6 +504,10 @@ bool FileManagerView::handle_file_open() {
|
||||
} else if (path_iequal(png_ext, ext)) {
|
||||
nav_.push<ScreenshotViewer>(path);
|
||||
return true;
|
||||
} else if (path_iequal(bmp_ext, ext)) {
|
||||
nav_.push<SplashViewer>(path);
|
||||
reload_current();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -216,23 +216,10 @@ size_t LevelView::change_mode(freqman_index_t new_mod) {
|
||||
}
|
||||
|
||||
void LevelView::handle_coded_squelch(const uint32_t value) {
|
||||
static tone_index last_squelch_index = -1;
|
||||
|
||||
if (field_mode.selected_index() == NFM_MODULATION) {
|
||||
tone_index idx = tone_key_index_by_value(value);
|
||||
|
||||
if ((last_squelch_index < 0) || (last_squelch_index != idx)) {
|
||||
last_squelch_index = idx;
|
||||
if (idx >= 0) {
|
||||
text_ctcss.set("T: " + tone_key_string(idx));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
text_ctcss.set(" ");
|
||||
if (field_mode.selected_index() == NFM_MODULATION)
|
||||
text_ctcss.set(tone_key_string_by_value(value, text_ctcss.parent_rect().width() / 8));
|
||||
else
|
||||
text_ctcss.set(" ");
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -114,7 +114,7 @@ class LevelView : public View {
|
||||
}};
|
||||
|
||||
Text text_ctcss{
|
||||
{22 * 8, 3 * 16 + 4, 14 * 8, 1 * 8},
|
||||
{22 * 8, 3 * 16 + 4, 8 * 8, 1 * 8},
|
||||
""};
|
||||
|
||||
// RSSI: XX/XX/XXX,dt: XX
|
||||
|
||||
@@ -471,9 +471,9 @@ GlassView::GlassView(
|
||||
|
||||
button_marker.on_select = [this](ButtonWithEncoder&) {
|
||||
receiver_model.set_target_frequency(marker); // Center tune rx in marker freq.
|
||||
receiver_model.set_frequency_step(MHZ_DIV); // Preset a 1 MHz frequency step into RX -> AUDIO
|
||||
nav_.pop();
|
||||
nav_.push<AnalogAudioView>(); // Jump into audio view
|
||||
auto settings = receiver_model.settings();
|
||||
settings.frequency_step = MHZ_DIV; // Preset a 1 MHz frequency step into RX -> AUDIO
|
||||
nav_.replace<AnalogAudioView>(settings); // Jump into audio view
|
||||
};
|
||||
|
||||
field_trigger.on_change = [this](int32_t v) {
|
||||
@@ -495,9 +495,9 @@ GlassView::GlassView(
|
||||
|
||||
button_jump.on_select = [this](Button&) {
|
||||
receiver_model.set_target_frequency(max_freq_hold); // Center tune rx in marker freq.
|
||||
receiver_model.set_frequency_step(MHZ_DIV); // Preset a 1 MHz frequency step into RX -> AUDIO
|
||||
nav_.pop();
|
||||
nav_.push<AnalogAudioView>(); // Jump into audio view
|
||||
auto settings = receiver_model.settings();
|
||||
settings.frequency_step = MHZ_DIV; // Preset a 1 MHz frequency step into RX -> AUDIO
|
||||
nav_.replace<AnalogAudioView>(settings); // Jump into audio view
|
||||
};
|
||||
|
||||
button_rst.on_select = [this](Button&) {
|
||||
@@ -513,7 +513,6 @@ GlassView::GlassView(
|
||||
marker_pixel_index = 120;
|
||||
on_range_changed();
|
||||
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::SpectrumAnalysis);
|
||||
receiver_model.set_sampling_rate(looking_glass_sampling_rate); // 20mhz
|
||||
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);
|
||||
|
||||
@@ -71,7 +71,7 @@ class GlassView : public View {
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
RxRadioState radio_state_{};
|
||||
RxRadioState radio_state_{ReceiverModel::Mode::SpectrumAnalysis};
|
||||
app_settings::SettingsManager settings_{
|
||||
"rx_glass", app_settings::Mode::RX};
|
||||
|
||||
|
||||
@@ -145,25 +145,25 @@ void MicTXView::rxaudio(bool is_on) {
|
||||
audio::input::stop();
|
||||
baseband::shutdown();
|
||||
|
||||
if (enable_am || enable_usb || enable_lsb || enable_dsb) { // "NFM/FM",0 ," WFM ",1 , " AM ",2, " USB ", 3, " LSB ",4, " DSB-SC", 5
|
||||
if (enable_am || enable_usb || enable_lsb || enable_dsb) { // "NFM/FM", 0, " WFM ", 1, " AM ", 2, " USB ", 3, " LSB ", 4, " DSB-SC", 5
|
||||
baseband::run_image(portapack::spi_flash::image_tag_am_audio);
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::AMAudio); // that AM demodulation engine is common to all Amplitude mod : AM/USB/LSB/DSB (2,3,4,5)
|
||||
if (options_mode.selected_index() < 5) // We will be called here with 2,3,4,5 . We treat here demod. filter 2,3,4; (excluding DSB-C case (5) it is treated more down).
|
||||
receiver_model.set_am_configuration(options_mode.selected_index() - 1); // selecting proper filter(2,3,4). 2-1=1=>6k-AM(1) , 3-1=2=>+3k-USB(2), 4-1=3=>-3K-LSB(3),
|
||||
} else { // We are in NFM/FM or WFM (NFM BW:8k5 or 11k / FM BW 16k / WFM BW:200k)
|
||||
if (options_mode.selected_index() < 5) // We will be called here with 2,3,4,5. We treat here demod. filter 2,3,4; (excluding DSB-C case (5) it is treated more down).
|
||||
receiver_model.set_am_configuration(options_mode.selected_index() - 1); // selecting proper filter(2,3,4). 2-1=1=>6k-AM(1), 3-1=2=>+3k-USB(2), 4-1=3=>-3K-LSB(3),
|
||||
} else { // We are in NFM/FM or WFM (NFM BW:8k5 or 11k / FM BW 16k / WFM BW:200k)
|
||||
|
||||
if (enable_wfm) { // WFM , BW 200Khz aprox , or the two new addional BW filters (180k, 40k)
|
||||
if (enable_wfm) { // WFM, BW 200Khz aprox, or the two new addional BW filters (180k, 40k)
|
||||
baseband::run_image(portapack::spi_flash::image_tag_wfm_audio);
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::WidebandFMAudio);
|
||||
// receiver_model.set_wfm_configuration(n); // it is called above , depending user's selection (200k, 180k,40k).
|
||||
} else { // NFM BW:8k5 or 11k / FM BW 16k
|
||||
// receiver_model.set_wfm_configuration(n); // it is called above, depending user's selection (200k, 180k, 0k).
|
||||
} else { // NFM BW:8k5 or 11k / FM BW 16k
|
||||
baseband::run_image(portapack::spi_flash::image_tag_nfm_audio);
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::NarrowbandFMAudio); //
|
||||
// receiver_model.set_nbfm_configuration(n); is called above , depending user's selection (8k5, 11k, 16k).
|
||||
// receiver_model.set_nbfm_configuration(n); is called above, depending user's selection (8k5, 11k, 16k).
|
||||
}
|
||||
}
|
||||
|
||||
if (bool_same_F_tx_rx_enabled) // when stop TX ,define to which freq RX we return
|
||||
if (bool_same_F_tx_rx_enabled) // when stop TX, define to which freq RX we return
|
||||
receiver_model.set_target_frequency(tx_frequency); // Update freq also for RX = TX
|
||||
else
|
||||
receiver_model.set_target_frequency(rx_frequency); // Now with separate freq controls!
|
||||
@@ -196,7 +196,7 @@ MicTXView::MicTXView(
|
||||
baseband::run_image(portapack::spi_flash::image_tag_mic_tx);
|
||||
|
||||
if (audio::debug::codec_name() == "WM8731") {
|
||||
add_children({&labels_WM8731, // we have audio codec WM8731, same MIC menu as original.
|
||||
add_children({&labels_WM8731, // we have audio codec WM8731, same MIC menu as original.
|
||||
&vumeter,
|
||||
&options_gain, // MIC GAIN float factor on the GUI.
|
||||
&options_wm8731_boost_mode,
|
||||
@@ -260,7 +260,7 @@ MicTXView::MicTXView(
|
||||
mic_gain = v / 10.0;
|
||||
configure_baseband();
|
||||
};
|
||||
options_gain.set_selected_index(1); // x1.0 preselected default.
|
||||
options_gain.set_selected_index(1); // x1.0 preselected default.
|
||||
|
||||
if (audio::debug::codec_name() == "WM8731") {
|
||||
options_wm8731_boost_mode.on_change = [this](size_t, int8_t v) {
|
||||
@@ -268,30 +268,30 @@ MicTXView::MicTXView(
|
||||
case 0: // +12 dB’s respect reference level orig fw 1.5.x fw FM : when +20dB's boost ON) and shift bits (>>8),
|
||||
shift_bits_s16 = 6; // now mic-boost on (+20dBs) and shift bits (>>6), +20+12=32 dB’s (orig fw +20 dBs+ 0dBs)=> +12dB's respect ref.
|
||||
break;
|
||||
case 1: // +06 dB’s reference level , (when +20dB's boost ON)
|
||||
case 1: // +06 dB’s reference level, (when +20dB's boost ON)
|
||||
shift_bits_s16 = 7; // now mic-boost on (+20dBs) and shift bits (>>7), +20+06=26 dB’s (orig fw +20 dBs+ 0dBs) => +06dB's respect ref.
|
||||
break;
|
||||
case 2:
|
||||
shift_bits_s16 = 4; // +04 dB’s respect ref level , (when +20dB's boost OFF)
|
||||
shift_bits_s16 = 4; // +04 dB’s respect ref level, (when +20dB's boost OFF)
|
||||
break; // now mic-boost off (+00dBs) shift bits (4) (+0+24dB's)=24 dBs => +04dB's respect ref.
|
||||
case 3:
|
||||
shift_bits_s16 = 5; // -02 dB’s respect ref level , (when +20dB's boost OFF)
|
||||
shift_bits_s16 = 5; // -02 dB’s respect ref level, (when +20dB's boost OFF)
|
||||
break; // now mic-boost off (+00dBs) shift bits (5) (+0+18dB's)=18 dBs => -02dB's respect ref.
|
||||
case 4:
|
||||
shift_bits_s16 = 6; // -08 dB’s respect ref level , (when +20dB's boost OFF)
|
||||
shift_bits_s16 = 6; // -08 dB’s respect ref level, (when +20dB's boost OFF)
|
||||
break; // now mic-boost off (+00dBs) shift bits (6) (+0+12dB's)=12 dBs => -08dB's respect ref.
|
||||
}
|
||||
ak4951_alc_and_wm8731_boost_GUI = v; // 0,..4 WM8731_boost dB's options, (combination boost on/off , and effective gain in captured data >>x)
|
||||
audio::input::start(ak4951_alc_and_wm8731_boost_GUI); // Detected (WM8731) , set up the proper wm_boost on/off , 0..4 (0,1) boost_on , (2,3,4) boost_0ff
|
||||
configure_baseband(); // to update in real time, sending msg , var-parameters >>shift_bits FM msg ,to audio_tx from M0 to M4 Proc -
|
||||
ak4951_alc_and_wm8731_boost_GUI = v; // 0..4, WM8731_boost dB's options, (combination boost on/off, and effective gain in captured data >>x)
|
||||
audio::input::start(ak4951_alc_and_wm8731_boost_GUI); // Detected (WM8731), set up the proper wm_boost on/off, 0..4 (0,1) boost_on, (2,3,4) boost_off
|
||||
configure_baseband(); // to update in real time, sending msg, var-parameters >>shift_bits FM msg, to audio_tx from M0 to M4 Proc -
|
||||
};
|
||||
options_wm8731_boost_mode.set_selected_index(3); // preset GUI index 3 as default WM -> -02 dB's .
|
||||
options_wm8731_boost_mode.set_selected_index(3); // preset GUI index 3 as default WM -> -02 dB's.
|
||||
} else {
|
||||
shift_bits_s16 = 8; // Initialized default fixed >>8_FM for FM tx mod , shift audio data for AK4951 ,using top 8 bits s16 data (>>8)
|
||||
shift_bits_s16 = 8; // Initialized default fixed >>8_FM for FM tx mod, shift audio data for AK4951, using top 8 bits s16 data (>>8)
|
||||
options_ak4951_alc_mode.on_change = [this](size_t, int8_t v) {
|
||||
ak4951_alc_and_wm8731_boost_GUI = v; // 0,..11, AK4951 Mic -Automatic volume Level Control options,
|
||||
ak4951_alc_and_wm8731_boost_GUI = v; // 0..11, AK4951 Mic -Automatic volume Level Control options,
|
||||
audio::input::start(ak4951_alc_and_wm8731_boost_GUI); // Detected (AK4951) ==> Set up proper ALC mode from 0..11 options
|
||||
configure_baseband(); // sending fixed >>8_FM , var-parameters msg , to audiotx from this M0 to M4 process.
|
||||
configure_baseband(); // sending fixed >>8_FM, var-parameters msg, to audiotx from this M0 to M4 process.
|
||||
};
|
||||
}
|
||||
|
||||
@@ -329,11 +329,11 @@ MicTXView::MicTXView(
|
||||
field_bw.on_change = [this](uint32_t v) {
|
||||
transmitter_model.set_channel_bandwidth(v * 1000);
|
||||
};
|
||||
field_bw.set_value(10); // pre-default first time, TX deviation FM for NFM / FM
|
||||
field_bw.set_value(10); // pre-default first time, TX deviation FM for NFM / FM
|
||||
|
||||
// now , no need direct update , field_rfgain , field_rfamp (it is done in ui_transmitter.cpp)
|
||||
// now, no need direct update, field_rfgain, field_rfamp (it is done in ui_transmitter.cpp)
|
||||
|
||||
options_mode.on_change = [this](size_t, int32_t v) { //{ "NFM/FM", 0 }, { " WFM ", 1 },{ "AM", 2 },{ "USB", 3 },{ "LSB", 4 },{ "DSB", 5 }
|
||||
options_mode.on_change = [this](size_t, int32_t v) { // { "NFM/FM", 0 }, { " WFM ", 1 }, { "AM", 2 }, { "USB", 3 }, { "LSB", 4 }, { "DSB", 5 }
|
||||
enable_am = false;
|
||||
enable_usb = false;
|
||||
enable_lsb = false;
|
||||
@@ -342,7 +342,7 @@ MicTXView::MicTXView(
|
||||
|
||||
using option_t = std::pair<std::string, int32_t>;
|
||||
using options_t = std::vector<option_t>;
|
||||
options_t rxbw; // Aux structure to change dynamically field_rxbw contents,
|
||||
options_t rxbw; // Aux structure to change dynamically field_rxbw contents,
|
||||
|
||||
switch (v) {
|
||||
case 0: //{ "FM", 0 }
|
||||
@@ -354,15 +354,15 @@ MicTXView::MicTXView(
|
||||
// field_bw.set_value(transmitter_model.channel_bandwidth() / 1000);
|
||||
// if (rx_enabled)
|
||||
rxaudio(rx_enabled); // Update now if we have RX audio on
|
||||
options_tone_key.hidden(0); // we are in FM mode , we should have active the Key-tones & CTCSS option.
|
||||
options_tone_key.hidden(0); // we are in FM mode, we should have active the Key-tones & CTCSS option.
|
||||
|
||||
rxbw.emplace_back(" NFM1:8k5 ", 0); // restore the original dynamic field_rxbw value.
|
||||
rxbw.emplace_back(" NFM2:11k ", 1);
|
||||
rxbw.emplace_back(" FM :16k ", 2);
|
||||
field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw.
|
||||
|
||||
field_rxbw.hidden(0); // we are in FM mode, we need to allow the user set up of the RX NFM BW selection (8K5, 11K, 16K)
|
||||
field_bw.hidden(0); // we are in FM mode, we need to allow FM deviation parameter , in non FM mode.
|
||||
field_rxbw.hidden(0); // we are in FM mode, we need to allow the user set up of the RX NFM BW selection (8K5, 11K, 16K)
|
||||
field_bw.hidden(0); // we are in FM mode, we need to allow FM deviation parameter, in non FM mode.
|
||||
break;
|
||||
case 1: //{ "WFM", 1 }
|
||||
enable_am = false;
|
||||
@@ -374,38 +374,38 @@ MicTXView::MicTXView(
|
||||
// field_bw.set_value(transmitter_model.channel_bandwidth() / 1000);
|
||||
// if (rx_enabled)
|
||||
rxaudio(rx_enabled); // Update now if we have RX audio on
|
||||
options_tone_key.hidden(0); // we are in WFM mode , we should have active the Key-tones & CTCSS option.
|
||||
options_tone_key.hidden(0); // we are in WFM mode, we should have active the Key-tones & CTCSS option.
|
||||
|
||||
rxbw.emplace_back(" 200k-WFM ", 0); // We allow the user selection of the 3 x WFM BW filters, (0) WFM-200K, (1) WFM-180K , (2) WFM-40K .
|
||||
rxbw.emplace_back(" 200k-WFM ", 0); // We allow the user selection of the 3 x WFM BW filters, (0) WFM-200K, (1) WFM-180K, (2) WFM-40K.
|
||||
rxbw.emplace_back(" 180k-WFM ", 1);
|
||||
rxbw.emplace_back(" 40k-WFM ", 2);
|
||||
field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw.
|
||||
|
||||
field_rxbw.hidden(0); // we are in WFM mode, we need to show to the user the selected BW WFM filter .
|
||||
field_bw.hidden(0); // we are in WFM mode, we need to allow WFM deviation parameter , in non FM mode.
|
||||
field_rxbw.hidden(0); // we are in WFM mode, we need to show to the user the selected BW WFM filter.
|
||||
field_bw.hidden(0); // we are in WFM mode, we need to allow WFM deviation parameter, in non FM mode.
|
||||
break;
|
||||
case 2: //{ "AM", 2 }
|
||||
enable_am = true;
|
||||
rxaudio(rx_enabled); // Update now if we have RX audio on
|
||||
options_tone_key.set_selected_index(0); // we are NOT in FM mode , we reset the possible previous key-tones &CTCSS selection.
|
||||
options_tone_key.set_selected_index(0); // we are NOT in FM mode, we reset the possible previous key-tones &CTCSS selection.
|
||||
set_dirty(); // Refresh display
|
||||
options_tone_key.hidden(1); // we hide that Key-tones & CTCSS input selecction, (no meaning in AM/DSB/SSB).
|
||||
|
||||
rxbw.emplace_back(" DSB1-9k ", 0); // we offer in AM DSB two audio BW 9k / 6k .
|
||||
rxbw.emplace_back(" DSB1-9k ", 0); // we offer in AM DSB two audio BW 9k / 6k.
|
||||
rxbw.emplace_back(" DSB2-6k ", 1);
|
||||
field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw.
|
||||
|
||||
field_rxbw.hidden(0); // we show fixed RX AM BW 6Khz
|
||||
field_bw.hidden(1); // we hide the FM TX deviation parameter , in non FM mode.
|
||||
field_rxbw.hidden(0); // we show fixed RX AM BW 6Khz
|
||||
field_bw.hidden(1); // we hide the FM TX deviation parameter, in non FM mode.
|
||||
check_rogerbeep.hidden(0); // make visible again the "rogerbeep" selection.
|
||||
break;
|
||||
case 3: //{ "USB", 3 }
|
||||
enable_usb = true;
|
||||
rxaudio(rx_enabled); // Update now if we have RX audio on
|
||||
check_rogerbeep.set_value(false); // reset the possible activation of roger beep, because it is not compatible with SSB , by now.
|
||||
check_rogerbeep.set_value(false); // reset the possible activation of roger beep, because it is not compatible with SSB, by now.
|
||||
check_rogerbeep.hidden(1); // hide that roger beep selection.
|
||||
|
||||
rxbw.emplace_back(" USB+3k ", 0); // locked a fixed option , to display it .
|
||||
rxbw.emplace_back(" USB+3k ", 0); // locked a fixed option, to display it.
|
||||
field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw.
|
||||
|
||||
set_dirty(); // Refresh display
|
||||
@@ -413,10 +413,10 @@ MicTXView::MicTXView(
|
||||
case 4: //{ "LSB", 4 }
|
||||
enable_lsb = true;
|
||||
rxaudio(rx_enabled); // Update now if we have RX audio on
|
||||
check_rogerbeep.set_value(false); // reset the possible activation of roger beep, because it is not compatible with SSB , by now.
|
||||
check_rogerbeep.set_value(false); // reset the possible activation of roger beep, because it is not compatible with SSB, by now.
|
||||
check_rogerbeep.hidden(1); // hide that roger beep selection.
|
||||
|
||||
rxbw.emplace_back(" LSB-3k ", 0); // locked a fixed option , to display it .
|
||||
rxbw.emplace_back(" LSB-3k ", 0); // locked a fixed option, to display it.
|
||||
field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw.
|
||||
|
||||
set_dirty(); // Refresh display
|
||||
@@ -426,7 +426,7 @@ MicTXView::MicTXView(
|
||||
rxaudio(rx_enabled); // Update now if we have RX audio on
|
||||
check_rogerbeep.hidden(0); // make visible again the "rogerbeep" selection.
|
||||
|
||||
rxbw.emplace_back("SSB1:USB+3k", 0); // added dynamically two options (index 0,1) to that DSB-C case to the field_rxbw value.
|
||||
rxbw.emplace_back("SSB1:USB+3k", 0); // added dynamically two options (index 0,1) to that DSB-C case to the field_rxbw value.
|
||||
rxbw.emplace_back("SSB2:LSB-3k", 1);
|
||||
|
||||
field_rxbw.set_options(rxbw); // store that aux GUI option to the field_rxbw.
|
||||
@@ -479,7 +479,7 @@ MicTXView::MicTXView(
|
||||
|
||||
check_common_freq_tx_rx.on_select = [this](Checkbox&, bool v) {
|
||||
bool_same_F_tx_rx_enabled = v;
|
||||
field_rxfrequency.hidden(v); // Hide or show separated freq RX field . (When no hide user can enter down indep. freq for RX)
|
||||
field_rxfrequency.hidden(v); // Hide or show separated freq RX field. (When no hide user can enter down indep. freq for RX)
|
||||
set_dirty(); // Refresh GUI interface
|
||||
receiver_model.set_target_frequency(v ? tx_frequency : rx_frequency); // To go to the proper tuned freq. when toggling it
|
||||
};
|
||||
@@ -510,17 +510,17 @@ MicTXView::MicTXView(
|
||||
|
||||
field_rxbw.on_change = [this](size_t, int32_t v) {
|
||||
if (!(enable_am || enable_usb || enable_lsb || enable_dsb || enable_wfm)) {
|
||||
// In Previous fw versions, that nbfm_configuration(n) was done in any mode (FM/AM/SSB/DSB)...strictly speaking only need it in (NFM/FM)
|
||||
receiver_model.set_nbfm_configuration(v); // we are in NFM/FM case, we need to select proper NFM/FM RX channel filter , NFM BW 8K5(0), NFM BW 11K(1) , FM BW 16K (2)
|
||||
} else { // we are not in NFM/FM mode .(we could be in any of the rest : AM /USB/LSB/DSB-SC)
|
||||
if (enable_am) { // we are in AM TX mode , we will allow both independent RX audio BW : AM 9K (9K00AE3 / AM 6K (6K00AE3). (In AM option v can be 0 (9k) , 1 (6k)
|
||||
receiver_model.set_am_configuration(v); // we are in AM TX mode , we need to select proper AM full path config AM-9K filter. 0+0 =>AM-9K(0), 0+1=1 =>AM-6K(1),
|
||||
// In Previous fw versions, that nbfm_configuration(n) was done in any mode (FM/AM/SSB/DSB)...strictly speaking only need it in (NFM/FM)
|
||||
receiver_model.set_nbfm_configuration(v); // we are in NFM/FM case, we need to select proper NFM/FM RX channel filter, NFM BW 8K5(0), NFM BW 11K(1), FM BW 16K (2)
|
||||
} else { // we are not in NFM/FM mode. (we could be in any of the rest : AM /USB/LSB/DSB-SC)
|
||||
if (enable_am) { // we are in AM TX mode, we will allow both independent RX audio BW : AM 9K (9K00AE3 / AM 6K (6K00AE3). (In AM option v can be 0 (9k), 1 (6k)
|
||||
receiver_model.set_am_configuration(v); // we are in AM TX mode, we need to select proper AM full path config AM-9K filter. 0+0 =>AM-9K(0), 0+1=1 =>AM-6K(1),
|
||||
}
|
||||
if (enable_dsb) { // we are in DSB-SC in TX mode , we will allow both independent RX SSB demodulation (USB / LSB side band). in that submenu, v is 0 (SSB1 USB) or 1 (SSB2 LSB)
|
||||
receiver_model.set_am_configuration(v + 2); // we are in DSB-SC TX mode , we need to select proper SSB filter. 0+2 =>usb(2), 1+2=3 =>lsb(3),
|
||||
if (enable_dsb) { // we are in DSB-SC in TX mode, we will allow both independent RX SSB demodulation (USB / LSB side band). in that submenu, v is 0 (SSB1 USB) or 1 (SSB2 LSB)
|
||||
receiver_model.set_am_configuration(v + 2); // we are in DSB-SC TX mode, we need to select proper SSB filter. 0+2 =>usb(2), 1+2=3 =>lsb(3),
|
||||
}
|
||||
if (enable_wfm) {
|
||||
receiver_model.set_wfm_configuration(v); // we are in WFM case, we need to select proper WFB RX BW filter , WFM BW 200K(0), WFM BW 180K(1) , WFM BW 40K(2)
|
||||
receiver_model.set_wfm_configuration(v); // we are in WFM case, we need to select proper WFB RX BW filter, WFM BW 200K(0), WFM BW 180K(1), WFM BW 40K(2)
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -607,6 +607,36 @@ MicTXView::MicTXView(
|
||||
audio::input::start(ak4951_alc_and_wm8731_boost_GUI); // When detected AK4951 => set up ALC mode; when detected WM8731 => set up mic_boost ON/OFF.
|
||||
}
|
||||
|
||||
MicTXView::MicTXView(
|
||||
NavigationView& nav,
|
||||
ReceiverModel::settings_t override)
|
||||
: MicTXView(nav) {
|
||||
// Try to use the modulation/bandwidth from RX settings.
|
||||
// TODO: These concepts should be merged so there's only one.
|
||||
// TODO: enums/constants for these indexes.
|
||||
switch (override.mode) {
|
||||
case ReceiverModel::Mode::AMAudio:
|
||||
options_mode.set_selected_index(2);
|
||||
break;
|
||||
case ReceiverModel::Mode::NarrowbandFMAudio:
|
||||
options_mode.set_selected_index(0);
|
||||
break;
|
||||
case ReceiverModel::Mode::WidebandFMAudio:
|
||||
options_mode.set_selected_index(1);
|
||||
break;
|
||||
|
||||
// Unsupported modulations.
|
||||
case ReceiverModel::Mode::SpectrumAnalysis:
|
||||
case ReceiverModel::Mode::Capture:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: bandwidth selection is tied too tightly to the UI
|
||||
// controls. It's not possible to set the bandwidth here without
|
||||
// refactoring. Also options_mode seems to have a category error.
|
||||
}
|
||||
|
||||
MicTXView::~MicTXView() {
|
||||
audio::input::stop();
|
||||
transmitter_model.set_target_frequency(tx_frequency); // Save Tx frequency instead of Rx. Or maybe we need some "System Wide" changes to seperate Tx and Rx frequency.
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
// TODO: Consolidate Modulation/Bandwidth modes/settings with freqman/receiver_model.
|
||||
|
||||
#ifndef __UI_MICTX_H__
|
||||
#define __UI_MICTX_H__
|
||||
|
||||
@@ -43,6 +45,7 @@ namespace ui {
|
||||
class MicTXView : public View {
|
||||
public:
|
||||
MicTXView(NavigationView& nav);
|
||||
MicTXView(NavigationView& nav, ReceiverModel::settings_t override);
|
||||
~MicTXView();
|
||||
|
||||
MicTXView(const MicTXView&) = delete;
|
||||
@@ -117,18 +120,19 @@ class MicTXView : public View {
|
||||
uint8_t shift_bits_s16{4}; // shift bits factor to the captured ADC S16 audio sample.
|
||||
|
||||
// AM TX Stuff
|
||||
// TODO: Some of this stuff is mutually exclusive. Need a better representation.
|
||||
bool enable_am{false};
|
||||
bool enable_dsb{false};
|
||||
bool enable_usb{false};
|
||||
bool enable_lsb{false};
|
||||
bool enable_wfm{false}; // added to distinguish in the FM mode , RX BW : NFM (8K5, 11K), FM (16K), WFM(200K)
|
||||
bool enable_wfm{false}; // added to distinguish in the FM mode, RX BW : NFM (8K5, 11K), FM (16K), WFM(200K)
|
||||
|
||||
Labels labels_WM8731{
|
||||
{{3 * 8, 1 * 8}, "MIC-GAIN:", Color::light_grey()},
|
||||
{{17 * 8, 1 * 8}, "Boost", Color::light_grey()},
|
||||
{{3 * 8, 3 * 8}, "F:", Color::light_grey()},
|
||||
{{15 * 8, 3 * 8}, "FM TXBW: kHz", Color::light_grey()}, // to be more symetric and consistent to the below FM RXBW
|
||||
{{18 * 8, (5 * 8)}, "Mode:", Color::light_grey()}, // now , no need to handle GAIN , Amp here It is handled by ui_transmitter.cpp
|
||||
{{18 * 8, (5 * 8)}, "Mode:", Color::light_grey()}, // now, no need to handle GAIN, Amp here It is handled by ui_transmitter.cpp
|
||||
{{3 * 8, 8 * 8}, "TX Activation:", Color::light_grey()}, // we delete { { 3 * 8, 5 * 8 }, "GAIN:", Color::light_grey() },
|
||||
{{4 * 8, 10 * 8}, "LVL:", Color::light_grey()}, // we delete { {11 * 8, 5 * 8 }, "Amp:", Color::light_grey() },
|
||||
{{12 * 8, 10 * 8}, "ATT:", Color::light_grey()},
|
||||
@@ -147,7 +151,7 @@ class MicTXView : public View {
|
||||
{{17 * 8, 1 * 8}, "ALC", Color::light_grey()},
|
||||
{{3 * 8, 3 * 8}, "F:", Color::light_grey()},
|
||||
{{15 * 8, 3 * 8}, "FM TXBW: kHz", Color::light_grey()},
|
||||
{{18 * 8, (5 * 8)}, "Mode:", Color::light_grey()}, // now , no need to handle GAIN , Amp here It is handled by ui_transmitter.cpp
|
||||
{{18 * 8, (5 * 8)}, "Mode:", Color::light_grey()}, // now, no need to handle GAIN, Amp here It is handled by ui_transmitter.cpp
|
||||
{{3 * 8, 8 * 8}, "TX Activation:", Color::light_grey()}, // we delete { { 3 * 8, 5 * 8 }, "GAIN:", Color::light_grey() },
|
||||
{{4 * 8, 10 * 8}, "LVL:", Color::light_grey()}, // we delete { {11 * 8, 5 * 8 }, "Amp:", Color::light_grey() },
|
||||
{{12 * 8, 10 * 8}, "ATT:", Color::light_grey()},
|
||||
@@ -176,15 +180,15 @@ class MicTXView : public View {
|
||||
{"x2.0", 20}}};
|
||||
|
||||
OptionsField options_ak4951_alc_mode{
|
||||
{20 * 8, 1 * 8}, // Coordinates are: int:x (px), int:y (px)
|
||||
{20 * 8, 1 * 8},
|
||||
11,
|
||||
{
|
||||
{" OFF-12kHz", 0}, // Nothing changed from ORIGINAL,keeping ALL programmable AK4951 Digital Block->OFF, sampling 24Khz)
|
||||
{" OFF-12kHz", 0}, // Nothing changed from ORIGINAL, keeping ALL programmable AK4951 Digital Block->OFF, sampling 24Khz)
|
||||
{"+12dB-6kHz", 1}, // ALC-> on, (+12dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
|
||||
{"+09dB-6kHz", 2}, // ALC-> on, (+09dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
|
||||
{"+06dB-6kHz", 3}, // ALC-> on, (+06dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
|
||||
{"+03dB-2kHz", 4}, // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + LPF 3,5k + Pre-amp Mic (+21dB=original)+ EQ boosting ~<2kHz (f0~1k1,fb:1,7K, k=1,8)
|
||||
{"+03dB-4kHz", 5}, // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + LPF 4kHz + Pre-amp Mic (+21dB=original)+ EQ boosting ~<3kHz (f0~1k4,fb~2,4k, k=1,8)
|
||||
{"+03dB-2kHz", 4}, // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + LPF 3,5k + Pre-amp Mic (+21dB=original)+ EQ boosting ~<2kHz (f0~1k1, fb:1,7K, k=1,8)
|
||||
{"+03dB-4kHz", 5}, // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + LPF 4kHz + Pre-amp Mic (+21dB=original)+ EQ boosting ~<3kHz (f0~1k4, fb~2,4k, k=1,8)
|
||||
{"+03dB-6kHz", 6}, // ALC-> on, (+03dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
|
||||
{"+00dB-6kHz", 7}, // ALC-> on, (+00dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
|
||||
{"-03dB-6kHz", 8}, // ALC-> on, (-03dB's) Auto Vol max + Wind Noise cancel + LPF 6kHz + Pre-amp Mic (+21dB=original)
|
||||
@@ -194,14 +198,14 @@ class MicTXView : public View {
|
||||
}};
|
||||
|
||||
OptionsField options_wm8731_boost_mode{
|
||||
{22 * 8, 1 * 8}, // Coordinates are: int:x (px), int:y (px)
|
||||
{22 * 8, 1 * 8},
|
||||
5,
|
||||
{
|
||||
{"ON +12dB", 0}, // WM8731 Mic Boost ON ,original+12dBs condition, easy to saturate ADC sat in high voice ,relative G = +12 dB's respect ref level
|
||||
{"ON +06dB", 1}, // WM8731 Mic Boost ON ,original+6 dBs condition, easy to saturate ADC sat in high voice ,relative G = +06 dB's respect ref level
|
||||
{"OFF+04dB", 2}, // WM8731 Mic Boost OFF to avoid ADC sat in high voice ,relative G = +04 dB's (respect ref level) , always effective sampling 24khz
|
||||
{"OFF-02dB", 3}, // WM8731 Mic Boost OFF to avoid ADC sat in high voice ,relative G = -02 dB's (respect ref level)
|
||||
{"OFF-08dB", 4}, // WM8731 Mic Boost OFF to avoid ADC sat in high voice ,relative G = -12 dB's (respect ref level)
|
||||
{"ON +12dB", 0}, // WM8731 Mic Boost ON, original+12dBs condition, easy to saturate ADC sat in high voice, relative G = +12 dB's respect ref level
|
||||
{"ON +06dB", 1}, // WM8731 Mic Boost ON, original+6 dBs condition, easy to saturate ADC sat in high voice, relative G = +06 dB's respect ref level
|
||||
{"OFF+04dB", 2}, // WM8731 Mic Boost OFF to avoid ADC sat in high voice, relative G = +04 dB's (respect ref level), always effective sampling 24khz
|
||||
{"OFF-02dB", 3}, // WM8731 Mic Boost OFF to avoid ADC sat in high voice, relative G = -02 dB's (respect ref level)
|
||||
{"OFF-08dB", 4}, // WM8731 Mic Boost OFF to avoid ADC sat in high voice, relative G = -12 dB's (respect ref level)
|
||||
}};
|
||||
|
||||
// TODO: Use TxFrequencyField
|
||||
@@ -227,7 +231,7 @@ class MicTXView : public View {
|
||||
{
|
||||
{"NFM/FM", 0},
|
||||
{" WFM ", 1},
|
||||
{" AM ", 2}, // in fact that TX mode = AM -DSB with carrier .
|
||||
{" AM ", 2}, // in fact that TX mode = AM -DSB with carrier.
|
||||
{" USB ", 3},
|
||||
{" LSB ", 4},
|
||||
{"DSB-SC", 5} // We are TX Double Side AM Band with suppressed carrier, and allowing in RX both indep SSB lateral band (USB/LSB).
|
||||
@@ -269,7 +273,7 @@ class MicTXView : public View {
|
||||
|
||||
OptionsField options_tone_key{
|
||||
{12 * 8, (13 * 8) - 5},
|
||||
23,
|
||||
18,
|
||||
{}};
|
||||
|
||||
Checkbox check_rogerbeep{
|
||||
|
||||
@@ -76,7 +76,6 @@ NRFRxView::NRFRxView(NavigationView& nav)
|
||||
audio::set_rate(audio::Rate::Hz_24000);
|
||||
audio::output::start();
|
||||
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::WidebandFMAudio);
|
||||
receiver_model.enable();
|
||||
}
|
||||
|
||||
|
||||
@@ -51,8 +51,8 @@ class NRFRxView : public View {
|
||||
NavigationView& nav_;
|
||||
RxRadioState radio_state_{
|
||||
4000000 /* bandwidth */,
|
||||
4000000 /* sampling rate */
|
||||
};
|
||||
4000000 /* sampling rate */,
|
||||
ReceiverModel::Mode::WidebandFMAudio};
|
||||
app_settings::SettingsManager settings_{
|
||||
"rx_nrf", app_settings::Mode::RX};
|
||||
|
||||
|
||||
@@ -80,8 +80,7 @@ bool POCSAGTXView::start_tx() {
|
||||
progressbar.set_max(total_frames);
|
||||
|
||||
transmitter_model.set_rf_amp(true);
|
||||
transmitter_model.set_lna(40);
|
||||
transmitter_model.set_vga(40);
|
||||
transmitter_model.set_tx_gain(40);
|
||||
transmitter_model.enable();
|
||||
|
||||
uint8_t* data_ptr = shared_memory.bb_data.data;
|
||||
|
||||
@@ -366,7 +366,6 @@ ReconView::~ReconView() {
|
||||
recon_save_config_to_sd();
|
||||
if (field_mode.selected_index_value() != SPEC_MODULATION)
|
||||
audio::output::stop();
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::WidebandFMAudio);
|
||||
receiver_model.disable();
|
||||
baseband::shutdown();
|
||||
}
|
||||
@@ -549,8 +548,9 @@ ReconView::ReconView(NavigationView& nav)
|
||||
};
|
||||
|
||||
button_audio_app.on_select = [this](Button&) {
|
||||
nav_.pop();
|
||||
nav_.push<AnalogAudioView>();
|
||||
auto settings = receiver_model.settings();
|
||||
settings.frequency_step = step_mode.selected_index_value();
|
||||
nav_.replace<AnalogAudioView>(settings);
|
||||
};
|
||||
|
||||
button_loop_config.on_select = [this](Button&) {
|
||||
@@ -569,9 +569,9 @@ ReconView::ReconView(NavigationView& nav)
|
||||
button_mic_app.on_select = [this](Button&) {
|
||||
if (frequency_list.size() > 0 && current_index >= 0 && (unsigned)current_index < frequency_list.size()) {
|
||||
if (frequency_list[current_index].type == HAMRADIO) {
|
||||
// if it's a HAMRADIO entry, then frequency_a is the freq at which the repeater reveive, so we have to set it in transmit in mic app
|
||||
// if it's a HAMRADIO entry, then frequency_a is the freq at which the repeater receives, so we have to set it in transmit in mic app
|
||||
transmitter_model.set_target_frequency(frequency_list[current_index].frequency_a);
|
||||
// if it's a HAMRADIO entry, then frequency_b is the freq at which the repeater transmit, so we have to set it in receive in mic app
|
||||
// if it's a HAMRADIO entry, then frequency_b is the freq at which the repeater transmits, so we have to set it in receive in mic app
|
||||
receiver_model.set_target_frequency(frequency_list[current_index].frequency_b);
|
||||
} else {
|
||||
// it's single or range so we us actual tuned frequency
|
||||
@@ -579,9 +579,9 @@ ReconView::ReconView(NavigationView& nav)
|
||||
receiver_model.set_target_frequency(freq);
|
||||
}
|
||||
}
|
||||
// there is no way yet to set modulation and bandwidth from Recon to MicApp
|
||||
nav_.pop();
|
||||
nav_.push<MicTXView>();
|
||||
|
||||
// MicTX wants Modulation and Bandwidth overrides, but that's only stored on the RX model.
|
||||
nav_.replace<MicTXView>(receiver_model.settings());
|
||||
};
|
||||
|
||||
button_remove.on_select = [this](ButtonWithEncoder&) {
|
||||
@@ -731,7 +731,7 @@ ReconView::ReconView(NavigationView& nav)
|
||||
text_cycle.set_text("1");
|
||||
text_max.set("/1");
|
||||
button_scanner_mode.set_style(&Styles::white);
|
||||
button_scanner_mode.set_text("MSEARCH");
|
||||
button_scanner_mode.set_text("MANUAL");
|
||||
file_name.set_style(&Styles::white);
|
||||
file_name.set("MANUAL RANGE RECON");
|
||||
desc_cycle.set_style(&Styles::white);
|
||||
@@ -776,7 +776,7 @@ ReconView::ReconView(NavigationView& nav)
|
||||
if (scanner_mode) {
|
||||
file_name.set_style(&Styles::red);
|
||||
button_scanner_mode.set_style(&Styles::red);
|
||||
button_scanner_mode.set_text("SCANNER");
|
||||
button_scanner_mode.set_text("SCAN");
|
||||
} else {
|
||||
file_name.set_style(&Styles::blue);
|
||||
button_scanner_mode.set_style(&Styles::blue);
|
||||
@@ -808,7 +808,7 @@ ReconView::ReconView(NavigationView& nav)
|
||||
} else {
|
||||
scanner_mode = true;
|
||||
button_scanner_mode.set_style(&Styles::red);
|
||||
button_scanner_mode.set_text("SCANNER");
|
||||
button_scanner_mode.set_text("SCAN");
|
||||
button_scanner_mode.set_text("REMOVE");
|
||||
}
|
||||
frequency_file_load(true);
|
||||
@@ -930,7 +930,7 @@ void ReconView::frequency_file_load(bool stop_all_before) {
|
||||
file_name.set_style(&Styles::red);
|
||||
button_scanner_mode.set_style(&Styles::red);
|
||||
desc_cycle.set_style(&Styles::red);
|
||||
button_scanner_mode.set_text("SCANNER");
|
||||
button_scanner_mode.set_text("SCAN");
|
||||
} else {
|
||||
file_name.set_style(&Styles::blue);
|
||||
button_scanner_mode.set_style(&Styles::blue);
|
||||
@@ -1024,12 +1024,23 @@ void ReconView::frequency_file_load(bool stop_all_before) {
|
||||
|
||||
void ReconView::on_statistics_update(const ChannelStatistics& statistics) {
|
||||
systime_t time_interval = 100;
|
||||
uint32_t local_recon_lock_duration = recon_lock_duration;
|
||||
|
||||
chrono_end = chTimeNow();
|
||||
if (field_mode.selected_index_value() == SPEC_MODULATION) {
|
||||
chrono_end = chTimeNow();
|
||||
time_interval = chrono_end - chrono_start;
|
||||
chrono_start = chrono_end;
|
||||
// capping here to avoid double check a frequency because time_interval is more than exactly 100 by a few units
|
||||
// this is because we are making a measurement and not using a fixed value
|
||||
if (time_interval > 100)
|
||||
time_interval = 100;
|
||||
if (field_lock_wait.value() == 0) {
|
||||
if (time_interval <= 1) // capping here to avoid freeze because too quick
|
||||
local_recon_lock_duration = 2; // minimum working tested value
|
||||
else
|
||||
local_recon_lock_duration = time_interval;
|
||||
}
|
||||
}
|
||||
chrono_start = chrono_end;
|
||||
|
||||
// hack to reload the list if it was cleared by going into CONFIG
|
||||
if (freqlist_cleared_for_ui_action) {
|
||||
@@ -1049,7 +1060,7 @@ void ReconView::on_statistics_update(const ChannelStatistics& statistics) {
|
||||
status = 0;
|
||||
continuous_lock = false;
|
||||
freq_lock = 0;
|
||||
timer = recon_lock_duration;
|
||||
timer = local_recon_lock_duration;
|
||||
big_display.set_style(&Styles::white);
|
||||
}
|
||||
if (freq_lock < recon_lock_nb_match) // LOCKING
|
||||
@@ -1409,8 +1420,13 @@ size_t ReconView::change_mode(freqman_index_t new_mod) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (new_mod != SPEC_MODULATION)
|
||||
if (new_mod != SPEC_MODULATION) {
|
||||
record_view->set_sampling_rate(recording_sampling_rate);
|
||||
// reset receiver model to fix bug when going from SPEC to audio, the sound is distorded
|
||||
receiver_model.set_sampling_rate(3072000);
|
||||
receiver_model.set_baseband_bandwidth(1750000);
|
||||
}
|
||||
|
||||
field_mode.set_selected_index(new_mod);
|
||||
field_mode.on_change = [this](size_t, OptionsField::value_t v) {
|
||||
if (v != -1) {
|
||||
@@ -1426,20 +1442,10 @@ size_t ReconView::change_mode(freqman_index_t new_mod) {
|
||||
}
|
||||
|
||||
void ReconView::handle_coded_squelch(const uint32_t value) {
|
||||
if (field_mode.selected_index() == NFM_MODULATION) {
|
||||
tone_index idx = tone_key_index_by_value(value);
|
||||
|
||||
if ((last_squelch_index < 0) || (last_squelch_index != idx)) {
|
||||
last_squelch_index = idx;
|
||||
if (idx >= 0) {
|
||||
text_ctcss.set("T: " + tone_key_string(idx));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
text_ctcss.set(" ");
|
||||
if (field_mode.selected_index() == NFM_MODULATION)
|
||||
text_ctcss.set(tone_key_string_by_value(value, text_ctcss.parent_rect().width() / 8));
|
||||
else
|
||||
text_ctcss.set(" ");
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
@@ -139,7 +139,6 @@ class ReconView : public View {
|
||||
int8_t last_rssi_med{-127};
|
||||
int8_t last_rssi_max{-127};
|
||||
int32_t last_index{-1};
|
||||
tone_index last_squelch_index{-1};
|
||||
int64_t last_freq{0};
|
||||
std::string freq_file_path{};
|
||||
systime_t chrono_start{};
|
||||
@@ -270,7 +269,7 @@ class ReconView : public View {
|
||||
NumberField field_lock_wait{
|
||||
{25 * 8, 24 * 8 + 4},
|
||||
4,
|
||||
{RECON_MIN_LOCK_DURATION, RECON_MAX_LOCK_DURATION},
|
||||
{0, RECON_MAX_LOCK_DURATION},
|
||||
STATS_UPDATE_INTERVAL,
|
||||
' ',
|
||||
};
|
||||
|
||||
@@ -135,7 +135,7 @@ class ReconSetupViewMore : public View {
|
||||
Checkbox checkbox_auto_record_locked{
|
||||
{1 * 8, 132},
|
||||
3,
|
||||
"auto record locked periods"};
|
||||
"record locked periods"};
|
||||
};
|
||||
|
||||
class ReconSetupView : public View {
|
||||
|
||||
@@ -392,16 +392,17 @@ ScannerView::ScannerView(
|
||||
button_audio_app.on_select = [this](Button&) {
|
||||
if (scan_thread)
|
||||
scan_thread->stop();
|
||||
nav_.pop();
|
||||
nav_.push<AnalogAudioView>();
|
||||
auto settings = receiver_model.settings();
|
||||
settings.frequency_step = field_step.selected_index_value();
|
||||
nav_.replace<AnalogAudioView>(settings);
|
||||
};
|
||||
|
||||
// Button to switch to Mic app
|
||||
button_mic_app.on_select = [this](Button&) {
|
||||
if (scan_thread)
|
||||
scan_thread->stop();
|
||||
nav_.pop();
|
||||
nav_.push<MicTXView>();
|
||||
// MicTX wants Modulation and Bandwidth overrides, but that's only stored on the RX model.
|
||||
nav_.replace<MicTXView>(receiver_model.settings());
|
||||
};
|
||||
|
||||
// Button to delete current frequency from scan Freq List
|
||||
|
||||
@@ -122,17 +122,7 @@ void SearchView::do_detection() {
|
||||
locked = true;
|
||||
locked_bin = bin_max;
|
||||
|
||||
// TODO
|
||||
/*nav_.pop();
|
||||
receiver_model.disable();
|
||||
baseband::shutdown();
|
||||
nav_.pop();*/
|
||||
|
||||
/*if (options_goto.selected_index() == 1)
|
||||
nav_.push<AnalogAudioView>(false);
|
||||
else if (options_goto.selected_index() == 2)
|
||||
nav_.push<POCSAGAppView>();
|
||||
*/
|
||||
// TODO: open Audio.
|
||||
} else
|
||||
text_infos.set("Out of range");
|
||||
}
|
||||
@@ -414,7 +404,6 @@ SearchView::SearchView(
|
||||
|
||||
on_range_changed();
|
||||
|
||||
receiver_model.set_modulation(ReceiverModel::Mode::SpectrumAnalysis);
|
||||
receiver_model.enable();
|
||||
}
|
||||
|
||||
|
||||
@@ -92,8 +92,8 @@ class SearchView : public View {
|
||||
NavigationView& nav_;
|
||||
RxRadioState radio_state_{
|
||||
2500000 /* bandwidth */,
|
||||
SEARCH_SLICE_WIDTH /* sampling rate */
|
||||
};
|
||||
SEARCH_SLICE_WIDTH /* sampling rate */,
|
||||
ReceiverModel::Mode::SpectrumAnalysis};
|
||||
|
||||
struct slice_t {
|
||||
rf::Frequency center_frequency;
|
||||
|
||||
@@ -35,6 +35,9 @@ using namespace lpc43xx;
|
||||
#include "portapack.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
#include "file.hpp"
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
#include "string_format.hpp"
|
||||
#include "ui_styles.hpp"
|
||||
#include "cpld_update.hpp"
|
||||
@@ -489,35 +492,30 @@ SetPersistentMemoryView::SetPersistentMemoryView(NavigationView& nav) {
|
||||
check_use_sdcard_for_pmem.set_value(pmem::should_use_sdcard_for_pmem());
|
||||
check_use_sdcard_for_pmem.on_select = [this](Checkbox&, bool v) {
|
||||
File pmem_flag_file_handle;
|
||||
std::string pmem_flag_file = PMEM_FILEFLAG;
|
||||
if (v) {
|
||||
auto result = pmem_flag_file_handle.open(pmem_flag_file);
|
||||
if (result.is_valid()) {
|
||||
auto result = pmem_flag_file_handle.create(pmem_flag_file); // third: create if it is not there
|
||||
if (!result.is_valid()) {
|
||||
text_pmem_status.set("pmem flag file created");
|
||||
} else {
|
||||
text_pmem_status.set("!err. creating pmem flagfile!");
|
||||
}
|
||||
} else {
|
||||
if (fs::file_exists(PMEM_FILEFLAG)) {
|
||||
text_pmem_status.set("pmem flag already present");
|
||||
} else {
|
||||
auto error = pmem_flag_file_handle.create(PMEM_FILEFLAG);
|
||||
if (error)
|
||||
text_pmem_status.set("!err. creating pmem flagfile!");
|
||||
else
|
||||
text_pmem_status.set("pmem flag file created");
|
||||
}
|
||||
} else {
|
||||
auto result = delete_file(pmem_flag_file);
|
||||
if (result.code() != FR_OK) {
|
||||
auto result = delete_file(PMEM_FILEFLAG);
|
||||
if (result.code() != FR_OK)
|
||||
text_pmem_status.set("!err. deleting pmem flagfile!");
|
||||
} else {
|
||||
else
|
||||
text_pmem_status.set("pmem flag file deleted");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
button_save_mem_to_file.on_select = [&nav, this](Button&) {
|
||||
if (!pmem::save_persistent_settings_to_file()) {
|
||||
if (!pmem::save_persistent_settings_to_file())
|
||||
text_pmem_status.set("!problem saving settings!");
|
||||
} else {
|
||||
else
|
||||
text_pmem_status.set("settings saved");
|
||||
}
|
||||
};
|
||||
|
||||
button_load_mem_from_file.on_select = [&nav, this](Button&) {
|
||||
|
||||
@@ -26,6 +26,8 @@ namespace fs = std::filesystem;
|
||||
|
||||
namespace ui {
|
||||
|
||||
const std::filesystem::path splash_dot_bmp{u"/splash.bmp"};
|
||||
|
||||
ScreenshotViewer::ScreenshotViewer(
|
||||
NavigationView& nav,
|
||||
const std::filesystem::path& path)
|
||||
@@ -40,11 +42,9 @@ bool ScreenshotViewer::on_key(KeyEvent) {
|
||||
}
|
||||
|
||||
void ScreenshotViewer::paint(Painter& painter) {
|
||||
constexpr size_t pixel_width = 240;
|
||||
constexpr size_t pixel_height = 320;
|
||||
File file{};
|
||||
|
||||
painter.fill_rectangle({0, 0, pixel_width, pixel_height}, Color::black());
|
||||
painter.fill_rectangle({0, 0, screen_width, screen_height}, Color::black());
|
||||
|
||||
auto show_invalid = [&]() {
|
||||
painter.draw_string({10, 160}, Styles::white, "Not a valid screenshot.");
|
||||
@@ -65,19 +65,19 @@ void ScreenshotViewer::paint(Painter& painter) {
|
||||
constexpr size_t read_chunk = 80; // NB: must be a factor of pixel_width.
|
||||
constexpr size_t buffer_size = sizeof(ColorRGB888) * read_chunk;
|
||||
uint8_t buffer[buffer_size];
|
||||
std::array<Color, pixel_width> pixel_data;
|
||||
std::array<Color, screen_width> pixel_data;
|
||||
|
||||
// Seek past all the headers.
|
||||
file.seek(43);
|
||||
|
||||
for (auto line = 0u; line < pixel_height; ++line) {
|
||||
for (auto line = 0u; line < screen_height; ++line) {
|
||||
// Seek past the per-line header.
|
||||
file.seek(file.tell() + 6);
|
||||
|
||||
// Per comment in PNGWriter, read in chunks of 80.
|
||||
// NB: Reading in one large chunk caused corruption so there's
|
||||
// likely a bug lurking in the SD Card/FatFs layer.
|
||||
for (auto offset = 0u; offset < pixel_width; offset += read_chunk) {
|
||||
for (auto offset = 0u; offset < screen_width; offset += read_chunk) {
|
||||
auto read = file.read(buffer, buffer_size);
|
||||
|
||||
if (!read || *read != buffer_size) {
|
||||
@@ -92,8 +92,42 @@ void ScreenshotViewer::paint(Painter& painter) {
|
||||
}
|
||||
}
|
||||
|
||||
display.draw_pixels({0, (int)line, pixel_width, 1}, pixel_data);
|
||||
display.draw_pixels({0, (int)line, screen_width, 1}, pixel_data);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
SplashViewer::SplashViewer(
|
||||
NavigationView& nav,
|
||||
const std::filesystem::path& path)
|
||||
: nav_{nav},
|
||||
path_{path} {
|
||||
valid_image = false;
|
||||
set_focusable(true);
|
||||
}
|
||||
|
||||
bool SplashViewer::on_key(const KeyEvent key) {
|
||||
if (valid_image && key == KeyEvent::Right) {
|
||||
delete_file(splash_dot_bmp);
|
||||
copy_file(path_, splash_dot_bmp);
|
||||
}
|
||||
|
||||
nav_.pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SplashViewer::paint(Painter& painter) {
|
||||
painter.fill_rectangle({0, 0, screen_width, screen_height}, Color::black());
|
||||
|
||||
if (!portapack::display.drawBMP2({0, 0}, path_)) {
|
||||
painter.draw_string({10, 160}, Styles::white, "Not a valid splash image.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Show option to set splash screen if it's not already the splash screen
|
||||
if (!path_iequal(path_, splash_dot_bmp)) {
|
||||
painter.draw_string({0, 0}, Styles::white, "*RIGHT BUTTON UPDATES SPLASH*");
|
||||
valid_image = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
|
||||
namespace ui {
|
||||
|
||||
extern const std::filesystem::path splash_dot_bmp;
|
||||
|
||||
class ScreenshotViewer : public View {
|
||||
public:
|
||||
ScreenshotViewer(NavigationView& nav, const std::filesystem::path& path);
|
||||
@@ -42,6 +44,19 @@ class ScreenshotViewer : public View {
|
||||
std::filesystem::path path_{};
|
||||
};
|
||||
|
||||
class SplashViewer : public View {
|
||||
public:
|
||||
SplashViewer(NavigationView& nav, const std::filesystem::path& path);
|
||||
bool on_key(KeyEvent key) override;
|
||||
void paint(Painter& painter) override;
|
||||
void update_ss(void);
|
||||
|
||||
private:
|
||||
NavigationView& nav_;
|
||||
std::filesystem::path path_{};
|
||||
bool valid_image{};
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
|
||||
#endif // __UI_SS_VIEWER_H__
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
using option_t = std::pair<std::string, int32_t>;
|
||||
using options_t = std::vector<option_t>;
|
||||
|
||||
// TODO: Consolidate with receiver_model.
|
||||
// These definitions are spread all over and stiched together with indices.
|
||||
options_t freqman_entry_modulations = {
|
||||
{"AM", 0},
|
||||
{"NFM", 1},
|
||||
@@ -122,6 +124,8 @@ bool load_freqman_file(std::string& file_stem, freqman_db& db, bool load_freqs,
|
||||
freqman_index_t bandwidth = -1;
|
||||
freqman_index_t step = -1;
|
||||
freqman_index_t tone = -1;
|
||||
uint32_t tone_freq;
|
||||
char c;
|
||||
|
||||
auto result = freqman_file.open("FREQMAN/" + file_stem + ".TXT");
|
||||
if (result.is_valid())
|
||||
@@ -210,12 +214,26 @@ bool load_freqman_file(std::string& file_stem, freqman_db& db, bool load_freqs,
|
||||
step = freqman_entry_get_step_from_str_short(pos);
|
||||
}
|
||||
// ctcss tone if any
|
||||
/* disabled until better form
|
||||
pos = strstr(line_start, "c=");
|
||||
if (pos) {
|
||||
pos += 2;
|
||||
tone = tone_key_index_by_value( strtoll( pos , nullptr , 10 ) );
|
||||
} */
|
||||
pos = strstr(line_start, "c=");
|
||||
if (pos) {
|
||||
pos += 2;
|
||||
// find decimal point and replace with 0 if there is one, for strtoll
|
||||
length = strcspn(pos, ".,\x0A");
|
||||
if (pos + length <= line_end) {
|
||||
c = *(pos + length);
|
||||
*(pos + length) = 0;
|
||||
// ASCII Hz to integer Hz x 100
|
||||
tone_freq = strtoll(pos, nullptr, 10) * 100;
|
||||
// stuff saved character back into string in case it was not a decimal point
|
||||
*(pos + length) = c;
|
||||
// now get first digit after decimal point (10ths of Hz)
|
||||
pos += length + 1;
|
||||
if (c == '.' && *pos >= '0' && *pos <= '9')
|
||||
tone_freq += (*pos - '0') * 10;
|
||||
// convert tone_freq (100x the freq in Hz) to a tone_key index
|
||||
tone = tone_key_index_by_value(tone_freq);
|
||||
}
|
||||
}
|
||||
// Read description until , or LF
|
||||
pos = strstr(line_start, "d=");
|
||||
if (pos) {
|
||||
@@ -284,7 +302,7 @@ bool get_freq_string(freqman_entry& entry, std::string& item_string) {
|
||||
item_string = "r=" + to_string_dec_uint(frequency_a / 1000) + to_string_dec_uint(frequency_a % 1000UL, 3, '0');
|
||||
item_string += ",t=" + to_string_dec_uint(frequency_b / 1000) + to_string_dec_uint(frequency_b % 1000UL, 3, '0');
|
||||
if (entry.tone >= 0) {
|
||||
item_string += ",c=" + tone_key_string(entry.tone);
|
||||
item_string += ",c=" + tone_key_value_string(entry.tone);
|
||||
}
|
||||
}
|
||||
if (entry.modulation >= 0 && (unsigned)entry.modulation < freqman_entry_modulations.size()) {
|
||||
|
||||
@@ -28,38 +28,47 @@
|
||||
#include "receiver_model.hpp"
|
||||
#include "transmitter_model.hpp"
|
||||
|
||||
/* Stashes current radio bandwidth and sampling rate.
|
||||
* Inits to defaults, and restores previous when destroyed.
|
||||
* The idea here is that an app will eventually call enable
|
||||
* on the model which will sync all of the model state into
|
||||
* the radio. We tried lazily setting these using the
|
||||
* set_configuration_without_update function, but there are
|
||||
* still various UI components (mainly Waterfall) that need
|
||||
* the radio set in order to load properly.
|
||||
/* Reinitialized model with defaults so each app can start
|
||||
* with a clean, default model instance. We tried lazily
|
||||
* setting these using the set_configuration_without_update
|
||||
* function, but there are still various UI components
|
||||
* (e.g. Waterfall) that need the radio set in order to load.
|
||||
* NB: This member must be added before SettingsManager. */
|
||||
template <typename TModel, TModel* model>
|
||||
class RadioState {
|
||||
public:
|
||||
RadioState()
|
||||
: RadioState(max2837::filter::bandwidth_minimum, 3072000) {
|
||||
RadioState() {
|
||||
model->initialize();
|
||||
}
|
||||
|
||||
RadioState(uint32_t new_bandwidth, uint32_t new_sampling_rate)
|
||||
: prev_bandwidth_{model->baseband_bandwidth()},
|
||||
prev_sampling_rate_{model->sampling_rate()} {
|
||||
// Update the new settings in the radio.
|
||||
RadioState(uint32_t new_bandwidth, uint32_t new_sampling_rate) {
|
||||
model->initialize();
|
||||
model->set_sampling_rate(new_sampling_rate);
|
||||
model->set_baseband_bandwidth(new_bandwidth);
|
||||
}
|
||||
|
||||
~RadioState() {
|
||||
model->set_configuration_without_update(
|
||||
prev_bandwidth_, prev_sampling_rate_);
|
||||
// NB: only enabled for RX model.
|
||||
template <
|
||||
typename U = TModel,
|
||||
typename Mode = std::enable_if_t<sizeof(typename U::Mode), typename U::Mode> >
|
||||
RadioState(Mode new_mode) {
|
||||
model->initialize();
|
||||
model->settings().mode = new_mode;
|
||||
}
|
||||
|
||||
private:
|
||||
const uint32_t prev_bandwidth_;
|
||||
const uint32_t prev_sampling_rate_;
|
||||
// NB: only enabled for RX model.
|
||||
template <
|
||||
typename U = TModel,
|
||||
typename Mode = std::enable_if_t<sizeof(typename U::Mode), typename U::Mode> >
|
||||
RadioState(
|
||||
uint32_t new_bandwidth,
|
||||
uint32_t new_sampling_rate,
|
||||
Mode new_mode) {
|
||||
model->initialize();
|
||||
model->set_sampling_rate(new_sampling_rate);
|
||||
model->set_baseband_bandwidth(new_bandwidth);
|
||||
model->settings().mode = new_mode;
|
||||
}
|
||||
};
|
||||
|
||||
using RxRadioState = RadioState<ReceiverModel, &portapack::receiver_model>;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Kyle Reed
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
@@ -39,9 +40,9 @@ using namespace portapack;
|
||||
namespace {
|
||||
|
||||
static constexpr std::array<baseband::AMConfig, 5> am_configs{{
|
||||
// we config here all the non COMMON parameters to each AM modulation type in RX.
|
||||
{taps_9k0_decim_2, taps_9k0_dsb_channel, AMConfigureMessage::Modulation::DSB}, // AM DSB-C BW 9khz (+-4k5) commercial EU bandwidth .
|
||||
{taps_6k0_decim_2, taps_6k0_dsb_channel, AMConfigureMessage::Modulation::DSB}, // AM DSB-C BW 6khz (+-3k0) narrow AM , ham equipments.
|
||||
// we config here all the non COMMON parameters to each AM modulation type in RX.
|
||||
{taps_9k0_decim_2, taps_9k0_dsb_channel, AMConfigureMessage::Modulation::DSB}, // AM DSB-C BW 9khz (+-4k5) commercial EU bandwidth .
|
||||
{taps_6k0_decim_2, taps_6k0_dsb_channel, AMConfigureMessage::Modulation::DSB}, // AM DSB-C BW 6khz (+-3k0) narrow AM , ham equipments.
|
||||
{taps_6k0_decim_2, taps_2k8_usb_channel, AMConfigureMessage::Modulation::SSB}, // SSB USB BW 2K8 (+ 2K8)
|
||||
{taps_6k0_decim_2, taps_2k8_lsb_channel, AMConfigureMessage::Modulation::SSB}, // SSB LSB BW 2K8 (- 2K8)
|
||||
{taps_6k0_decim_2, taps_0k7_usb_channel, AMConfigureMessage::Modulation::SSB}, // SSB USB BW 0K7 (+ 0K7) used to get audio tone from CW Morse, assuming tx shifted +700hz aprox
|
||||
@@ -70,72 +71,114 @@ void ReceiverModel::set_target_frequency(rf::Frequency f) {
|
||||
update_tuning_frequency();
|
||||
}
|
||||
|
||||
uint32_t ReceiverModel::baseband_bandwidth() const {
|
||||
return settings_.baseband_bandwidth;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_baseband_bandwidth(uint32_t v) {
|
||||
settings_.baseband_bandwidth = v;
|
||||
update_baseband_bandwidth();
|
||||
}
|
||||
|
||||
uint32_t ReceiverModel::sampling_rate() const {
|
||||
return settings_.sampling_rate;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_sampling_rate(uint32_t v) {
|
||||
settings_.sampling_rate = v;
|
||||
update_sampling_rate();
|
||||
}
|
||||
|
||||
rf::Frequency ReceiverModel::frequency_step() const {
|
||||
return frequency_step_;
|
||||
return settings_.frequency_step;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_frequency_step(rf::Frequency f) {
|
||||
frequency_step_ = f;
|
||||
settings_.frequency_step = f;
|
||||
}
|
||||
|
||||
uint8_t ReceiverModel::lna() const {
|
||||
return settings_.lna_gain_db;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_lna(uint8_t v_db) {
|
||||
settings_.lna_gain_db = v_db;
|
||||
update_lna();
|
||||
}
|
||||
|
||||
uint8_t ReceiverModel::vga() const {
|
||||
return settings_.vga_gain_db;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_vga(uint8_t v_db) {
|
||||
settings_.vga_gain_db = v_db;
|
||||
update_vga();
|
||||
}
|
||||
|
||||
bool ReceiverModel::rf_amp() const {
|
||||
return settings_.rf_amp;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_rf_amp(bool enabled) {
|
||||
settings_.rf_amp = enabled;
|
||||
update_rf_amp();
|
||||
}
|
||||
|
||||
ReceiverModel::Mode ReceiverModel::modulation() const {
|
||||
return settings_.mode;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_modulation(Mode v) {
|
||||
settings_.mode = v;
|
||||
update_modulation();
|
||||
}
|
||||
|
||||
uint8_t ReceiverModel::am_configuration() const {
|
||||
return settings_.am_config_index;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_am_configuration(uint8_t n) {
|
||||
if (n < am_configs.size()) {
|
||||
settings_.am_config_index = n;
|
||||
update_modulation();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ReceiverModel::nbfm_configuration() const {
|
||||
return settings_.nbfm_config_index;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_nbfm_configuration(uint8_t n) {
|
||||
if (n < nbfm_configs.size()) {
|
||||
settings_.nbfm_config_index = n;
|
||||
update_modulation();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ReceiverModel::wfm_configuration() const {
|
||||
return settings_.wfm_config_index;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_wfm_configuration(uint8_t n) {
|
||||
if (n < wfm_configs.size()) {
|
||||
settings_.wfm_config_index = n;
|
||||
update_modulation();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ReceiverModel::squelch_level() const {
|
||||
return settings_.squelch_level;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_squelch_level(uint8_t v) {
|
||||
settings_.squelch_level = v;
|
||||
update_modulation();
|
||||
}
|
||||
|
||||
void ReceiverModel::set_antenna_bias() {
|
||||
update_antenna_bias();
|
||||
}
|
||||
|
||||
bool ReceiverModel::rf_amp() const {
|
||||
return rf_amp_;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_rf_amp(bool enabled) {
|
||||
rf_amp_ = enabled;
|
||||
update_rf_amp();
|
||||
}
|
||||
|
||||
int32_t ReceiverModel::lna() const {
|
||||
return lna_gain_db_;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_lna(int32_t v_db) {
|
||||
lna_gain_db_ = v_db;
|
||||
update_lna();
|
||||
}
|
||||
|
||||
uint32_t ReceiverModel::baseband_bandwidth() const {
|
||||
return baseband_bandwidth_;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_baseband_bandwidth(uint32_t v) {
|
||||
baseband_bandwidth_ = v;
|
||||
update_baseband_bandwidth();
|
||||
}
|
||||
|
||||
int32_t ReceiverModel::vga() const {
|
||||
return vga_gain_db_;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_vga(int32_t v_db) {
|
||||
vga_gain_db_ = v_db;
|
||||
update_vga();
|
||||
}
|
||||
|
||||
uint32_t ReceiverModel::sampling_rate() const {
|
||||
return sampling_rate_;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_sampling_rate(uint32_t v) {
|
||||
sampling_rate_ = v;
|
||||
update_sampling_rate();
|
||||
}
|
||||
|
||||
ReceiverModel::Mode ReceiverModel::modulation() const {
|
||||
return mode_;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_modulation(const Mode v) {
|
||||
mode_ = v;
|
||||
update_modulation();
|
||||
}
|
||||
|
||||
volume_t ReceiverModel::headphone_volume() const {
|
||||
return persistent_memory::headphone_volume();
|
||||
}
|
||||
@@ -157,15 +200,6 @@ void ReceiverModel::set_normalized_headphone_volume(uint8_t v) {
|
||||
set_headphone_volume(new_volume);
|
||||
}
|
||||
|
||||
uint8_t ReceiverModel::squelch_level() const {
|
||||
return squelch_level_;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_squelch_level(uint8_t v) {
|
||||
squelch_level_ = v;
|
||||
update_modulation();
|
||||
}
|
||||
|
||||
void ReceiverModel::enable() {
|
||||
enabled_ = true;
|
||||
radio::set_direction(rf::Direction::Receive);
|
||||
@@ -193,6 +227,35 @@ void ReceiverModel::disable() {
|
||||
led_rx.off();
|
||||
}
|
||||
|
||||
void ReceiverModel::initialize() {
|
||||
settings_ = settings_t{};
|
||||
}
|
||||
|
||||
void ReceiverModel::set_configuration_without_update(
|
||||
Mode new_mode,
|
||||
rf::Frequency new_frequency_step,
|
||||
size_t new_am_config_index,
|
||||
size_t new_nbfm_config_index,
|
||||
size_t new_wfm_config_index,
|
||||
uint8_t new_squelch_level) {
|
||||
settings_.mode = new_mode;
|
||||
settings_.frequency_step = new_frequency_step;
|
||||
settings_.am_config_index = new_am_config_index;
|
||||
settings_.nbfm_config_index = new_nbfm_config_index;
|
||||
settings_.wfm_config_index = new_wfm_config_index;
|
||||
settings_.squelch_level = new_squelch_level;
|
||||
}
|
||||
|
||||
void ReceiverModel::configure_from_app_settings(
|
||||
const app_settings::AppSettings& settings) {
|
||||
settings_.baseband_bandwidth = settings.baseband_bandwidth;
|
||||
settings_.sampling_rate = settings.sampling_rate;
|
||||
settings_.lna_gain_db = settings.lna;
|
||||
settings_.vga_gain_db = settings.vga;
|
||||
settings_.rf_amp = settings.rx_amp;
|
||||
settings_.squelch_level = settings.squelch;
|
||||
}
|
||||
|
||||
int32_t ReceiverModel::tuning_offset() {
|
||||
if ((modulation() == Mode::SpectrumAnalysis)) {
|
||||
return 0;
|
||||
@@ -206,78 +269,8 @@ void ReceiverModel::update_tuning_frequency() {
|
||||
radio::set_tuning_frequency(target_frequency() + tuning_offset());
|
||||
}
|
||||
|
||||
void ReceiverModel::update_antenna_bias() {
|
||||
if (enabled_)
|
||||
radio::set_antenna_bias(portapack::get_antenna_bias());
|
||||
}
|
||||
|
||||
void ReceiverModel::update_rf_amp() {
|
||||
radio::set_rf_amp(rf_amp_);
|
||||
}
|
||||
|
||||
void ReceiverModel::update_lna() {
|
||||
radio::set_lna_gain(lna_gain_db_);
|
||||
}
|
||||
|
||||
void ReceiverModel::update_baseband_bandwidth() {
|
||||
radio::set_baseband_filter_bandwidth(baseband_bandwidth_);
|
||||
}
|
||||
|
||||
void ReceiverModel::update_vga() {
|
||||
radio::set_vga_gain(vga_gain_db_);
|
||||
}
|
||||
|
||||
void ReceiverModel::set_am_configuration(const size_t n) {
|
||||
if (n < am_configs.size()) {
|
||||
am_config_index = n;
|
||||
update_modulation();
|
||||
}
|
||||
}
|
||||
|
||||
void ReceiverModel::set_nbfm_configuration(const size_t n) {
|
||||
if (n < nbfm_configs.size()) {
|
||||
nbfm_config_index = n;
|
||||
update_modulation();
|
||||
}
|
||||
}
|
||||
|
||||
void ReceiverModel::set_wfm_configuration(const size_t n) {
|
||||
if (n < wfm_configs.size()) {
|
||||
wfm_config_index = n;
|
||||
update_modulation();
|
||||
}
|
||||
}
|
||||
|
||||
void ReceiverModel::set_configuration_without_update(
|
||||
uint32_t baseband_bandwidth,
|
||||
uint32_t sampling_rate) {
|
||||
baseband_bandwidth_ = baseband_bandwidth;
|
||||
sampling_rate_ = sampling_rate;
|
||||
}
|
||||
|
||||
void ReceiverModel::set_configuration_without_update(
|
||||
Mode new_mode,
|
||||
rf::Frequency new_frequency_step,
|
||||
size_t new_am_config_index,
|
||||
size_t new_nbfm_config_index,
|
||||
size_t new_wfm_config_index,
|
||||
uint8_t new_squelch_level) {
|
||||
mode_ = new_mode;
|
||||
frequency_step_ = new_frequency_step;
|
||||
am_config_index = new_am_config_index;
|
||||
nbfm_config_index = new_nbfm_config_index;
|
||||
wfm_config_index = new_wfm_config_index;
|
||||
squelch_level_ = new_squelch_level;
|
||||
}
|
||||
|
||||
void ReceiverModel::configure_from_app_settings(
|
||||
const app_settings::AppSettings& settings) {
|
||||
baseband_bandwidth_ = settings.baseband_bandwidth;
|
||||
sampling_rate_ = settings.sampling_rate;
|
||||
lna_gain_db_ = settings.lna;
|
||||
vga_gain_db_ = settings.vga;
|
||||
rf_amp_ = settings.rx_amp;
|
||||
squelch_level_ = settings.squelch;
|
||||
radio::set_baseband_filter_bandwidth(baseband_bandwidth());
|
||||
}
|
||||
|
||||
void ReceiverModel::update_sampling_rate() {
|
||||
@@ -290,8 +283,16 @@ void ReceiverModel::update_sampling_rate() {
|
||||
update_tuning_frequency();
|
||||
}
|
||||
|
||||
void ReceiverModel::update_headphone_volume() {
|
||||
audio::headphone::set_volume(headphone_volume());
|
||||
void ReceiverModel::update_lna() {
|
||||
radio::set_lna_gain(lna());
|
||||
}
|
||||
|
||||
void ReceiverModel::update_vga() {
|
||||
radio::set_vga_gain(vga());
|
||||
}
|
||||
|
||||
void ReceiverModel::update_rf_amp() {
|
||||
radio::set_rf_amp(rf_amp());
|
||||
}
|
||||
|
||||
void ReceiverModel::update_modulation() {
|
||||
@@ -315,26 +316,23 @@ void ReceiverModel::update_modulation() {
|
||||
}
|
||||
}
|
||||
|
||||
size_t ReceiverModel::am_configuration() const {
|
||||
return am_config_index;
|
||||
}
|
||||
|
||||
void ReceiverModel::update_am_configuration() {
|
||||
am_configs[am_config_index].apply();
|
||||
}
|
||||
|
||||
size_t ReceiverModel::nbfm_configuration() const {
|
||||
return nbfm_config_index;
|
||||
am_configs[am_configuration()].apply();
|
||||
}
|
||||
|
||||
void ReceiverModel::update_nbfm_configuration() {
|
||||
nbfm_configs[nbfm_config_index].apply(squelch_level_);
|
||||
}
|
||||
|
||||
size_t ReceiverModel::wfm_configuration() const {
|
||||
return wfm_config_index;
|
||||
nbfm_configs[nbfm_configuration()].apply(squelch_level());
|
||||
}
|
||||
|
||||
void ReceiverModel::update_wfm_configuration() {
|
||||
wfm_configs[wfm_config_index].apply();
|
||||
wfm_configs[wfm_configuration()].apply();
|
||||
}
|
||||
|
||||
void ReceiverModel::update_antenna_bias() {
|
||||
if (enabled_)
|
||||
radio::set_antenna_bias(portapack::get_antenna_bias());
|
||||
}
|
||||
|
||||
void ReceiverModel::update_headphone_volume() {
|
||||
audio::headphone::set_volume(headphone_volume());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2023 Kyle Reed
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
@@ -26,16 +27,16 @@
|
||||
#include <cstddef>
|
||||
|
||||
#include "app_settings.hpp"
|
||||
#include "max283x.hpp"
|
||||
#include "message.hpp"
|
||||
#include "rf_path.hpp"
|
||||
#include "max283x.hpp"
|
||||
#include "volume.hpp"
|
||||
|
||||
// TODO: consider a base class for ReceiverModel & TransmitterModel.
|
||||
// There are multiple values that are actually shared by both.
|
||||
class ReceiverModel {
|
||||
public:
|
||||
enum class Mode {
|
||||
enum class Mode : uint8_t {
|
||||
AMAudio = 0,
|
||||
NarrowbandFMAudio = 1,
|
||||
WidebandFMAudio = 2,
|
||||
@@ -43,33 +44,59 @@ class ReceiverModel {
|
||||
Capture = 4
|
||||
};
|
||||
|
||||
struct settings_t {
|
||||
uint32_t baseband_bandwidth = max283x::filter::bandwidth_minimum;
|
||||
uint32_t sampling_rate = 3'072'000;
|
||||
rf::Frequency frequency_step = 25'000;
|
||||
uint8_t lna_gain_db = 32;
|
||||
uint8_t vga_gain_db = 32;
|
||||
bool rf_amp = false;
|
||||
Mode mode = Mode::NarrowbandFMAudio;
|
||||
uint8_t am_config_index = 0;
|
||||
uint8_t nbfm_config_index = 0;
|
||||
uint8_t wfm_config_index = 0;
|
||||
uint8_t squelch_level = 80;
|
||||
};
|
||||
|
||||
/* The frequency to receive (no offset). */
|
||||
rf::Frequency target_frequency() const;
|
||||
void set_target_frequency(rf::Frequency f);
|
||||
|
||||
rf::Frequency frequency_step() const;
|
||||
void set_frequency_step(rf::Frequency f);
|
||||
|
||||
void set_antenna_bias();
|
||||
|
||||
bool rf_amp() const;
|
||||
void set_rf_amp(bool enabled);
|
||||
|
||||
int32_t lna() const;
|
||||
void set_lna(int32_t v_db);
|
||||
|
||||
uint32_t baseband_bandwidth() const;
|
||||
void set_baseband_bandwidth(uint32_t v);
|
||||
|
||||
int32_t vga() const;
|
||||
void set_vga(int32_t v_db);
|
||||
|
||||
uint32_t sampling_rate() const;
|
||||
void set_sampling_rate(uint32_t v);
|
||||
|
||||
rf::Frequency frequency_step() const;
|
||||
void set_frequency_step(rf::Frequency f);
|
||||
|
||||
uint8_t lna() const;
|
||||
void set_lna(uint8_t v_db);
|
||||
|
||||
uint8_t vga() const;
|
||||
void set_vga(uint8_t v_db);
|
||||
|
||||
bool rf_amp() const;
|
||||
void set_rf_amp(bool enabled);
|
||||
|
||||
Mode modulation() const;
|
||||
void set_modulation(Mode v);
|
||||
|
||||
uint8_t am_configuration() const;
|
||||
void set_am_configuration(uint8_t n);
|
||||
|
||||
uint8_t nbfm_configuration() const;
|
||||
void set_nbfm_configuration(uint8_t n);
|
||||
|
||||
uint8_t wfm_configuration() const;
|
||||
void set_wfm_configuration(uint8_t n);
|
||||
|
||||
uint8_t squelch_level() const;
|
||||
void set_squelch_level(uint8_t v);
|
||||
|
||||
void set_antenna_bias();
|
||||
|
||||
volume_t headphone_volume() const;
|
||||
void set_headphone_volume(volume_t v);
|
||||
|
||||
@@ -77,25 +104,11 @@ class ReceiverModel {
|
||||
uint8_t normalized_headphone_volume() const;
|
||||
void set_normalized_headphone_volume(uint8_t v);
|
||||
|
||||
uint8_t squelch_level() const;
|
||||
void set_squelch_level(uint8_t v);
|
||||
|
||||
void enable();
|
||||
void disable();
|
||||
|
||||
size_t am_configuration() const;
|
||||
void set_am_configuration(const size_t n);
|
||||
|
||||
size_t nbfm_configuration() const;
|
||||
void set_nbfm_configuration(const size_t n);
|
||||
|
||||
size_t wfm_configuration() const;
|
||||
void set_wfm_configuration(const size_t n);
|
||||
|
||||
/* Sets the model values without updating the radio. */
|
||||
void set_configuration_without_update(
|
||||
uint32_t baseband_bandwidth,
|
||||
uint32_t sampling_rate);
|
||||
/* Resets some members back to default. */
|
||||
void initialize();
|
||||
|
||||
void set_configuration_without_update(
|
||||
Mode new_mode,
|
||||
@@ -107,35 +120,30 @@ class ReceiverModel {
|
||||
|
||||
void configure_from_app_settings(const app_settings::AppSettings& settings);
|
||||
|
||||
/* Get access to the underlying settings to allow
|
||||
* values to be set directly without calling update. */
|
||||
settings_t& settings() { return settings_; }
|
||||
|
||||
private:
|
||||
rf::Frequency frequency_step_{25000};
|
||||
bool enabled_{false};
|
||||
bool rf_amp_{false};
|
||||
int32_t lna_gain_db_{32};
|
||||
uint32_t baseband_bandwidth_{max283x::filter::bandwidth_minimum};
|
||||
int32_t vga_gain_db_{32};
|
||||
Mode mode_{Mode::NarrowbandFMAudio};
|
||||
uint32_t sampling_rate_{3072000};
|
||||
size_t am_config_index = 0;
|
||||
size_t nbfm_config_index = 0;
|
||||
size_t wfm_config_index = 0;
|
||||
uint8_t squelch_level_{80};
|
||||
settings_t settings_{};
|
||||
bool enabled_ = false;
|
||||
|
||||
int32_t tuning_offset();
|
||||
|
||||
void update_tuning_frequency();
|
||||
void update_antenna_bias();
|
||||
void update_rf_amp();
|
||||
void update_lna();
|
||||
void update_baseband_bandwidth();
|
||||
void update_vga();
|
||||
void update_sampling_rate();
|
||||
void update_headphone_volume();
|
||||
void update_lna();
|
||||
void update_vga();
|
||||
void update_rf_amp();
|
||||
|
||||
void update_modulation();
|
||||
void update_am_configuration();
|
||||
void update_nbfm_configuration();
|
||||
void update_wfm_configuration();
|
||||
|
||||
void update_antenna_bias();
|
||||
void update_headphone_volume();
|
||||
};
|
||||
|
||||
#endif /*__RECEIVER_MODEL_H__*/
|
||||
|
||||
@@ -25,63 +25,68 @@
|
||||
|
||||
namespace tonekey {
|
||||
|
||||
// Keep list in ascending order by tone frequency
|
||||
const tone_key_t tone_keys = {
|
||||
{"None", 0.0},
|
||||
{"0 XZ", 67.000},
|
||||
{"1 WZ", 69.400},
|
||||
{"2 XA", 71.900},
|
||||
{"3 WA", 74.400},
|
||||
{"4 XB", 77.000},
|
||||
{"5 WB", 79.700},
|
||||
{"6 YZ", 82.500},
|
||||
{"7 YA", 85.400},
|
||||
{"8 YB", 88.500},
|
||||
{"9 ZZ", 91.500},
|
||||
{"10 ZA", 94.800},
|
||||
{"11 ZB", 97.400},
|
||||
{"12 1Z", 100.000},
|
||||
{"13 1A", 103.500},
|
||||
{"14 1B", 107.200},
|
||||
{"15 2Z", 110.900},
|
||||
{"16 2A", 114.800},
|
||||
{"17 2B", 118.800},
|
||||
{"18 3Z", 123.000},
|
||||
{"19 3A", 127.300},
|
||||
{"20 3B", 131.800},
|
||||
{"21 4Z", 136.500},
|
||||
{"22 4A", 141.300},
|
||||
{"23 4B", 146.200},
|
||||
{"24 5Z", 151.400},
|
||||
{"25 5A", 156.700},
|
||||
{"40 --", 159.800},
|
||||
{"26 5B", 162.200},
|
||||
{"41 --", 165.500},
|
||||
{"27 6Z", 167.900},
|
||||
{"42 --", 171.300},
|
||||
{"28 6A", 173.800},
|
||||
{"43 --", 177.300},
|
||||
{"29 6B", 179.900},
|
||||
{"44 --", 183.500},
|
||||
{"30 7Z", 186.200},
|
||||
{"45 --", 189.900},
|
||||
{"31 7A", 192.800},
|
||||
{"46 --", 196.600},
|
||||
{"47 --", 199.500},
|
||||
{"32 M1", 203.500},
|
||||
{"48 8Z", 206.500},
|
||||
{"33 M2", 210.700},
|
||||
{"34 M3", 218.100},
|
||||
{"35 M4", 225.700},
|
||||
{"49 9Z", 229.100},
|
||||
{"36 M5", 233.600},
|
||||
{"37 M6", 241.800},
|
||||
{"38 M7", 250.300},
|
||||
{"50 0Z", 254.100},
|
||||
{"Axient 28kHz", 28000.0},
|
||||
{"Senn. 32.768k", 32768.0},
|
||||
{"Senn. 32.000k", 32000.0},
|
||||
{"Sony 32.382k", 32382.0},
|
||||
{"Shure 19kHz", 19000.0}};
|
||||
{"None", F2Ix100(0.0)},
|
||||
{"1 XZ", F2Ix100(67.0)},
|
||||
{"39 WZ", F2Ix100(69.3)},
|
||||
{"2 XA", F2Ix100(71.9)},
|
||||
{"3 WA", F2Ix100(74.4)},
|
||||
{"4 XB", F2Ix100(77.0)},
|
||||
{"5 WB", F2Ix100(79.7)},
|
||||
{"6 YZ", F2Ix100(82.5)},
|
||||
{"7 YA", F2Ix100(85.4)},
|
||||
{"8 YB", F2Ix100(88.5)},
|
||||
{"9 ZZ", F2Ix100(91.5)},
|
||||
{"10 ZA", F2Ix100(94.8)},
|
||||
{"11 ZB", F2Ix100(97.4)},
|
||||
{"12 1Z", F2Ix100(100.0)},
|
||||
{"13 1A", F2Ix100(103.5)},
|
||||
{"14 1B", F2Ix100(107.2)},
|
||||
{"15 2Z", F2Ix100(110.9)},
|
||||
{"16 2A", F2Ix100(114.8)},
|
||||
{"17 2B", F2Ix100(118.8)},
|
||||
{"18 3Z", F2Ix100(123.0)},
|
||||
{"19 3A", F2Ix100(127.3)},
|
||||
{"20 3B", F2Ix100(131.8)},
|
||||
{"21 4Z", F2Ix100(136.5)},
|
||||
{"22 4A", F2Ix100(141.3)},
|
||||
{"23 4B", F2Ix100(146.2)},
|
||||
{"24 5Z", F2Ix100(151.4)},
|
||||
{"25 5A", F2Ix100(156.7)},
|
||||
{"40 --", F2Ix100(159.8)},
|
||||
{"26 5B", F2Ix100(162.2)},
|
||||
{"41 --", F2Ix100(165.5)},
|
||||
{"27 6Z", F2Ix100(167.9)},
|
||||
{"42 --", F2Ix100(171.3)},
|
||||
{"28 6A", F2Ix100(173.8)},
|
||||
{"43 --", F2Ix100(177.3)},
|
||||
{"29 6B", F2Ix100(179.9)},
|
||||
{"44 --", F2Ix100(183.5)},
|
||||
{"30 7Z", F2Ix100(186.2)},
|
||||
{"45 --", F2Ix100(189.9)},
|
||||
{"31 7A", F2Ix100(192.8)},
|
||||
{"46 --", F2Ix100(196.6)},
|
||||
{"47 --", F2Ix100(199.5)},
|
||||
{"32 M1", F2Ix100(203.5)},
|
||||
{"48 8Z", F2Ix100(206.5)},
|
||||
{"33 M2", F2Ix100(210.7)},
|
||||
{"34 M3", F2Ix100(218.1)},
|
||||
{"35 M4", F2Ix100(225.7)},
|
||||
{"49 9Z", F2Ix100(229.1)},
|
||||
{"36 M5", F2Ix100(233.6)},
|
||||
{"37 M6", F2Ix100(241.8)},
|
||||
{"38 M7", F2Ix100(250.3)},
|
||||
{"50 0Z", F2Ix100(254.1)},
|
||||
{"Shure 19kHz", F2Ix100(19000.0)},
|
||||
{"Axient 28kHz", F2Ix100(28000.0)},
|
||||
{"Senn. 32.000k", F2Ix100(32000.0)},
|
||||
{"Sony 32.382k", F2Ix100(32382.0)},
|
||||
{"Senn. 32.768k", F2Ix100(32768.0)}};
|
||||
|
||||
std::string fx100_string(uint32_t f) {
|
||||
return to_string_dec_uint(f / 100) + "." + to_string_dec_uint((f / 10) % 10);
|
||||
}
|
||||
|
||||
void tone_keys_populate(OptionsField& field) {
|
||||
using option_t = std::pair<std::string, int32_t>;
|
||||
@@ -90,12 +95,11 @@ void tone_keys_populate(OptionsField& field) {
|
||||
std::string tone_name;
|
||||
|
||||
for (size_t c = 0; c < tone_keys.size(); c++) {
|
||||
if (c && c < 51) {
|
||||
auto f = tone_keys[c].second;
|
||||
tone_name = "CTCSS " + tone_keys[c].first + " " + to_string_dec_uint(f) + "." + to_string_dec_uint((uint32_t)(f * 10) % 10);
|
||||
} else {
|
||||
auto f = tone_keys[c].second;
|
||||
if ((c != 0) && (f < 1000 * 100))
|
||||
tone_name = "CTCSS " + fx100_string(f) + " #" + tone_keys[c].first;
|
||||
else
|
||||
tone_name = tone_keys[c].first;
|
||||
}
|
||||
|
||||
tone_key_options.emplace_back(tone_name, c);
|
||||
}
|
||||
@@ -103,8 +107,8 @@ void tone_keys_populate(OptionsField& field) {
|
||||
field.set_options(tone_key_options);
|
||||
}
|
||||
|
||||
float tone_key_frequency(const tone_index index) {
|
||||
return tone_keys[index].second;
|
||||
float tone_key_frequency(tone_index index) {
|
||||
return float(tone_keys[index].second) / 100.0;
|
||||
}
|
||||
|
||||
std::string tone_key_string(tone_index index) {
|
||||
@@ -113,20 +117,65 @@ std::string tone_key_string(tone_index index) {
|
||||
return tone_keys[index].first;
|
||||
}
|
||||
|
||||
std::string tone_key_string_by_value(uint32_t value) {
|
||||
return tone_key_string(tone_key_index_by_value(value));
|
||||
// Return string showing frequency only from specific table index
|
||||
std::string tone_key_value_string(tone_index index) {
|
||||
if (index < 0 || (unsigned)index >= tone_keys.size())
|
||||
return std::string("");
|
||||
return fx100_string(tone_keys[index].second);
|
||||
}
|
||||
|
||||
// Return variable-length string showing CTCSS tone from tone frequency
|
||||
// Value is in 0.01 Hz units
|
||||
std::string tone_key_string_by_value(uint32_t value, size_t max_length) {
|
||||
static uint8_t tone_display_toggle{0};
|
||||
static uint32_t last_value;
|
||||
tone_index idx;
|
||||
std::string freq_str;
|
||||
|
||||
// If >10Hz difference between consecutive samples, it's probably noise, so ignore
|
||||
if (abs(value - last_value) > 10 * 100) {
|
||||
last_value = value;
|
||||
tone_display_toggle = 0;
|
||||
return " ";
|
||||
}
|
||||
last_value = value;
|
||||
|
||||
// Only display 1/10 Hz accuracy if <1000 Hz; max 5 characters
|
||||
if (value < 1000 * 100)
|
||||
freq_str = "T:" + fx100_string(value);
|
||||
else
|
||||
freq_str = "T:" + to_string_dec_uint(value / 100);
|
||||
|
||||
// Check field length is enough for character counts in the string below
|
||||
if (max_length >= 7 + 2 + 5) {
|
||||
idx = tone_key_index_by_value(value);
|
||||
if (idx != -1)
|
||||
return freq_str + " #" + tone_key_string(idx);
|
||||
} else {
|
||||
// Not enough space; toggle between display of tone received and tone code #
|
||||
if (tone_display_toggle++ >= TONE_DISPLAY_TOGGLE_COUNTER) {
|
||||
if (tone_display_toggle >= TONE_DISPLAY_TOGGLE_COUNTER * 2) tone_display_toggle = 0;
|
||||
|
||||
// Look for a match in the table (otherwise just display frequency)
|
||||
idx = tone_key_index_by_value(value);
|
||||
if (idx != -1)
|
||||
return "T:" + tone_key_string(idx);
|
||||
}
|
||||
}
|
||||
return freq_str;
|
||||
}
|
||||
|
||||
// Search tone_key table for tone frequency value
|
||||
// Value is in 0.01 Hz units
|
||||
tone_index tone_key_index_by_value(uint32_t value) {
|
||||
float diff;
|
||||
float min_diff{(float)value};
|
||||
float fvalue{(float)((min_diff + 50.0) / 100.0)};
|
||||
uint32_t diff;
|
||||
uint32_t min_diff{value * 2};
|
||||
tone_index min_idx{-1};
|
||||
tone_index idx;
|
||||
|
||||
// Find nearest match
|
||||
for (idx = 0; idx < (tone_index)tone_keys.size(); idx++) {
|
||||
diff = abs(fvalue - tone_keys[idx].second);
|
||||
diff = abs(value - tone_keys[idx].second);
|
||||
if (diff < min_diff) {
|
||||
min_idx = idx;
|
||||
min_diff = diff;
|
||||
@@ -137,7 +186,7 @@ tone_index tone_key_index_by_value(uint32_t value) {
|
||||
}
|
||||
|
||||
// Arbitrary confidence threshold
|
||||
if (min_diff < 40.0)
|
||||
if (min_diff < TONE_FREQ_TOLERANCE_CENTIHZ)
|
||||
return min_idx;
|
||||
else
|
||||
return -1;
|
||||
|
||||
@@ -30,17 +30,22 @@ using namespace ui;
|
||||
|
||||
namespace tonekey {
|
||||
|
||||
#define TONE_FREQ_TOLERANCE_CENTIHZ (4 * 100)
|
||||
#define TONE_DISPLAY_TOGGLE_COUNTER 3
|
||||
#define F2Ix100(x) (int32_t)(x * 100.0)
|
||||
|
||||
typedef int32_t tone_index;
|
||||
|
||||
using tone_key_t = std::vector<std::pair<std::string, float>>;
|
||||
using tone_key_t = std::vector<std::pair<std::string, uint32_t>>;
|
||||
|
||||
extern const tone_key_t tone_keys;
|
||||
|
||||
void tone_keys_populate(OptionsField& field);
|
||||
float tone_key_frequency(const tone_index index);
|
||||
float tone_key_frequency(tone_index index);
|
||||
|
||||
std::string tone_key_string(const tone_index index);
|
||||
std::string tone_key_string_by_value(uint32_t value);
|
||||
std::string tone_key_string(tone_index index);
|
||||
std::string tone_key_value_string(tone_index index);
|
||||
std::string tone_key_string_by_value(uint32_t value, size_t max_length);
|
||||
tone_index tone_key_index_by_value(uint32_t value);
|
||||
|
||||
} // namespace tonekey
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2016 Furrtek
|
||||
* Copyright (C) 2023 Kyle Reed
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
@@ -22,15 +23,13 @@
|
||||
|
||||
#include "transmitter_model.hpp"
|
||||
|
||||
#include "audio.hpp"
|
||||
#include "baseband_api.hpp"
|
||||
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
#include "event_m0.hpp"
|
||||
#include "hackrf_gpio.hpp"
|
||||
#include "portapack.hpp"
|
||||
#include "rtc_time.hpp"
|
||||
#include "event_m0.hpp"
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
#include "radio.hpp"
|
||||
#include "audio.hpp"
|
||||
|
||||
using namespace hackrf::one;
|
||||
using namespace portapack;
|
||||
@@ -44,75 +43,52 @@ void TransmitterModel::set_target_frequency(rf::Frequency f) {
|
||||
update_tuning_frequency();
|
||||
}
|
||||
|
||||
void TransmitterModel::set_antenna_bias() {
|
||||
update_antenna_bias();
|
||||
}
|
||||
|
||||
bool TransmitterModel::rf_amp() const {
|
||||
return rf_amp_;
|
||||
}
|
||||
|
||||
void TransmitterModel::set_rf_amp(bool enabled) {
|
||||
rf_amp_ = enabled;
|
||||
update_rf_amp();
|
||||
}
|
||||
|
||||
int32_t TransmitterModel::lna() const {
|
||||
return lna_gain_db_;
|
||||
}
|
||||
|
||||
void TransmitterModel::set_lna(int32_t v_db) {
|
||||
lna_gain_db_ = v_db;
|
||||
update_lna();
|
||||
}
|
||||
|
||||
uint32_t TransmitterModel::baseband_bandwidth() const {
|
||||
return baseband_bandwidth_;
|
||||
return settings_.baseband_bandwidth;
|
||||
}
|
||||
|
||||
void TransmitterModel::set_baseband_bandwidth(uint32_t v) {
|
||||
baseband_bandwidth_ = v;
|
||||
settings_.baseband_bandwidth = v;
|
||||
update_baseband_bandwidth();
|
||||
}
|
||||
|
||||
int32_t TransmitterModel::vga() const {
|
||||
return vga_gain_db_;
|
||||
}
|
||||
|
||||
void TransmitterModel::set_vga(int32_t v_db) {
|
||||
vga_gain_db_ = v_db;
|
||||
update_vga();
|
||||
}
|
||||
|
||||
uint32_t TransmitterModel::channel_bandwidth() const {
|
||||
return channel_bandwidth_;
|
||||
}
|
||||
|
||||
void TransmitterModel::set_channel_bandwidth(uint32_t v) {
|
||||
channel_bandwidth_ = v;
|
||||
}
|
||||
|
||||
uint32_t TransmitterModel::sampling_rate() const {
|
||||
return sampling_rate_;
|
||||
return settings_.sampling_rate;
|
||||
}
|
||||
|
||||
void TransmitterModel::set_sampling_rate(uint32_t v) {
|
||||
sampling_rate_ = v;
|
||||
settings_.sampling_rate = v;
|
||||
update_sampling_rate();
|
||||
}
|
||||
|
||||
int32_t TransmitterModel::tx_gain() const {
|
||||
return tx_gain_db_;
|
||||
uint32_t TransmitterModel::channel_bandwidth() const {
|
||||
return settings_.channel_bandwidth;
|
||||
}
|
||||
|
||||
void TransmitterModel::set_tx_gain(int32_t v_db) {
|
||||
tx_gain_db_ = v_db;
|
||||
void TransmitterModel::set_channel_bandwidth(uint32_t v) {
|
||||
settings_.channel_bandwidth = v;
|
||||
}
|
||||
|
||||
uint8_t TransmitterModel::tx_gain() const {
|
||||
return settings_.tx_gain_db;
|
||||
}
|
||||
|
||||
void TransmitterModel::set_tx_gain(uint8_t v_db) {
|
||||
settings_.tx_gain_db = v_db;
|
||||
update_tx_gain();
|
||||
}
|
||||
|
||||
void TransmitterModel::on_tick_second() {
|
||||
if (portapack::persistent_memory::stealth_mode())
|
||||
led_tx.toggle();
|
||||
bool TransmitterModel::rf_amp() const {
|
||||
return settings_.rf_amp;
|
||||
}
|
||||
|
||||
void TransmitterModel::set_rf_amp(bool enabled) {
|
||||
settings_.rf_amp = enabled;
|
||||
update_rf_amp();
|
||||
}
|
||||
|
||||
void TransmitterModel::set_antenna_bias() {
|
||||
update_antenna_bias();
|
||||
}
|
||||
|
||||
void TransmitterModel::enable() {
|
||||
@@ -121,8 +97,6 @@ void TransmitterModel::enable() {
|
||||
update_tuning_frequency();
|
||||
update_antenna_bias();
|
||||
update_rf_amp();
|
||||
update_lna();
|
||||
update_vga();
|
||||
update_baseband_bandwidth();
|
||||
update_sampling_rate();
|
||||
update_tx_gain();
|
||||
@@ -147,53 +121,25 @@ void TransmitterModel::disable() {
|
||||
led_tx.off();
|
||||
}
|
||||
|
||||
void TransmitterModel::set_configuration_without_update(
|
||||
uint32_t baseband_bandwidth,
|
||||
uint32_t sampling_rate) {
|
||||
baseband_bandwidth_ = baseband_bandwidth;
|
||||
sampling_rate_ = sampling_rate;
|
||||
void TransmitterModel::initialize() {
|
||||
settings_ = settings_t{};
|
||||
}
|
||||
|
||||
void TransmitterModel::configure_from_app_settings(
|
||||
const app_settings::AppSettings& settings) {
|
||||
baseband_bandwidth_ = settings.baseband_bandwidth;
|
||||
channel_bandwidth_ = settings.channel_bandwidth;
|
||||
tx_gain_db_ = settings.tx_gain;
|
||||
rf_amp_ = settings.tx_amp;
|
||||
|
||||
// TODO: Do these make sense for TX?
|
||||
lna_gain_db_ = settings.lna;
|
||||
vga_gain_db_ = settings.vga;
|
||||
sampling_rate_ = settings.sampling_rate;
|
||||
settings_.baseband_bandwidth = settings.baseband_bandwidth;
|
||||
settings_.sampling_rate = settings.sampling_rate;
|
||||
settings_.channel_bandwidth = settings.channel_bandwidth;
|
||||
settings_.tx_gain_db = settings.tx_gain;
|
||||
settings_.rf_amp = settings.tx_amp;
|
||||
}
|
||||
|
||||
void TransmitterModel::update_tuning_frequency() {
|
||||
radio::set_tuning_frequency(target_frequency());
|
||||
}
|
||||
|
||||
void TransmitterModel::update_antenna_bias() {
|
||||
if (enabled_)
|
||||
radio::set_antenna_bias(portapack::get_antenna_bias());
|
||||
}
|
||||
|
||||
void TransmitterModel::update_rf_amp() {
|
||||
radio::set_rf_amp(rf_amp_);
|
||||
}
|
||||
|
||||
void TransmitterModel::update_lna() {
|
||||
radio::set_lna_gain(lna_gain_db_);
|
||||
}
|
||||
|
||||
void TransmitterModel::update_baseband_bandwidth() {
|
||||
radio::set_baseband_filter_bandwidth(baseband_bandwidth_);
|
||||
}
|
||||
|
||||
void TransmitterModel::update_vga() {
|
||||
radio::set_vga_gain(vga_gain_db_);
|
||||
}
|
||||
|
||||
void TransmitterModel::update_tx_gain() {
|
||||
radio::set_tx_gain(tx_gain_db_);
|
||||
radio::set_baseband_filter_bandwidth(baseband_bandwidth());
|
||||
}
|
||||
|
||||
void TransmitterModel::update_sampling_rate() {
|
||||
@@ -206,3 +152,21 @@ void TransmitterModel::update_sampling_rate() {
|
||||
radio::set_baseband_rate(sampling_rate());
|
||||
update_tuning_frequency();
|
||||
}
|
||||
|
||||
void TransmitterModel::update_tx_gain() {
|
||||
radio::set_tx_gain(tx_gain());
|
||||
}
|
||||
|
||||
void TransmitterModel::update_rf_amp() {
|
||||
radio::set_rf_amp(rf_amp());
|
||||
}
|
||||
|
||||
void TransmitterModel::update_antenna_bias() {
|
||||
if (enabled_)
|
||||
radio::set_antenna_bias(portapack::get_antenna_bias());
|
||||
}
|
||||
|
||||
void TransmitterModel::on_tick_second() {
|
||||
if (portapack::persistent_memory::stealth_mode())
|
||||
led_tx.toggle();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
* Copyright (C) 2016 Furrtek
|
||||
* Copyright (C) 2023 Kyle Reed
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
@@ -26,77 +27,68 @@
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
#include "receiver_model.hpp"
|
||||
#include "app_settings.hpp"
|
||||
#include "message.hpp"
|
||||
#include "rf_path.hpp"
|
||||
#include "max2837.hpp"
|
||||
#include "volume.hpp"
|
||||
#include "message.hpp"
|
||||
#include "receiver_model.hpp"
|
||||
#include "rf_path.hpp"
|
||||
#include "signal.hpp"
|
||||
|
||||
class TransmitterModel {
|
||||
public:
|
||||
struct settings_t {
|
||||
uint32_t baseband_bandwidth = max283x::filter::bandwidth_minimum;
|
||||
uint32_t sampling_rate = 3'072'000;
|
||||
uint32_t channel_bandwidth = 1;
|
||||
/* 35 should give approx 1m transmission range. */
|
||||
uint8_t tx_gain_db = 35;
|
||||
bool rf_amp = false;
|
||||
};
|
||||
|
||||
/* The frequency to transmit on. */
|
||||
rf::Frequency target_frequency() const;
|
||||
void set_target_frequency(rf::Frequency f);
|
||||
|
||||
void set_antenna_bias();
|
||||
|
||||
bool rf_amp() const;
|
||||
void set_rf_amp(bool enabled);
|
||||
|
||||
// TODO: does this make sense on TX?
|
||||
int32_t lna() const;
|
||||
void set_lna(int32_t v_db);
|
||||
|
||||
uint32_t baseband_bandwidth() const;
|
||||
void set_baseband_bandwidth(uint32_t v);
|
||||
|
||||
// TODO: does this make sense on TX?
|
||||
int32_t vga() const;
|
||||
void set_vga(int32_t v_db);
|
||||
|
||||
int32_t tx_gain() const;
|
||||
void set_tx_gain(int32_t v_db);
|
||||
|
||||
// TODO: Doesn't actually affect radio.
|
||||
uint32_t channel_bandwidth() const;
|
||||
void set_channel_bandwidth(uint32_t v);
|
||||
|
||||
// TODO: does this make sense on TX?
|
||||
uint32_t sampling_rate() const;
|
||||
void set_sampling_rate(uint32_t v);
|
||||
|
||||
uint8_t tx_gain() const;
|
||||
void set_tx_gain(uint8_t v_db);
|
||||
|
||||
bool rf_amp() const;
|
||||
void set_rf_amp(bool enabled);
|
||||
|
||||
void set_antenna_bias();
|
||||
|
||||
void enable();
|
||||
void disable();
|
||||
|
||||
/* Sets the model values without updating the radio. */
|
||||
void set_configuration_without_update(
|
||||
uint32_t baseband_bandwidth,
|
||||
uint32_t sampling_rate);
|
||||
void initialize();
|
||||
|
||||
void configure_from_app_settings(const app_settings::AppSettings& settings);
|
||||
|
||||
/* Get access to the underlying settings to allow
|
||||
* values to be set directly without calling update. */
|
||||
settings_t& settings() { return settings_; }
|
||||
|
||||
private:
|
||||
bool enabled_{false};
|
||||
bool rf_amp_{false};
|
||||
int32_t lna_gain_db_{0};
|
||||
uint32_t channel_bandwidth_{1};
|
||||
uint32_t baseband_bandwidth_{max2837::filter::bandwidth_minimum};
|
||||
int32_t vga_gain_db_{8};
|
||||
/* 35 should give approx 1m transmission range. */
|
||||
int32_t tx_gain_db_{35};
|
||||
uint32_t sampling_rate_{3072000};
|
||||
settings_t settings_{};
|
||||
bool enabled_ = false;
|
||||
SignalToken signal_token_tick_second{};
|
||||
|
||||
void update_tuning_frequency();
|
||||
void update_antenna_bias();
|
||||
void update_rf_amp();
|
||||
void update_lna();
|
||||
void update_baseband_bandwidth();
|
||||
void update_vga();
|
||||
void update_tx_gain();
|
||||
void update_sampling_rate();
|
||||
void update_tx_gain();
|
||||
void update_rf_amp();
|
||||
void update_antenna_bias();
|
||||
void on_tick_second();
|
||||
};
|
||||
|
||||
|
||||
@@ -280,7 +280,7 @@ FrequencyOptionsView::FrequencyOptionsView(
|
||||
}
|
||||
|
||||
void FrequencyOptionsView::set_step(rf::Frequency f) {
|
||||
field_step.set_by_value(f);
|
||||
field_step.set_by_nearest_value(f);
|
||||
}
|
||||
|
||||
void FrequencyOptionsView::set_reference_ppm_correction(int32_t v) {
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
#include "ui_flash_utility.hpp"
|
||||
#include "ui_sd_over_usb.hpp"
|
||||
#include "ui_spectrum_painter.hpp"
|
||||
#include "ui_ss_viewer.hpp"
|
||||
|
||||
// #include "acars_app.hpp"
|
||||
#include "ais_app.hpp"
|
||||
@@ -179,16 +180,21 @@ SystemStatusView::SystemStatusView(
|
||||
this->on_converter();
|
||||
};
|
||||
|
||||
button_speaker.on_select = [this](ImageButton&) {
|
||||
this->on_speaker();
|
||||
toggle_speaker.on_change = [this](bool v) {
|
||||
pmem::set_config_speaker_disable(v);
|
||||
audio::output::update_audio_mute();
|
||||
refresh();
|
||||
};
|
||||
|
||||
button_mute.on_select = [this](ImageButton&) {
|
||||
this->on_mute();
|
||||
toggle_mute.on_change = [this](bool v) {
|
||||
pmem::set_config_audio_mute(v);
|
||||
audio::output::update_audio_mute();
|
||||
refresh();
|
||||
};
|
||||
|
||||
button_stealth.on_select = [this](ImageButton&) {
|
||||
this->on_stealth();
|
||||
toggle_stealth.on_change = [this](bool v) {
|
||||
pmem::set_stealth_mode(v);
|
||||
refresh();
|
||||
};
|
||||
|
||||
button_bias_tee.on_select = [this](ImageButton&) {
|
||||
@@ -208,6 +214,11 @@ SystemStatusView::SystemStatusView(
|
||||
this->on_clk();
|
||||
};
|
||||
|
||||
// Initialize toggle buttons
|
||||
toggle_speaker.set_value(pmem::config_speaker_disable());
|
||||
toggle_mute.set_value(pmem::config_audio_mute());
|
||||
toggle_stealth.set_value(pmem::stealth_mode());
|
||||
|
||||
audio::output::update_audio_mute();
|
||||
refresh();
|
||||
}
|
||||
@@ -218,43 +229,22 @@ void SystemStatusView::refresh() {
|
||||
status_icons.clear();
|
||||
if (!pmem::ui_hide_camera()) status_icons.add(&button_camera);
|
||||
if (!pmem::ui_hide_sleep()) status_icons.add(&button_sleep);
|
||||
if (!pmem::ui_hide_stealth()) status_icons.add(&button_stealth);
|
||||
if (!pmem::ui_hide_stealth()) status_icons.add(&toggle_stealth);
|
||||
if (!pmem::ui_hide_converter()) status_icons.add(&button_converter);
|
||||
if (!pmem::ui_hide_bias_tee()) status_icons.add(&button_bias_tee);
|
||||
if (!pmem::ui_hide_clock()) status_icons.add(&button_clock_status);
|
||||
if (!pmem::ui_hide_mute()) status_icons.add(&button_mute);
|
||||
if (!pmem::ui_hide_mute()) status_icons.add(&toggle_mute);
|
||||
|
||||
// Display "Disable speaker" icon only if AK4951 Codec which has separate speaker/headphone control
|
||||
if (audio::speaker_disable_supported() && !pmem::ui_hide_speaker())
|
||||
status_icons.add(&button_speaker);
|
||||
if (audio::speaker_disable_supported() && !pmem::ui_hide_speaker()) status_icons.add(&toggle_speaker);
|
||||
|
||||
if (!pmem::ui_hide_sd_card()) status_icons.add(&sd_card_status_view);
|
||||
status_icons.update_layout();
|
||||
|
||||
// Update icon display (try to keep all in on place).
|
||||
// Speaker Enable/Disable (AK4951 boards only)
|
||||
if (pmem::config_speaker_disable()) {
|
||||
button_speaker.set_foreground(Color::light_grey());
|
||||
button_speaker.set_bitmap(&bitmap_icon_speaker_mute);
|
||||
} else {
|
||||
button_speaker.set_foreground(Color::green());
|
||||
button_speaker.set_bitmap(&bitmap_icon_speaker);
|
||||
}
|
||||
|
||||
// Audio Mute (both headphones & speaker)
|
||||
if (pmem::config_audio_mute()) {
|
||||
button_mute.set_foreground(Color::light_grey());
|
||||
button_mute.set_bitmap(&bitmap_icon_speaker_and_headphones_mute);
|
||||
} else {
|
||||
button_mute.set_foreground(Color::green());
|
||||
button_mute.set_bitmap(&bitmap_icon_speaker_and_headphones);
|
||||
}
|
||||
|
||||
// Clock status
|
||||
bool external_clk = portapack::clock_manager.get_reference().source == ClockManager::ReferenceSource::External;
|
||||
button_clock_status.set_bitmap(external_clk ? &bitmap_icon_clk_ext : &bitmap_icon_clk_int);
|
||||
button_clock_status.set_foreground(
|
||||
pmem::clkout_enabled() ? Color::green() : Color::light_grey());
|
||||
button_clock_status.set_foreground(pmem::clkout_enabled() ? Color::green() : Color::light_grey());
|
||||
|
||||
// Antenna DC Bias
|
||||
if (portapack::get_antenna_bias()) {
|
||||
@@ -266,14 +256,9 @@ void SystemStatusView::refresh() {
|
||||
}
|
||||
|
||||
// Converter
|
||||
button_converter.set_bitmap(
|
||||
pmem::config_updown_converter() ? &bitmap_icon_downconvert : &bitmap_icon_upconvert);
|
||||
button_converter.set_bitmap(pmem::config_updown_converter() ? &bitmap_icon_downconvert : &bitmap_icon_upconvert);
|
||||
button_converter.set_foreground(pmem::config_converter() ? Color::red() : Color::light_grey());
|
||||
|
||||
// Stealth
|
||||
button_stealth.set_foreground(
|
||||
pmem::stealth_mode() ? Color::green() : Color::light_grey());
|
||||
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
@@ -314,23 +299,6 @@ void SystemStatusView::on_converter() {
|
||||
refresh();
|
||||
}
|
||||
|
||||
void SystemStatusView::on_speaker() {
|
||||
pmem::set_config_speaker_disable(!pmem::config_speaker_disable());
|
||||
audio::output::update_audio_mute();
|
||||
refresh();
|
||||
}
|
||||
|
||||
void SystemStatusView::on_mute() {
|
||||
pmem::set_config_audio_mute(!pmem::config_audio_mute());
|
||||
audio::output::update_audio_mute();
|
||||
refresh();
|
||||
}
|
||||
|
||||
void SystemStatusView::on_stealth() {
|
||||
pmem::set_stealth_mode(!pmem::stealth_mode());
|
||||
refresh();
|
||||
}
|
||||
|
||||
void SystemStatusView::on_bias_tee() {
|
||||
if (!portapack::get_antenna_bias()) {
|
||||
nav_.display_modal("Bias voltage",
|
||||
@@ -767,7 +735,7 @@ BMPView::BMPView(NavigationView& nav) {
|
||||
}
|
||||
|
||||
void BMPView::paint(Painter&) {
|
||||
if (!portapack::display.drawBMP2({0, 0}, "splash.bmp"))
|
||||
if (!portapack::display.drawBMP2({0, 0}, splash_dot_bmp))
|
||||
portapack::display.drawBMP({(240 - 230) / 2, (320 - 50) / 2 - 10}, splash_bmp, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -184,17 +184,22 @@ class SystemStatusView : public View {
|
||||
|
||||
StatusTray status_icons{{screen_width, 0}};
|
||||
|
||||
// TODO: Convert to ImageToggle buttons.
|
||||
ImageButton button_speaker{
|
||||
ImageToggle toggle_speaker{
|
||||
{0, 0, 2 * 8, 1 * 16},
|
||||
&bitmap_icon_speaker_mute,
|
||||
&bitmap_icon_speaker,
|
||||
Color::light_grey(),
|
||||
Color::dark_grey(),
|
||||
Color::green(),
|
||||
Color::dark_grey()};
|
||||
|
||||
ImageButton button_mute{
|
||||
ImageToggle toggle_mute{
|
||||
{0, 0, 2 * 8, 1 * 16},
|
||||
&bitmap_icon_speaker_and_headphones_mute,
|
||||
&bitmap_icon_speaker_and_headphones,
|
||||
Color::light_grey(),
|
||||
Color::dark_grey(),
|
||||
Color::green(),
|
||||
Color::dark_grey()};
|
||||
|
||||
ImageButton button_converter{
|
||||
@@ -203,11 +208,9 @@ class SystemStatusView : public View {
|
||||
Color::light_grey(),
|
||||
Color::dark_grey()};
|
||||
|
||||
ImageButton button_stealth{
|
||||
ImageToggle toggle_stealth{
|
||||
{0, 0, 2 * 8, 1 * 16},
|
||||
&bitmap_icon_stealth,
|
||||
Color::light_grey(),
|
||||
Color::dark_grey()};
|
||||
&bitmap_icon_stealth};
|
||||
|
||||
ImageButton button_camera{
|
||||
{0, 0, 2 * 8, 1 * 16},
|
||||
@@ -237,9 +240,6 @@ class SystemStatusView : public View {
|
||||
{0, 0 * 16, 2 * 8, 1 * 16}};
|
||||
|
||||
void on_converter();
|
||||
void on_speaker();
|
||||
void on_mute();
|
||||
void on_stealth();
|
||||
void on_bias_tee();
|
||||
void on_camera();
|
||||
void on_title();
|
||||
|
||||
@@ -53,7 +53,9 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) {
|
||||
if (ctcss_detect_enabled) {
|
||||
/* 24kHz int16_t[16]
|
||||
* -> FIR filter, <300Hz pass, >300Hz stop, gain of 1
|
||||
* -> 12kHz int16_t[8] */
|
||||
* -> 12kHz int16_t[8]
|
||||
*
|
||||
* Note we're only processing a small section of the wave each time this fn is called */
|
||||
auto audio_ctcss = ctcss_filter.execute(audio, work_audio_buffer);
|
||||
|
||||
// s16 to f32 for hpf
|
||||
@@ -72,16 +74,18 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) {
|
||||
cur_sample = audio_f[c];
|
||||
if (cur_sample * prev_sample < 0.0) {
|
||||
z_acc += z_timer;
|
||||
z_timer = 0;
|
||||
z_timer = 1;
|
||||
z_count++;
|
||||
} else
|
||||
z_timer++;
|
||||
prev_sample = cur_sample;
|
||||
}
|
||||
|
||||
if (z_count >= 30) {
|
||||
z_filter_count++;
|
||||
if ((z_filter_count >= Z_MIN_FILTER_COUNT) && (z_count >= Z_MIN_ZERO_CROSSINGS)) {
|
||||
ctcss_message.value = (100 * 12000 / 2 * z_count) / z_acc;
|
||||
shared_memory.application_queue.push(ctcss_message);
|
||||
z_filter_count = 0;
|
||||
z_count = 0;
|
||||
z_acc = 0;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,9 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#define Z_MIN_FILTER_COUNT 224
|
||||
#define Z_MIN_ZERO_CROSSINGS 20
|
||||
|
||||
class NarrowbandFMAudio : public BasebandProcessor {
|
||||
public:
|
||||
void execute(const buffer_c8_t& buffer) override;
|
||||
@@ -88,7 +91,7 @@ class NarrowbandFMAudio : public BasebandProcessor {
|
||||
bool pitch_rssi_enabled{false};
|
||||
|
||||
float cur_sample{}, prev_sample{};
|
||||
uint32_t z_acc{0}, z_timer{0}, z_count{0};
|
||||
uint32_t z_acc{0}, z_timer{0}, z_count{0}, z_filter_count{0};
|
||||
bool ctcss_detect_enabled{true};
|
||||
static constexpr float k = 32768.0f;
|
||||
static constexpr float ki = 1.0f / k;
|
||||
|
||||
@@ -412,7 +412,7 @@ void ILI9341::drawBMP(const ui::Point p, const uint8_t* bitmap, const bool trans
|
||||
24bpp RGB
|
||||
32bpp ARGB
|
||||
*/
|
||||
bool ILI9341::drawBMP2(const ui::Point p, const std::string file) {
|
||||
bool ILI9341::drawBMP2(const ui::Point p, const std::filesystem::path& file) {
|
||||
File bmpimage;
|
||||
size_t file_pos = 0;
|
||||
uint16_t pointer = 0;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "ui.hpp"
|
||||
#include "ui_text.hpp"
|
||||
#include "file.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
@@ -58,7 +59,7 @@ class ILI9341 {
|
||||
|
||||
void draw_pixel(const ui::Point p, const ui::Color color);
|
||||
void drawBMP(const ui::Point p, const uint8_t* bitmap, const bool transparency);
|
||||
bool drawBMP2(const ui::Point p, const std::string file);
|
||||
bool drawBMP2(const ui::Point p, const std::filesystem::path& file);
|
||||
void render_line(const ui::Point p, const uint8_t count, const ui::Color* line_buffer);
|
||||
void render_box(const ui::Point p, const ui::Size s, const ui::Color* line_buffer);
|
||||
|
||||
|
||||
@@ -23,27 +23,21 @@
|
||||
#include "portapack_persistent_memory.hpp"
|
||||
|
||||
#include "audio.hpp"
|
||||
#include "portapack.hpp"
|
||||
#include "hal.h"
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include "memory_map.hpp"
|
||||
|
||||
#include "crc.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include "file.hpp"
|
||||
|
||||
#include "hal.h"
|
||||
#include "irq_controls.hpp"
|
||||
|
||||
#include "memory_map.hpp"
|
||||
#include "portapack.hpp"
|
||||
#include "string_format.hpp"
|
||||
#include "ui_styles.hpp"
|
||||
#include "ui_painter.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <utility>
|
||||
|
||||
#include <ch.h>
|
||||
|
||||
@@ -71,9 +65,11 @@ using modem_baudrate_range_t = range_t<int32_t>;
|
||||
constexpr modem_baudrate_range_t modem_baudrate_range{50, 9600};
|
||||
constexpr int32_t modem_baudrate_reset_value{1200};
|
||||
|
||||
/*using modem_bw_range_t = range_t<int32_t>;
|
||||
constexpr modem_bw_range_t modem_bw_range { 1000, 50000 };
|
||||
constexpr int32_t modem_bw_reset_value { 15000 };*/
|
||||
/*
|
||||
using modem_bw_range_t = range_t<int32_t>;
|
||||
constexpr modem_bw_range_t modem_bw_range { 1000, 50000 };
|
||||
constexpr int32_t modem_bw_reset_value { 15000 };
|
||||
*/
|
||||
|
||||
using modem_repeat_range_t = range_t<int32_t>;
|
||||
constexpr modem_repeat_range_t modem_repeat_range{1, 99};
|
||||
@@ -81,176 +77,38 @@ constexpr int32_t modem_repeat_reset_value{5};
|
||||
|
||||
using clkout_freq_range_t = range_t<uint32_t>;
|
||||
constexpr clkout_freq_range_t clkout_freq_range{10, 60000};
|
||||
constexpr uint32_t clkout_freq_reset_value{10000};
|
||||
constexpr uint16_t clkout_freq_reset_value{10000};
|
||||
|
||||
enum data_structure_version_enum : uint32_t {
|
||||
VERSION_CURRENT = 0x10000003,
|
||||
VERSION_CURRENT = 0x10000004,
|
||||
};
|
||||
|
||||
static const uint32_t TOUCH_CALIBRATION_MAGIC = 0x074af82f;
|
||||
|
||||
/* UI config.
|
||||
* NB: Will be default init - override in defaults(). */
|
||||
struct ui_config_t {
|
||||
private:
|
||||
enum bits_t {
|
||||
BacklightTimeoutLSB = 0,
|
||||
BacklightTimeoutEnable = 3,
|
||||
ClkoutFreqLSB = 4,
|
||||
ShowGUIReturnIcon = 20,
|
||||
LoadAppSettings = 21,
|
||||
SaveAppSettings = 22,
|
||||
ShowBiggerQRCode = 23,
|
||||
DisableTouchscreen = 24,
|
||||
HideClock = 25,
|
||||
ClockWithDate = 26,
|
||||
ClkOutEnabled = 27,
|
||||
UNUSED = 28,
|
||||
StealthMode = 29,
|
||||
ConfigLogin = 30,
|
||||
ConfigSplash = 31,
|
||||
};
|
||||
uint16_t clkout_freq;
|
||||
|
||||
enum bits_mask_t : uint32_t {
|
||||
BacklightTimeoutMask = ((1 << 3) - 1) << bits_t::BacklightTimeoutLSB,
|
||||
ClkoutFreqMask = ((1 << 16) - 1) << bits_t::ClkoutFreqLSB,
|
||||
};
|
||||
// NB: bitsfields have to be the same type or the compiler will
|
||||
// split into a new byte hence uint8_t for these booleans.
|
||||
uint8_t backlight_timeout : 3;
|
||||
uint8_t enable_backlight_timeout : 1;
|
||||
uint8_t show_gui_return_icon : 1;
|
||||
uint8_t load_app_settings : 1;
|
||||
uint8_t save_app_settings : 1;
|
||||
uint8_t show_large_qr_code : 1;
|
||||
|
||||
uint32_t values;
|
||||
|
||||
constexpr bool bit_read(const bits_t n) const {
|
||||
return ((values >> n) & 1) != 0;
|
||||
}
|
||||
|
||||
constexpr void bit_write(const bits_t n, const bool v) {
|
||||
if (bit_read(n) != v) {
|
||||
values ^= 1 << n;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
backlight_config_t config_backlight_timer() {
|
||||
const auto timeout_enum = (backlight_timeout_t)((values & bits_mask_t::BacklightTimeoutMask) >> bits_t::BacklightTimeoutLSB);
|
||||
const bool timeout_enabled = bit_read(bits_t::BacklightTimeoutEnable);
|
||||
return backlight_config_t(timeout_enum, timeout_enabled);
|
||||
}
|
||||
|
||||
void set_config_backlight_timer(const backlight_config_t& new_value) {
|
||||
values = (values & ~bits_mask_t::BacklightTimeoutMask) | ((new_value.timeout_enum() << bits_t::BacklightTimeoutLSB) & bits_mask_t::BacklightTimeoutMask);
|
||||
bit_write(bits_t::BacklightTimeoutEnable, new_value.timeout_enabled());
|
||||
}
|
||||
|
||||
constexpr uint32_t clkout_freq() {
|
||||
uint32_t freq = (values & bits_mask_t::ClkoutFreqMask) >> bits_t::ClkoutFreqLSB;
|
||||
if (freq < clkout_freq_range.minimum || freq > clkout_freq_range.maximum) {
|
||||
values = (values & ~bits_mask_t::ClkoutFreqMask) | (clkout_freq_reset_value << bits_t::ClkoutFreqLSB);
|
||||
return clkout_freq_reset_value;
|
||||
} else {
|
||||
return freq;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void set_clkout_freq(uint32_t freq) {
|
||||
values = (values & ~bits_mask_t::ClkoutFreqMask) | (clkout_freq_range.clip(freq) << bits_t::ClkoutFreqLSB);
|
||||
}
|
||||
|
||||
// ui_config is an uint32_t var storing information bitwise
|
||||
// bits 0-2 store the backlight timer
|
||||
// bits 4-19 (16 bits) store the clkout frequency
|
||||
// bits 21-31 store the different single bit configs depicted below
|
||||
// bit 20 store the display state of the gui return icon, hidden (0) or shown (1)
|
||||
|
||||
constexpr bool show_gui_return_icon() const { // add return icon in touchscreen menue
|
||||
return bit_read(bits_t::ShowGUIReturnIcon);
|
||||
}
|
||||
|
||||
constexpr void set_gui_return_icon(bool v) {
|
||||
bit_write(bits_t::ShowGUIReturnIcon, v);
|
||||
}
|
||||
|
||||
constexpr bool load_app_settings() const { // load (last saved) app settings on startup of app
|
||||
return bit_read(bits_t::LoadAppSettings);
|
||||
}
|
||||
|
||||
constexpr void set_load_app_settings(bool v) {
|
||||
bit_write(bits_t::LoadAppSettings, v);
|
||||
}
|
||||
|
||||
constexpr bool save_app_settings() const { // save app settings when closing app
|
||||
return bit_read(bits_t::SaveAppSettings);
|
||||
}
|
||||
|
||||
constexpr void set_save_app_settings(bool v) {
|
||||
bit_write(bits_t::SaveAppSettings, v);
|
||||
}
|
||||
|
||||
constexpr bool show_bigger_qr_code() const { // show bigger QR code
|
||||
return bit_read(bits_t::ShowBiggerQRCode);
|
||||
}
|
||||
|
||||
constexpr void set_show_bigger_qr_code(bool v) {
|
||||
bit_write(bits_t::ShowBiggerQRCode, v);
|
||||
}
|
||||
|
||||
constexpr bool disable_touchscreen() const { // Option to disable touch screen
|
||||
return bit_read(bits_t::DisableTouchscreen);
|
||||
}
|
||||
|
||||
constexpr void set_disable_touchscreen(bool v) {
|
||||
bit_write(bits_t::DisableTouchscreen, v);
|
||||
}
|
||||
|
||||
constexpr bool hide_clock() const { // clock hidden from main menu
|
||||
return bit_read(bits_t::HideClock);
|
||||
}
|
||||
|
||||
constexpr void set_clock_hidden(bool v) {
|
||||
bit_write(bits_t::HideClock, v);
|
||||
}
|
||||
|
||||
constexpr bool clock_with_date() const { // show clock with date, if not hidden
|
||||
return bit_read(bits_t::ClockWithDate);
|
||||
}
|
||||
|
||||
constexpr void set_clock_with_date(bool v) {
|
||||
bit_write(bits_t::ClockWithDate, v);
|
||||
}
|
||||
|
||||
constexpr bool clkout_enabled() const {
|
||||
return bit_read(bits_t::ClkOutEnabled);
|
||||
}
|
||||
|
||||
constexpr void set_clkout_enabled(bool v) {
|
||||
bit_write(bits_t::ClkOutEnabled, v);
|
||||
}
|
||||
|
||||
constexpr bool stealth_mode() const {
|
||||
return bit_read(bits_t::StealthMode);
|
||||
}
|
||||
|
||||
constexpr void set_stealth_mode(bool v) {
|
||||
bit_write(bits_t::StealthMode, v);
|
||||
}
|
||||
|
||||
constexpr bool config_login() const {
|
||||
return bit_read(bits_t::ConfigLogin);
|
||||
}
|
||||
|
||||
constexpr void set_config_login(bool v) {
|
||||
bit_write(bits_t::ConfigLogin, v);
|
||||
}
|
||||
|
||||
constexpr bool config_splash() const {
|
||||
return bit_read(bits_t::ConfigSplash);
|
||||
}
|
||||
|
||||
constexpr void set_config_splash(bool v) {
|
||||
bit_write(bits_t::ConfigSplash, v);
|
||||
}
|
||||
|
||||
constexpr ui_config_t()
|
||||
: values(
|
||||
(1 << ConfigSplash) | (clkout_freq_reset_value << ClkoutFreqLSB) | (7 << BacklightTimeoutLSB)) {
|
||||
}
|
||||
bool disable_touchscreen : 1;
|
||||
bool hide_clock : 1;
|
||||
bool clock_show_date : 1;
|
||||
bool clkout_enabled : 1;
|
||||
bool UNUSED_1 : 1;
|
||||
bool stealth_mode : 1;
|
||||
bool config_login : 1;
|
||||
bool config_splash : 1;
|
||||
};
|
||||
static_assert(sizeof(ui_config_t) == sizeof(uint32_t));
|
||||
|
||||
/* Additional UI config.
|
||||
* NB: Will be default init - override in defaults(). */
|
||||
@@ -266,67 +124,48 @@ struct ui_config2_t {
|
||||
bool hide_sd_card : 1;
|
||||
|
||||
bool hide_mute : 1;
|
||||
bool UNUSED : 7;
|
||||
bool UNUSED_1 : 1;
|
||||
bool UNUSED_2 : 1;
|
||||
bool UNUSED_3 : 1;
|
||||
bool UNUSED_4 : 1;
|
||||
bool UNUSED_5 : 1;
|
||||
bool UNUSED_6 : 1;
|
||||
bool UNUSED_7 : 1;
|
||||
|
||||
uint8_t placeholder_1;
|
||||
uint8_t placeholder_2;
|
||||
uint8_t PLACEHOLDER_2;
|
||||
uint8_t PLACEHOLDER_3;
|
||||
};
|
||||
static_assert(sizeof(ui_config2_t) == sizeof(uint32_t));
|
||||
|
||||
/* Additional config.
|
||||
* NB: Will be default init - override in defaults(). */
|
||||
struct misc_config_t {
|
||||
private:
|
||||
enum bits_t {
|
||||
ConfigAudioMute = 0,
|
||||
ConfigSpeakerDisable = 1,
|
||||
};
|
||||
bool mute_audio : 1;
|
||||
bool disable_speaker : 1;
|
||||
bool UNUSED_2 : 1;
|
||||
bool UNUSED_3 : 1;
|
||||
bool UNUSED_4 : 1;
|
||||
bool UNUSED_5 : 1;
|
||||
bool UNUSED_6 : 1;
|
||||
bool UNUSED_7 : 1;
|
||||
|
||||
// misc_config_t bits:
|
||||
// ConfigAudioMute = set to mute all audio output (speakers & headphones)
|
||||
// ConfigSpeakerDisable = set to disable only the speaker and leave headphones enabled (only supported on AK4951 codec)
|
||||
|
||||
uint32_t values;
|
||||
|
||||
constexpr bool bit_read(const bits_t n) const {
|
||||
return ((values >> n) & 1) != 0;
|
||||
}
|
||||
|
||||
constexpr void bit_write(const bits_t n, const bool v) {
|
||||
if (bit_read(n) != v) {
|
||||
values ^= 1 << n;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr bool config_audio_mute() const {
|
||||
return bit_read(bits_t::ConfigAudioMute);
|
||||
}
|
||||
|
||||
constexpr void set_config_audio_mute(bool v) {
|
||||
bit_write(bits_t::ConfigAudioMute, v);
|
||||
}
|
||||
|
||||
constexpr bool config_speaker_disable() const {
|
||||
return bit_read(bits_t::ConfigSpeakerDisable);
|
||||
}
|
||||
|
||||
constexpr void set_config_speaker_disable(bool v) {
|
||||
bit_write(bits_t::ConfigSpeakerDisable, v);
|
||||
}
|
||||
|
||||
constexpr misc_config_t()
|
||||
: values(0) {
|
||||
}
|
||||
uint8_t PLACEHOLDER_1;
|
||||
uint8_t PLACEHOLDER_2;
|
||||
uint8_t PLACEHOLDER_3;
|
||||
};
|
||||
static_assert(sizeof(misc_config_t) == sizeof(uint32_t));
|
||||
|
||||
/* IMPORTANT: Report your changes here in the dump_persistent_memory function a few lines later !! */
|
||||
/* IMPORTANT: Update dump_persistent_memory (below) when changing data_t. */
|
||||
|
||||
/* Struct must pack the same way on M4 and M0 cores.
|
||||
* NB: When adding new members, keep 32bit-aligned.*/
|
||||
|
||||
/* struct must pack the same way on M4 and M0 cores. */
|
||||
struct data_t {
|
||||
data_structure_version_enum structure_version;
|
||||
int64_t target_frequency;
|
||||
int32_t correction_ppb;
|
||||
uint32_t touch_calibration_magic;
|
||||
touch::Calibration touch_calibration;
|
||||
touch::Calibration touch_calibration; // 7 * 32 bits.
|
||||
|
||||
// Modem
|
||||
uint32_t modem_def_index;
|
||||
@@ -337,7 +176,7 @@ struct data_t {
|
||||
int32_t modem_baudrate;
|
||||
int32_t modem_repeat;
|
||||
|
||||
// Play dead unlock
|
||||
// Play dead unlock (Used?)
|
||||
uint32_t playdead_magic;
|
||||
uint32_t playing_dead;
|
||||
uint32_t playdead_sequence;
|
||||
@@ -356,26 +195,30 @@ struct data_t {
|
||||
// Recon App
|
||||
uint64_t recon_config;
|
||||
|
||||
bool placeholder_0;
|
||||
|
||||
// enable or disable converter
|
||||
bool converter;
|
||||
// set up converter (false) or down converter (true) converter
|
||||
bool updown_converter;
|
||||
bool updown_frequency_rx_correction;
|
||||
bool updown_frequency_tx_correction;
|
||||
bool UNUSED_4 : 1;
|
||||
bool UNUSED_5 : 1;
|
||||
bool UNUSED_6 : 1;
|
||||
bool UNUSED_7 : 1;
|
||||
|
||||
// up/down converter offset
|
||||
int64_t converter_frequency_offset;
|
||||
|
||||
// frequency correction
|
||||
uint32_t frequency_rx_correction;
|
||||
bool updown_frequency_rx_correction;
|
||||
uint32_t frequency_tx_correction;
|
||||
bool updown_frequency_tx_correction;
|
||||
|
||||
// Rotary encoder dial sensitivity (encoder.cpp/hpp)
|
||||
uint8_t encoder_dial_sensitivity;
|
||||
uint16_t encoder_dial_sensitivity : 4;
|
||||
uint16_t UNUSED_8 : 12;
|
||||
|
||||
// Headphone volume in centibels. (Only really needs 10 bits)
|
||||
int32_t headphone_volume_cb;
|
||||
// Headphone volume in centibels.
|
||||
int16_t headphone_volume_cb;
|
||||
|
||||
// Misc flags
|
||||
misc_config_t misc_config;
|
||||
@@ -411,15 +254,23 @@ struct data_t {
|
||||
|
||||
hardware_config(0),
|
||||
recon_config(0),
|
||||
placeholder_0(0),
|
||||
converter(0),
|
||||
updown_converter(0),
|
||||
|
||||
converter(false),
|
||||
updown_converter(false),
|
||||
updown_frequency_rx_correction(false),
|
||||
updown_frequency_tx_correction(false),
|
||||
UNUSED_4(false),
|
||||
UNUSED_5(false),
|
||||
UNUSED_6(false),
|
||||
UNUSED_7(false),
|
||||
|
||||
converter_frequency_offset(0),
|
||||
|
||||
frequency_rx_correction(0),
|
||||
updown_frequency_rx_correction(0),
|
||||
frequency_tx_correction(0),
|
||||
updown_frequency_tx_correction(0),
|
||||
|
||||
encoder_dial_sensitivity(0),
|
||||
UNUSED_8(0),
|
||||
headphone_volume_cb(-600),
|
||||
misc_config(),
|
||||
ui_config2() {
|
||||
@@ -510,7 +361,10 @@ namespace cache {
|
||||
void defaults() {
|
||||
cached_backup_ram = backup_ram_t();
|
||||
|
||||
// defaults values for recon app
|
||||
set_config_backlight_timer(backlight_config_t{});
|
||||
set_config_splash(true);
|
||||
|
||||
// Default values for recon app.
|
||||
set_recon_autosave_freqs(false);
|
||||
set_recon_autostart_recon(true);
|
||||
set_recon_continuous(true);
|
||||
@@ -626,14 +480,16 @@ void set_modem_baudrate(const int32_t new_value) {
|
||||
data->modem_baudrate = modem_baudrate_range.clip(new_value);
|
||||
}
|
||||
|
||||
/*int32_t modem_bw() {
|
||||
modem_bw_range.reset_if_outside(data->modem_bw, modem_bw_reset_value);
|
||||
return data->modem_bw;
|
||||
}
|
||||
/*
|
||||
int32_t modem_bw() {
|
||||
modem_bw_range.reset_if_outside(data->modem_bw, modem_bw_reset_value);
|
||||
return data->modem_bw;
|
||||
}
|
||||
|
||||
void set_modem_bw(const int32_t new_value) {
|
||||
data->modem_bw = modem_bw_range.clip(new_value);
|
||||
}*/
|
||||
void set_modem_bw(const int32_t new_value) {
|
||||
data->modem_bw = modem_bw_range.clip(new_value);
|
||||
}
|
||||
*/
|
||||
|
||||
uint8_t modem_repeat() {
|
||||
modem_repeat_range.reset_if_outside(data->modem_repeat, modem_repeat_reset_value);
|
||||
@@ -652,56 +508,56 @@ void set_serial_format(const serial_format_t new_value) {
|
||||
data->serial_format = new_value;
|
||||
}
|
||||
|
||||
bool show_gui_return_icon() { // add return icon in touchscreen menue
|
||||
return data->ui_config.show_gui_return_icon();
|
||||
bool show_gui_return_icon() { // add return icon in touchscreen menu
|
||||
return data->ui_config.show_gui_return_icon != 0;
|
||||
}
|
||||
|
||||
bool load_app_settings() { // load (last saved) app settings on startup of app
|
||||
return data->ui_config.load_app_settings();
|
||||
return data->ui_config.load_app_settings != 0;
|
||||
}
|
||||
|
||||
bool save_app_settings() { // save app settings when closing app
|
||||
return data->ui_config.save_app_settings();
|
||||
return data->ui_config.save_app_settings != 0;
|
||||
}
|
||||
|
||||
bool show_bigger_qr_code() { // show bigger QR code
|
||||
return data->ui_config.show_bigger_qr_code();
|
||||
return data->ui_config.show_large_qr_code != 0;
|
||||
}
|
||||
|
||||
bool disable_touchscreen() { // Option to disable touch screen
|
||||
return data->ui_config.disable_touchscreen();
|
||||
return data->ui_config.disable_touchscreen;
|
||||
}
|
||||
|
||||
bool hide_clock() { // clock hidden from main menu
|
||||
return data->ui_config.hide_clock();
|
||||
bool hide_clock() { // Hide clock from main menu
|
||||
return data->ui_config.hide_clock;
|
||||
}
|
||||
|
||||
bool clock_with_date() { // show clock with date, if not hidden
|
||||
return data->ui_config.clock_with_date();
|
||||
bool clock_with_date() { // Show clock with date, if not hidden
|
||||
return data->ui_config.clock_show_date;
|
||||
}
|
||||
|
||||
bool clkout_enabled() {
|
||||
return data->ui_config.clkout_enabled();
|
||||
return data->ui_config.clkout_enabled;
|
||||
}
|
||||
|
||||
bool config_audio_mute() {
|
||||
return data->misc_config.config_audio_mute();
|
||||
return data->misc_config.mute_audio;
|
||||
}
|
||||
|
||||
bool config_speaker_disable() {
|
||||
return data->misc_config.config_speaker_disable();
|
||||
return data->misc_config.disable_speaker;
|
||||
}
|
||||
|
||||
bool stealth_mode() {
|
||||
return data->ui_config.stealth_mode();
|
||||
return data->ui_config.stealth_mode;
|
||||
}
|
||||
|
||||
bool config_login() {
|
||||
return data->ui_config.config_login();
|
||||
return data->ui_config.config_login;
|
||||
}
|
||||
|
||||
bool config_splash() {
|
||||
return data->ui_config.config_splash();
|
||||
return data->ui_config.config_splash;
|
||||
}
|
||||
|
||||
uint8_t config_cpld() {
|
||||
@@ -709,59 +565,60 @@ uint8_t config_cpld() {
|
||||
}
|
||||
|
||||
backlight_config_t config_backlight_timer() {
|
||||
return data->ui_config.config_backlight_timer();
|
||||
return {static_cast<backlight_timeout_t>(data->ui_config.backlight_timeout),
|
||||
data->ui_config.enable_backlight_timeout == 1};
|
||||
}
|
||||
|
||||
void set_gui_return_icon(bool v) {
|
||||
data->ui_config.set_gui_return_icon(v);
|
||||
data->ui_config.show_gui_return_icon = v ? 1 : 0;
|
||||
}
|
||||
|
||||
void set_load_app_settings(bool v) {
|
||||
data->ui_config.set_load_app_settings(v);
|
||||
data->ui_config.load_app_settings = v ? 1 : 0;
|
||||
}
|
||||
|
||||
void set_save_app_settings(bool v) {
|
||||
data->ui_config.set_save_app_settings(v);
|
||||
data->ui_config.save_app_settings = v ? 1 : 0;
|
||||
}
|
||||
|
||||
void set_show_bigger_qr_code(bool v) {
|
||||
data->ui_config.set_show_bigger_qr_code(v);
|
||||
data->ui_config.show_large_qr_code = v ? 1 : 0;
|
||||
}
|
||||
|
||||
void set_disable_touchscreen(bool v) {
|
||||
data->ui_config.set_disable_touchscreen(v);
|
||||
data->ui_config.disable_touchscreen = v;
|
||||
}
|
||||
|
||||
void set_clock_hidden(bool v) {
|
||||
data->ui_config.set_clock_hidden(v);
|
||||
data->ui_config.hide_clock = v;
|
||||
}
|
||||
|
||||
void set_clock_with_date(bool v) {
|
||||
data->ui_config.set_clock_with_date(v);
|
||||
data->ui_config.clock_show_date = v;
|
||||
}
|
||||
|
||||
void set_clkout_enabled(bool v) {
|
||||
data->ui_config.set_clkout_enabled(v);
|
||||
data->ui_config.clkout_enabled = v;
|
||||
}
|
||||
|
||||
void set_config_audio_mute(bool v) {
|
||||
data->misc_config.set_config_audio_mute(v);
|
||||
data->misc_config.mute_audio = v;
|
||||
}
|
||||
|
||||
void set_config_speaker_disable(bool v) {
|
||||
data->misc_config.set_config_speaker_disable(v);
|
||||
data->misc_config.disable_speaker = v;
|
||||
}
|
||||
|
||||
void set_stealth_mode(bool v) {
|
||||
data->ui_config.set_stealth_mode(v);
|
||||
data->ui_config.stealth_mode = v;
|
||||
}
|
||||
|
||||
void set_config_login(bool v) {
|
||||
data->ui_config.set_config_login(v);
|
||||
data->ui_config.config_login = v;
|
||||
}
|
||||
|
||||
void set_config_splash(bool v) {
|
||||
data->ui_config.set_config_splash(v);
|
||||
data->ui_config.config_splash = v;
|
||||
}
|
||||
|
||||
void set_config_cpld(uint8_t i) {
|
||||
@@ -769,7 +626,8 @@ void set_config_cpld(uint8_t i) {
|
||||
}
|
||||
|
||||
void set_config_backlight_timer(const backlight_config_t& new_value) {
|
||||
data->ui_config.set_config_backlight_timer(new_value);
|
||||
data->ui_config.backlight_timeout = static_cast<uint8_t>(new_value.timeout_enum());
|
||||
data->ui_config.enable_backlight_timeout = static_cast<uint8_t>(new_value.timeout_enabled());
|
||||
}
|
||||
|
||||
uint32_t pocsag_last_address() {
|
||||
@@ -788,12 +646,17 @@ void set_pocsag_ignore_address(uint32_t address) {
|
||||
data->pocsag_ignore_address = address;
|
||||
}
|
||||
|
||||
uint32_t clkout_freq() {
|
||||
return data->ui_config.clkout_freq();
|
||||
uint16_t clkout_freq() {
|
||||
auto freq = data->ui_config.clkout_freq;
|
||||
|
||||
if (freq < clkout_freq_range.minimum || freq > clkout_freq_range.maximum)
|
||||
set_clkout_freq(clkout_freq_reset_value);
|
||||
|
||||
return data->ui_config.clkout_freq;
|
||||
}
|
||||
|
||||
void set_clkout_freq(uint32_t freq) {
|
||||
data->ui_config.set_clkout_freq(freq);
|
||||
void set_clkout_freq(uint16_t freq) {
|
||||
data->ui_config.clkout_freq = freq;
|
||||
}
|
||||
|
||||
/* Recon app */
|
||||
@@ -982,26 +845,23 @@ bool should_use_sdcard_for_pmem() {
|
||||
}
|
||||
|
||||
int save_persistent_settings_to_file() {
|
||||
std::string filename = PMEM_SETTING_FILE;
|
||||
delete_file(filename);
|
||||
File outfile;
|
||||
auto result = outfile.create(filename);
|
||||
if (result.is_valid()) {
|
||||
auto error = outfile.create(PMEM_SETTING_FILE);
|
||||
if (error)
|
||||
return false;
|
||||
}
|
||||
|
||||
outfile.write(reinterpret_cast<char*>(&cached_backup_ram), sizeof(backup_ram_t));
|
||||
return true;
|
||||
}
|
||||
|
||||
int load_persistent_settings_from_file() {
|
||||
std::string filename = PMEM_SETTING_FILE;
|
||||
File infile;
|
||||
auto result = infile.open(filename);
|
||||
if (!result.is_valid()) {
|
||||
infile.read(reinterpret_cast<char*>(&cached_backup_ram), sizeof(backup_ram_t));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
auto error = infile.open(PMEM_SETTING_FILE);
|
||||
if (error)
|
||||
return false;
|
||||
|
||||
infile.read(reinterpret_cast<char*>(&cached_backup_ram), sizeof(backup_ram_t));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pmem size helper
|
||||
@@ -1057,33 +917,37 @@ bool debug_dump() {
|
||||
pmem_dump_file.write_line("tone_mix: " + to_string_dec_uint(data->tone_mix));
|
||||
pmem_dump_file.write_line("hardware_config: " + to_string_dec_uint(data->hardware_config));
|
||||
pmem_dump_file.write_line("recon_config: 0x" + to_string_hex(data->recon_config, 16));
|
||||
pmem_dump_file.write_line("placeholder_0: " + to_string_dec_int(data->placeholder_0));
|
||||
pmem_dump_file.write_line("converter: " + to_string_dec_int(data->converter));
|
||||
pmem_dump_file.write_line("updown_converter: " + to_string_dec_int(data->updown_converter));
|
||||
pmem_dump_file.write_line("updown_frequency_rx_correction: " + to_string_dec_int(data->updown_frequency_rx_correction));
|
||||
pmem_dump_file.write_line("updown_frequency_tx_correction: " + to_string_dec_int(data->updown_frequency_tx_correction));
|
||||
// pmem_dump_file.write_line("UNUSED_4: " + to_string_dec_int(data->UNUSED_4));
|
||||
// pmem_dump_file.write_line("UNUSED_5: " + to_string_dec_int(data->UNUSED_5));
|
||||
// pmem_dump_file.write_line("UNUSED_6: " + to_string_dec_int(data->UNUSED_6));
|
||||
// pmem_dump_file.write_line("UNUSED_7: " + to_string_dec_int(data->UNUSED_7));
|
||||
pmem_dump_file.write_line("converter_frequency_offset: " + to_string_dec_int(data->converter_frequency_offset));
|
||||
pmem_dump_file.write_line("frequency_rx_correction: " + to_string_dec_uint(data->frequency_rx_correction));
|
||||
pmem_dump_file.write_line("updown_frequency_rx_correction: " + to_string_dec_int(data->updown_frequency_rx_correction));
|
||||
pmem_dump_file.write_line("frequency_tx_correction: " + to_string_dec_uint(data->frequency_tx_correction));
|
||||
pmem_dump_file.write_line("updown_frequency_tx_correction: " + to_string_dec_int(data->updown_frequency_tx_correction));
|
||||
pmem_dump_file.write_line("encoder_dial_sensitivity: " + to_string_dec_uint(data->encoder_dial_sensitivity));
|
||||
// pmem_dump_file.write_line("UNUSED_8: " + to_string_dec_uint(data->UNUSED_8));
|
||||
pmem_dump_file.write_line("headphone_volume_cb: " + to_string_dec_int(data->headphone_volume_cb));
|
||||
|
||||
// ui_config bits
|
||||
const auto backlight_timer = portapack::persistent_memory::config_backlight_timer();
|
||||
pmem_dump_file.write_line("ui_config clkout_freq: " + to_string_dec_uint(clkout_freq()));
|
||||
pmem_dump_file.write_line("ui_config backlight_timer.timeout_enabled: " + to_string_dec_uint(backlight_timer.timeout_enabled()));
|
||||
pmem_dump_file.write_line("ui_config backlight_timer.timeout_seconds: " + to_string_dec_uint(backlight_timer.timeout_seconds()));
|
||||
pmem_dump_file.write_line("ui_config clkout_freq: " + to_string_dec_uint(clkout_freq()));
|
||||
pmem_dump_file.write_line("ui_config show_gui_return_icon: " + to_string_dec_uint(data->ui_config.show_gui_return_icon()));
|
||||
pmem_dump_file.write_line("ui_config load_app_settings: " + to_string_dec_uint(data->ui_config.load_app_settings()));
|
||||
pmem_dump_file.write_line("ui_config save_app_settings: " + to_string_dec_uint(data->ui_config.save_app_settings()));
|
||||
pmem_dump_file.write_line("ui_config show_bigger_qr_code: " + to_string_dec_uint(data->ui_config.show_bigger_qr_code()));
|
||||
pmem_dump_file.write_line("ui_config disable_touchscreen: " + to_string_dec_uint(data->ui_config.disable_touchscreen()));
|
||||
pmem_dump_file.write_line("ui_config hide_clock: " + to_string_dec_uint(data->ui_config.hide_clock()));
|
||||
pmem_dump_file.write_line("ui_config clock_with_date: " + to_string_dec_uint(data->ui_config.clock_with_date()));
|
||||
pmem_dump_file.write_line("ui_config clkout_enabled: " + to_string_dec_uint(data->ui_config.clkout_enabled()));
|
||||
pmem_dump_file.write_line("ui_config stealth_mode: " + to_string_dec_uint(data->ui_config.stealth_mode()));
|
||||
pmem_dump_file.write_line("ui_config config_login: " + to_string_dec_uint(data->ui_config.config_login()));
|
||||
pmem_dump_file.write_line("ui_config config_splash: " + to_string_dec_uint(data->ui_config.config_splash()));
|
||||
pmem_dump_file.write_line("ui_config show_gui_return_icon: " + to_string_dec_uint(data->ui_config.show_gui_return_icon));
|
||||
pmem_dump_file.write_line("ui_config load_app_settings: " + to_string_dec_uint(data->ui_config.load_app_settings));
|
||||
pmem_dump_file.write_line("ui_config save_app_settings: " + to_string_dec_uint(data->ui_config.save_app_settings));
|
||||
pmem_dump_file.write_line("ui_config show_bigger_qr_code: " + to_string_dec_uint(data->ui_config.show_large_qr_code));
|
||||
pmem_dump_file.write_line("ui_config disable_touchscreen: " + to_string_dec_uint(data->ui_config.disable_touchscreen));
|
||||
pmem_dump_file.write_line("ui_config hide_clock: " + to_string_dec_uint(data->ui_config.hide_clock));
|
||||
pmem_dump_file.write_line("ui_config clock_with_date: " + to_string_dec_uint(data->ui_config.clock_show_date));
|
||||
pmem_dump_file.write_line("ui_config clkout_enabled: " + to_string_dec_uint(data->ui_config.clkout_enabled));
|
||||
pmem_dump_file.write_line("ui_config stealth_mode: " + to_string_dec_uint(data->ui_config.stealth_mode));
|
||||
pmem_dump_file.write_line("ui_config config_login: " + to_string_dec_uint(data->ui_config.config_login));
|
||||
pmem_dump_file.write_line("ui_config config_splash: " + to_string_dec_uint(data->ui_config.config_splash));
|
||||
|
||||
// ui_config2 bits
|
||||
pmem_dump_file.write_line("ui_config2 hide_speaker: " + to_string_dec_uint(data->ui_config2.hide_speaker));
|
||||
@@ -1137,8 +1001,6 @@ bool debug_dump() {
|
||||
// transmitter_model
|
||||
pmem_dump_file.write_line("\n[Transmitter Model]");
|
||||
pmem_dump_file.write_line("target_frequency: " + to_string_dec_uint(transmitter_model.target_frequency()));
|
||||
pmem_dump_file.write_line("lna: " + to_string_dec_int(transmitter_model.lna()));
|
||||
pmem_dump_file.write_line("vga: " + to_string_dec_int(transmitter_model.vga()));
|
||||
pmem_dump_file.write_line("rf_amp: " + to_string_dec_int(transmitter_model.rf_amp()));
|
||||
pmem_dump_file.write_line("baseband_bandwidth: " + to_string_dec_uint(transmitter_model.baseband_bandwidth()));
|
||||
pmem_dump_file.write_line("sampling_rate: " + to_string_dec_uint(transmitter_model.sampling_rate()));
|
||||
|
||||
@@ -34,9 +34,10 @@
|
||||
#include "volume.hpp"
|
||||
|
||||
// persistant memory from/to sdcard flag file
|
||||
#define PMEM_FILEFLAG "/SETTINGS/PMEM_FILEFLAG"
|
||||
#define PMEM_FILEFLAG u"/SETTINGS/PMEM_FILEFLAG"
|
||||
|
||||
// persistant memory from/to sdcard flag file
|
||||
#define PMEM_SETTING_FILE "/SETTINGS/pmem_settings"
|
||||
#define PMEM_SETTING_FILE u"/SETTINGS/pmem_settings"
|
||||
|
||||
using namespace modems;
|
||||
using namespace serializer;
|
||||
@@ -225,8 +226,8 @@ void set_pocsag_ignore_address(uint32_t address);
|
||||
|
||||
bool clkout_enabled();
|
||||
void set_clkout_enabled(bool v);
|
||||
uint32_t clkout_freq();
|
||||
void set_clkout_freq(uint32_t freq);
|
||||
uint16_t clkout_freq();
|
||||
void set_clkout_freq(uint16_t freq);
|
||||
|
||||
/* Recon app */
|
||||
bool recon_autosave_freqs();
|
||||
|
||||
@@ -1524,6 +1524,24 @@ void OptionsField::set_by_value(value_t v) {
|
||||
set_selected_index(0);
|
||||
}
|
||||
|
||||
void OptionsField::set_by_nearest_value(value_t v) {
|
||||
size_t new_index = 0;
|
||||
size_t curr_index = 0;
|
||||
int32_t min_diff = INT32_MAX;
|
||||
|
||||
for (const auto& option : options) {
|
||||
auto diff = abs(v - option.second);
|
||||
if (diff < min_diff) {
|
||||
min_diff = diff;
|
||||
new_index = curr_index;
|
||||
}
|
||||
|
||||
curr_index++;
|
||||
}
|
||||
|
||||
set_selected_index(new_index);
|
||||
}
|
||||
|
||||
void OptionsField::set_options(options_t new_options) {
|
||||
options = new_options;
|
||||
|
||||
|
||||
@@ -624,6 +624,7 @@ class OptionsField : public Widget {
|
||||
void set_selected_index(const size_t new_index, bool trigger_change = true);
|
||||
|
||||
void set_by_value(value_t v);
|
||||
void set_by_nearest_value(value_t v);
|
||||
|
||||
void paint(Painter& painter) override;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user