diff --git a/firmware/application/app_settings.cpp b/firmware/application/app_settings.cpp index dc0c8dd7..40d75f0b 100644 --- a/firmware/application/app_settings.cpp +++ b/firmware/application/app_settings.cpp @@ -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)) { diff --git a/firmware/application/apps/analog_audio_app.cpp b/firmware/application/apps/analog_audio_app.cpp index 381871c2..23fba65c 100644 --- a/firmware/application/apps/analog_audio_app.cpp +++ b/firmware/application/apps/analog_audio_app.cpp @@ -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; } diff --git a/firmware/application/apps/analog_audio_app.hpp b/firmware/application/apps/analog_audio_app.hpp index b3a75f2b..271a3eb7 100644 --- a/firmware/application/apps/analog_audio_app.hpp +++ b/firmware/application/apps/analog_audio_app.hpp @@ -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; diff --git a/firmware/application/apps/capture_app.cpp b/firmware/application/apps/capture_app.cpp index d93c299f..16e6cbe5 100644 --- a/firmware/application/apps/capture_app.cpp +++ b/firmware/application/apps/capture_app.cpp @@ -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(); } diff --git a/firmware/application/apps/capture_app.hpp b/firmware/application/apps/capture_app.hpp index 62e973e4..963ce554 100644 --- a/firmware/application/apps/capture_app.hpp +++ b/firmware/application/apps/capture_app.hpp @@ -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}; diff --git a/firmware/application/apps/ert_app.hpp b/firmware/application/apps/ert_app.hpp index 58104696..ec80098e 100644 --- a/firmware/application/apps/ert_app.hpp +++ b/firmware/application/apps/ert_app.hpp @@ -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}; diff --git a/firmware/application/apps/pocsag_app.cpp b/firmware/application/apps/pocsag_app.cpp index 869911cc..5180e1ec 100644 --- a/firmware/application/apps/pocsag_app.cpp +++ b/firmware/application/apps/pocsag_app.cpp @@ -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? diff --git a/firmware/application/apps/tpms_app.hpp b/firmware/application/apps/tpms_app.hpp index bc071c5b..f2e72aa2 100644 --- a/firmware/application/apps/tpms_app.hpp +++ b/firmware/application/apps/tpms_app.hpp @@ -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}; diff --git a/firmware/application/apps/ui_adsb_rx.cpp b/firmware/application/apps/ui_adsb_rx.cpp index 7607403d..e7924be1 100644 --- a/firmware/application/apps/ui_adsb_rx.cpp +++ b/firmware/application/apps/ui_adsb_rx.cpp @@ -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(); } diff --git a/firmware/application/apps/ui_adsb_rx.hpp b/firmware/application/apps/ui_adsb_rx.hpp index 8ee05862..57d8fa64 100644 --- a/firmware/application/apps/ui_adsb_rx.hpp +++ b/firmware/application/apps/ui_adsb_rx.hpp @@ -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}; diff --git a/firmware/application/apps/ui_afsk_rx.cpp b/firmware/application/apps/ui_afsk_rx.cpp index 38674ada..d1253811 100644 --- a/firmware/application/apps/ui_afsk_rx.cpp +++ b/firmware/application/apps/ui_afsk_rx.cpp @@ -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(); } diff --git a/firmware/application/apps/ui_aprs_rx.cpp b/firmware/application/apps/ui_aprs_rx.cpp index 09d98b94..414bd44f 100644 --- a/firmware/application/apps/ui_aprs_rx.cpp +++ b/firmware/application/apps/ui_aprs_rx.cpp @@ -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(); } diff --git a/firmware/application/apps/ui_btle_rx.cpp b/firmware/application/apps/ui_btle_rx.cpp index bdf5601f..b9954dc3 100644 --- a/firmware/application/apps/ui_btle_rx.cpp +++ b/firmware/application/apps/ui_btle_rx.cpp @@ -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(); } diff --git a/firmware/application/apps/ui_btle_rx.hpp b/firmware/application/apps/ui_btle_rx.hpp index 0acb543f..4bdb993e 100644 --- a/firmware/application/apps/ui_btle_rx.hpp +++ b/firmware/application/apps/ui_btle_rx.hpp @@ -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}; diff --git a/firmware/application/apps/ui_looking_glass_app.cpp b/firmware/application/apps/ui_looking_glass_app.cpp index 7cd36f7e..8f88b08a 100644 --- a/firmware/application/apps/ui_looking_glass_app.cpp +++ b/firmware/application/apps/ui_looking_glass_app.cpp @@ -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(); // 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(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(); // 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(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); diff --git a/firmware/application/apps/ui_looking_glass_app.hpp b/firmware/application/apps/ui_looking_glass_app.hpp index 823d7990..0a6b1669 100644 --- a/firmware/application/apps/ui_looking_glass_app.hpp +++ b/firmware/application/apps/ui_looking_glass_app.hpp @@ -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}; diff --git a/firmware/application/apps/ui_mictx.cpp b/firmware/application/apps/ui_mictx.cpp index e9beb001..3f694654 100644 --- a/firmware/application/apps/ui_mictx.cpp +++ b/firmware/application/apps/ui_mictx.cpp @@ -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; using options_t = std::vector; - 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. diff --git a/firmware/application/apps/ui_mictx.hpp b/firmware/application/apps/ui_mictx.hpp index 4c7e724a..cca65e67 100644 --- a/firmware/application/apps/ui_mictx.hpp +++ b/firmware/application/apps/ui_mictx.hpp @@ -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). diff --git a/firmware/application/apps/ui_nrf_rx.cpp b/firmware/application/apps/ui_nrf_rx.cpp index e07135a5..eeba3e20 100644 --- a/firmware/application/apps/ui_nrf_rx.cpp +++ b/firmware/application/apps/ui_nrf_rx.cpp @@ -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(); } diff --git a/firmware/application/apps/ui_nrf_rx.hpp b/firmware/application/apps/ui_nrf_rx.hpp index 7ffa3613..a265d240 100644 --- a/firmware/application/apps/ui_nrf_rx.hpp +++ b/firmware/application/apps/ui_nrf_rx.hpp @@ -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}; diff --git a/firmware/application/apps/ui_pocsag_tx.cpp b/firmware/application/apps/ui_pocsag_tx.cpp index 69f7cbd2..e83cc89c 100644 --- a/firmware/application/apps/ui_pocsag_tx.cpp +++ b/firmware/application/apps/ui_pocsag_tx.cpp @@ -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; diff --git a/firmware/application/apps/ui_recon.cpp b/firmware/application/apps/ui_recon.cpp index 88afc6e3..eab1d558 100644 --- a/firmware/application/apps/ui_recon.cpp +++ b/firmware/application/apps/ui_recon.cpp @@ -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(); + auto settings = receiver_model.settings(); + settings.frequency_step = step_mode.selected_index_value(); + nav_.replace(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(); + + // MicTX wants Modulation and Bandwidth overrides, but that's only stored on the RX model. + nav_.replace(receiver_model.settings()); }; button_remove.on_select = [this](ButtonWithEncoder&) { diff --git a/firmware/application/apps/ui_scanner.cpp b/firmware/application/apps/ui_scanner.cpp index 2381dbe5..e545cf47 100644 --- a/firmware/application/apps/ui_scanner.cpp +++ b/firmware/application/apps/ui_scanner.cpp @@ -392,16 +392,17 @@ ScannerView::ScannerView( button_audio_app.on_select = [this](Button&) { if (scan_thread) scan_thread->stop(); - nav_.pop(); - nav_.push(); + auto settings = receiver_model.settings(); + settings.frequency_step = field_step.selected_index_value(); + nav_.replace(settings); }; // Button to switch to Mic app button_mic_app.on_select = [this](Button&) { if (scan_thread) scan_thread->stop(); - nav_.pop(); - nav_.push(); + // MicTX wants Modulation and Bandwidth overrides, but that's only stored on the RX model. + nav_.replace(receiver_model.settings()); }; // Button to delete current frequency from scan Freq List diff --git a/firmware/application/apps/ui_search.cpp b/firmware/application/apps/ui_search.cpp index 19bede87..f7b5e9b4 100644 --- a/firmware/application/apps/ui_search.cpp +++ b/firmware/application/apps/ui_search.cpp @@ -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(false); - else if (options_goto.selected_index() == 2) - nav_.push(); - */ + // 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(); } diff --git a/firmware/application/apps/ui_search.hpp b/firmware/application/apps/ui_search.hpp index d8a671f4..1169a49b 100644 --- a/firmware/application/apps/ui_search.hpp +++ b/firmware/application/apps/ui_search.hpp @@ -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; diff --git a/firmware/application/freqman.cpp b/firmware/application/freqman.cpp index ee6d455b..79fe7bda 100644 --- a/firmware/application/freqman.cpp +++ b/firmware/application/freqman.cpp @@ -27,6 +27,8 @@ using option_t = std::pair; using options_t = std::vector; +// 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}, diff --git a/firmware/application/radio_state.hpp b/firmware/application/radio_state.hpp index eaf4ae61..7145a1c5 100644 --- a/firmware/application/radio_state.hpp +++ b/firmware/application/radio_state.hpp @@ -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 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 > + 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 > + 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; diff --git a/firmware/application/receiver_model.cpp b/firmware/application/receiver_model.cpp index 675206d8..d490356f 100644 --- a/firmware/application/receiver_model.cpp +++ b/firmware/application/receiver_model.cpp @@ -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 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()); } diff --git a/firmware/application/receiver_model.hpp b/firmware/application/receiver_model.hpp index a7262372..7b5263d3 100644 --- a/firmware/application/receiver_model.hpp +++ b/firmware/application/receiver_model.hpp @@ -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 #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__*/ diff --git a/firmware/application/transmitter_model.cpp b/firmware/application/transmitter_model.cpp index b38ea121..159da018 100644 --- a/firmware/application/transmitter_model.cpp +++ b/firmware/application/transmitter_model.cpp @@ -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(); +} diff --git a/firmware/application/transmitter_model.hpp b/firmware/application/transmitter_model.hpp index 8718b407..058bc2ff 100644 --- a/firmware/application/transmitter_model.hpp +++ b/firmware/application/transmitter_model.hpp @@ -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 #include -#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(); }; diff --git a/firmware/application/ui/ui_receiver.cpp b/firmware/application/ui/ui_receiver.cpp index 918bb520..cc53409b 100644 --- a/firmware/application/ui/ui_receiver.cpp +++ b/firmware/application/ui/ui_receiver.cpp @@ -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) { diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index 531413e9..530fe172 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -1001,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())); diff --git a/firmware/common/ui_widget.cpp b/firmware/common/ui_widget.cpp index 84f0d0f0..a5ce1783 100644 --- a/firmware/common/ui_widget.cpp +++ b/firmware/common/ui_widget.cpp @@ -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; diff --git a/firmware/common/ui_widget.hpp b/firmware/common/ui_widget.hpp index 2bd6c97b..994a3223 100644 --- a/firmware/common/ui_widget.hpp +++ b/firmware/common/ui_widget.hpp @@ -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;