diff --git a/firmware/application/analog_audio_app.cpp b/firmware/application/analog_audio_app.cpp index b7b38295..cf680ca6 100644 --- a/firmware/application/analog_audio_app.cpp +++ b/firmware/application/analog_audio_app.cpp @@ -27,64 +27,6 @@ using namespace portapack; #include "utility.hpp" -#include "dsp_iir_config.hpp" - -void AMConfig::apply() const { - const AMConfigureMessage message { - taps_6k0_decim_0, - taps_6k0_decim_1, - taps_6k0_decim_2, - channel, - modulation, - audio_12k_hpf_300hz_config - }; - shared_memory.baseband_queue.push(message); - clock_manager.set_base_audio_clock_divider(4); -} - -void NBFMConfig::apply() const { - const NBFMConfigureMessage message { - decim_0, - decim_1, - channel, - 2, - deviation, - audio_24k_hpf_300hz_config, - audio_24k_deemph_300_6_config - }; - shared_memory.baseband_queue.push(message); - clock_manager.set_base_audio_clock_divider(2); -} - -void WFMConfig::apply() const { - const WFMConfigureMessage message { - taps_200k_wfm_decim_0, - taps_200k_wfm_decim_1, - taps_64_lp_156_198, - 75000, - audio_48k_hpf_30hz_config, - audio_48k_deemph_2122_6_config - }; - shared_memory.baseband_queue.push(message); - clock_manager.set_base_audio_clock_divider(1); -} - -static constexpr std::array am_configs { { - { taps_6k0_dsb_channel, AMConfigureMessage::Modulation::DSB }, - { taps_2k8_usb_channel, AMConfigureMessage::Modulation::SSB }, - { taps_2k8_lsb_channel, AMConfigureMessage::Modulation::SSB }, -} }; - -static constexpr std::array nbfm_configs { { - { taps_4k25_decim_0, taps_4k25_decim_1, taps_4k25_channel, 2500 }, - { taps_11k0_decim_0, taps_11k0_decim_1, taps_11k0_channel, 2500 }, - { taps_16k0_decim_0, taps_16k0_decim_1, taps_16k0_channel, 5000 }, -} }; - -static constexpr std::array wfm_configs { { - { }, -} }; - namespace ui { /* AnalogAudioView *******************************************************/ @@ -163,6 +105,8 @@ AnalogAudioView::AnalogAudioView( view_rf_gain_options.on_change_rf_amp = [this](bool enable) { this->on_rf_amp_changed(enable); }; + + update_modulation(static_cast(receiver_model.modulation())); } AnalogAudioView::~AnalogAudioView() { @@ -211,39 +155,12 @@ void AnalogAudioView::on_vga_changed(int32_t v_db) { receiver_model.set_vga(v_db); } -void AnalogAudioView::on_modulation_changed(const ReceiverModel::Mode mode) { +void AnalogAudioView::on_modulation_changed(const ReceiverModel::Mode modulation) { // TODO: Terrible kludge because widget system doesn't notify Waterfall that // it's being shown or hidden. waterfall.on_hide(); - - const auto is_wideband_spectrum_mode = (mode == ReceiverModel::Mode::SpectrumAnalysis); - receiver_model.set_baseband_configuration({ - .mode = toUType(mode), - .sampling_rate = is_wideband_spectrum_mode ? 20000000U : 3072000U, - .decimation_factor = 1, - }); - receiver_model.set_baseband_bandwidth(is_wideband_spectrum_mode ? 12000000 : 1750000); - receiver_model.enable(); - - switch(mode) { - default: - case ReceiverModel::Mode::AMAudio: - update_am_config(); - break; - - case ReceiverModel::Mode::NarrowbandFMAudio: - update_nbfm_config(); - break; - - case ReceiverModel::Mode::WidebandFMAudio: - update_wfm_config(); - break; - - case ReceiverModel::Mode::SpectrumAnalysis: - break; - } - - waterfall.on_show(); + update_modulation(modulation); + waterfall.on_show(); } void AnalogAudioView::on_show_options_frequency() { @@ -277,29 +194,22 @@ void AnalogAudioView::on_headphone_volume_changed(int32_t v) { } void AnalogAudioView::on_am_config_index_changed(size_t n) { - if( n < am_configs.size() ) { - am_config_index = n; - update_am_config(); - } + receiver_model.set_am_configuration(n); } void AnalogAudioView::on_nbfm_config_index_changed(size_t n) { - if( n < nbfm_configs.size() ) { - nbfm_config_index = n; - update_nbfm_config(); - } + receiver_model.set_nbfm_configuration(n); } -void AnalogAudioView::update_am_config() { - am_configs[am_config_index].apply(); -} - -void AnalogAudioView::update_nbfm_config() { - nbfm_configs[nbfm_config_index].apply(); -} - -void AnalogAudioView::update_wfm_config() { - wfm_configs[wfm_config_index].apply(); +void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) { + const auto is_wideband_spectrum_mode = (modulation == ReceiverModel::Mode::SpectrumAnalysis); + receiver_model.set_baseband_configuration({ + .mode = toUType(modulation), + .sampling_rate = is_wideband_spectrum_mode ? 20000000U : 3072000U, + .decimation_factor = 1, + }); + receiver_model.set_baseband_bandwidth(is_wideband_spectrum_mode ? 12000000 : 1750000); + receiver_model.enable(); } } /* namespace ui */ diff --git a/firmware/application/analog_audio_app.hpp b/firmware/application/analog_audio_app.hpp index f303bb0e..1aa691fa 100644 --- a/firmware/application/analog_audio_app.hpp +++ b/firmware/application/analog_audio_app.hpp @@ -29,29 +29,6 @@ #include "ui_font_fixed_8x16.hpp" -#include "dsp_fir_taps.hpp" -#include "dsp_iir.hpp" - -struct AMConfig { - const fir_taps_complex<64> channel; - const AMConfigureMessage::Modulation modulation; - - void apply() const; -}; - -struct NBFMConfig { - const fir_taps_real<24> decim_0; - const fir_taps_real<32> decim_1; - const fir_taps_real<32> channel; - const size_t deviation; - - void apply() const; -}; - -struct WFMConfig { - void apply() const; -}; - namespace ui { constexpr Style style_options_group { @@ -143,16 +120,13 @@ private: */ spectrum::WaterfallWidget waterfall; - size_t am_config_index = 0; - size_t nbfm_config_index = 0; - static constexpr size_t wfm_config_index = 0; void on_tuning_frequency_changed(rf::Frequency f); void on_baseband_bandwidth_changed(uint32_t bandwidth_hz); void on_rf_amp_changed(bool v); void on_lna_changed(int32_t v_db); void on_vga_changed(int32_t v_db); - void on_modulation_changed(const ReceiverModel::Mode mode); + void on_modulation_changed(const ReceiverModel::Mode modulation); void on_show_options_frequency(); void on_show_options_rf_gain(); void on_frequency_step_changed(rf::Frequency f); @@ -163,9 +137,7 @@ private: void on_am_config_index_changed(size_t n); void on_nbfm_config_index_changed(size_t n); - void update_am_config(); - void update_nbfm_config(); - void update_wfm_config(); + void update_modulation(const ReceiverModel::Mode modulation); }; } /* namespace ui */ diff --git a/firmware/application/receiver_model.cpp b/firmware/application/receiver_model.cpp index 4f4e4d1c..dd6554c6 100644 --- a/firmware/application/receiver_model.cpp +++ b/firmware/application/receiver_model.cpp @@ -26,6 +26,90 @@ #include "portapack.hpp" using namespace portapack; +#include "dsp_fir_taps.hpp" +#include "dsp_iir.hpp" +#include "dsp_iir_config.hpp" + +namespace { + +struct AMConfig { + const fir_taps_complex<64> channel; + const AMConfigureMessage::Modulation modulation; + + void apply() const; +}; + +struct NBFMConfig { + const fir_taps_real<24> decim_0; + const fir_taps_real<32> decim_1; + const fir_taps_real<32> channel; + const size_t deviation; + + void apply() const; +}; + +struct WFMConfig { + void apply() const; +}; + +void AMConfig::apply() const { + const AMConfigureMessage message { + taps_6k0_decim_0, + taps_6k0_decim_1, + taps_6k0_decim_2, + channel, + modulation, + audio_12k_hpf_300hz_config + }; + shared_memory.baseband_queue.push(message); + clock_manager.set_base_audio_clock_divider(4); +} + +void NBFMConfig::apply() const { + const NBFMConfigureMessage message { + decim_0, + decim_1, + channel, + 2, + deviation, + audio_24k_hpf_300hz_config, + audio_24k_deemph_300_6_config + }; + shared_memory.baseband_queue.push(message); + clock_manager.set_base_audio_clock_divider(2); +} + +void WFMConfig::apply() const { + const WFMConfigureMessage message { + taps_200k_wfm_decim_0, + taps_200k_wfm_decim_1, + taps_64_lp_156_198, + 75000, + audio_48k_hpf_30hz_config, + audio_48k_deemph_2122_6_config + }; + shared_memory.baseband_queue.push(message); + clock_manager.set_base_audio_clock_divider(1); +} + +static constexpr std::array am_configs { { + { taps_6k0_dsb_channel, AMConfigureMessage::Modulation::DSB }, + { taps_2k8_usb_channel, AMConfigureMessage::Modulation::SSB }, + { taps_2k8_lsb_channel, AMConfigureMessage::Modulation::SSB }, +} }; + +static constexpr std::array nbfm_configs { { + { taps_4k25_decim_0, taps_4k25_decim_1, taps_4k25_channel, 2500 }, + { taps_11k0_decim_0, taps_11k0_decim_1, taps_11k0_channel, 2500 }, + { taps_16k0_decim_0, taps_16k0_decim_1, taps_16k0_channel, 5000 }, +} }; + +static constexpr std::array wfm_configs { { + { }, +} }; + +} /* namespace */ + rf::Frequency ReceiverModel::tuning_frequency() const { return persistent_memory::tuned_frequency(); } @@ -129,7 +213,7 @@ void ReceiverModel::enable() { update_vga(); update_baseband_bandwidth(); update_baseband_configuration(); - + update_modulation_configuration(); update_headphone_volume(); } @@ -189,6 +273,27 @@ void ReceiverModel::set_baseband_configuration(const BasebandConfiguration confi update_baseband_configuration(); } +void ReceiverModel::set_am_configuration(const size_t n) { + if( n < am_configs.size() ) { + am_config_index = n; + update_modulation_configuration(); + } +} + +void ReceiverModel::set_nbfm_configuration(const size_t n) { + if( n < nbfm_configs.size() ) { + nbfm_config_index = n; + update_modulation_configuration(); + } +} + +void ReceiverModel::set_wfm_configuration(const size_t n) { + if( n < wfm_configs.size() ) { + wfm_config_index = n; + update_modulation_configuration(); + } +} + void ReceiverModel::update_baseband_configuration() { // TODO: Move more low-level radio control stuff to M4. It'll enable tighter // synchronization for things like wideband (sweeping) spectrum analysis, and @@ -211,3 +316,35 @@ void ReceiverModel::update_headphone_volume() { audio_codec.set_headphone_volume(headphone_volume_); } + +void ReceiverModel::update_modulation_configuration() { + switch(static_cast(modulation())) { + default: + case Mode::AMAudio: + update_am_configuration(); + break; + + case Mode::NarrowbandFMAudio: + update_nbfm_configuration(); + break; + + case Mode::WidebandFMAudio: + update_wfm_configuration(); + break; + + case Mode::SpectrumAnalysis: + break; + } +} + +void ReceiverModel::update_am_configuration() { + am_configs[am_config_index].apply(); +} + +void ReceiverModel::update_nbfm_configuration() { + nbfm_configs[nbfm_config_index].apply(); +} + +void ReceiverModel::update_wfm_configuration() { + wfm_configs[wfm_config_index].apply(); +} diff --git a/firmware/application/receiver_model.hpp b/firmware/application/receiver_model.hpp index d76f4670..3c1749c6 100644 --- a/firmware/application/receiver_model.hpp +++ b/firmware/application/receiver_model.hpp @@ -80,6 +80,10 @@ public: void set_baseband_configuration(const BasebandConfiguration config); + void set_am_configuration(const size_t n); + void set_nbfm_configuration(const size_t n); + void set_wfm_configuration(const size_t n); + private: rf::Frequency frequency_step_ { 25000 }; bool enabled_ { false }; @@ -93,6 +97,9 @@ private: .sampling_rate = 3072000, .decimation_factor = 1, }; + size_t am_config_index = 0; + size_t nbfm_config_index = 0; + size_t wfm_config_index = 0; volume_t headphone_volume_ { -43.0_dB }; int32_t tuning_offset(); @@ -106,6 +113,11 @@ private: void update_baseband_configuration(); void update_headphone_volume(); + void update_modulation_configuration(); + void update_am_configuration(); + void update_nbfm_configuration(); + void update_wfm_configuration(); + void baseband_disable(); };