From dfadd38e32462b99110f4f4312f3f1d809049c5c Mon Sep 17 00:00:00 2001 From: Brumi-2021 <86470699+Brumi-2021@users.noreply.github.com> Date: Sun, 7 May 2023 16:08:45 +0200 Subject: [PATCH] Adding 2 WFM filters more to current Audio App ( bw 180Khz and 40 khz to support rx for weather NOAA APT) (#961) * First part new filter 40k for NOAA in Audio App * Adding a third WFM filter 180Khz general pursose --- .../application/apps/analog_audio_app.cpp | 21 ++++++++ .../application/apps/analog_audio_app.hpp | 21 ++++++++ firmware/application/baseband_api.cpp | 5 +- firmware/application/baseband_api.hpp | 3 ++ firmware/application/receiver_model.cpp | 6 ++- firmware/common/dsp_fir_taps.hpp | 53 +++++++++++++++++++ 6 files changed, 105 insertions(+), 4 deletions(-) diff --git a/firmware/application/apps/analog_audio_app.cpp b/firmware/application/apps/analog_audio_app.cpp index abd3cefab..a0f395b37 100644 --- a/firmware/application/apps/analog_audio_app.cpp +++ b/firmware/application/apps/analog_audio_app.cpp @@ -83,6 +83,26 @@ NBFMOptionsView::NBFMOptionsView( }; } +/* WFMOptionsView *******************************************************/ + +WFMOptionsView::WFMOptionsView( + const Rect parent_rect, const Style* const style +) : View { parent_rect } +{ + set_style(style); + + add_children({ + &label_config, + &options_config, + }); + + options_config.set_selected_index(receiver_model.wfm_configuration()); + options_config.on_change = [this](size_t n, OptionsField::value_t) { + receiver_model.set_wfm_configuration(n); + }; +} + + /* SPECOptionsView *******************************************************/ SPECOptionsView::SPECOptionsView( @@ -346,6 +366,7 @@ void AnalogAudioView::on_show_options_modulation() { break; case ReceiverModel::Mode::WidebandFMAudio: + widget = std::make_unique(options_view_rect, &style_options_group); waterfall.show_audio_spectrum_view(true); text_ctcss.hidden(true); break; diff --git a/firmware/application/apps/analog_audio_app.hpp b/firmware/application/apps/analog_audio_app.hpp index 0a57e7d92..54a78cb35 100644 --- a/firmware/application/apps/analog_audio_app.hpp +++ b/firmware/application/apps/analog_audio_app.hpp @@ -96,6 +96,27 @@ private: }; }; + +class WFMOptionsView : public View { +public: + WFMOptionsView(const Rect parent_rect, const Style* const style); + +private: + Text label_config { + { 0 * 8, 0 * 16, 2 * 8, 1 * 16 }, + "BW", + }; + OptionsField options_config { + { 3 * 8, 0 * 16 }, + 3, + { + { "200K", 0 }, + { "180K", 1 }, + { " 40K", 2 }, + } + }; +}; + class AnalogAudioView; class SPECOptionsView : public View { diff --git a/firmware/application/baseband_api.cpp b/firmware/application/baseband_api.cpp index d7990403f..ecf161204 100644 --- a/firmware/application/baseband_api.cpp +++ b/firmware/application/baseband_api.cpp @@ -73,8 +73,8 @@ void NBFMConfig::apply(const uint8_t squelch_level) const { void WFMConfig::apply() const { const WFMConfigureMessage message { - taps_200k_wfm_decim_0, - taps_200k_wfm_decim_1, + decim_0, // taps_200k_decim_0 , taps_180k_wfm_decim_0, taps_40k_wfm_decim_0 + decim_1, // taps_200k_decim_1 or taps_180k_wfm_decim_1, taps_40k_wfm_decim_1 taps_64_lp_156_198, 75000, audio_48k_hpf_30hz_config, @@ -84,6 +84,7 @@ void WFMConfig::apply() const { audio::set_rate(audio::Rate::Hz_48000); } + void set_tone(const uint32_t index, const uint32_t delta, const uint32_t duration) { shared_memory.bb_data.tones_data.tone_defs[index].delta = delta; shared_memory.bb_data.tones_data.tone_defs[index].duration = duration; diff --git a/firmware/application/baseband_api.hpp b/firmware/application/baseband_api.hpp index 974d4923a..e1c93545c 100644 --- a/firmware/application/baseband_api.hpp +++ b/firmware/application/baseband_api.hpp @@ -53,6 +53,9 @@ struct NBFMConfig { }; struct WFMConfig { + const fir_taps_real<24> decim_0; // To handle both WFM filters , 200k and 40K for NOAA APT + const fir_taps_real<16> decim_1; + void apply() const; }; diff --git a/firmware/application/receiver_model.cpp b/firmware/application/receiver_model.cpp index c5c7f5ee4..e347c3f80 100644 --- a/firmware/application/receiver_model.cpp +++ b/firmware/application/receiver_model.cpp @@ -52,8 +52,10 @@ static constexpr std::array nbfm_configs { { { taps_16k0_decim_0, taps_16k0_decim_1, taps_16k0_channel, 5000 }, } }; -static constexpr std::array wfm_configs { { - { }, +static constexpr std::array wfm_configs { { + {taps_200k_wfm_decim_0, taps_200k_wfm_decim_1 }, + {taps_180k_wfm_decim_0, taps_180k_wfm_decim_1 }, + {taps_40k_wfm_decim_0, taps_40k_wfm_decim_1 }, } }; } /* namespace */ diff --git a/firmware/common/dsp_fir_taps.hpp b/firmware/common/dsp_fir_taps.hpp index 3b9f474ac..6abd60519 100644 --- a/firmware/common/dsp_fir_taps.hpp +++ b/firmware/common/dsp_fir_taps.hpp @@ -450,6 +450,59 @@ constexpr fir_taps_real<64> taps_64_lp_156_198 { } }, }; +// WFM 180kHZ General purpose filter with sharp transition , it improves Commercial WFM S/N in weak signals ////////////////////////////////////////////// + +// IFIR image-reject filter: fs=3072000, pass=90000, stop=250000, decim=4, fout=768000 +constexpr fir_taps_real<24> taps_180k_wfm_decim_0 = { + .low_frequency_normalized = -90000.0f / 3072000.0f, + .high_frequency_normalized = 90000.0f / 3072000.0f, + .transition_normalized = 160000.0f / 3072000.0f, + .taps = { { + 55, 122, 244, 424, 666, 965, 1308, 1669, + 2019, 2321, 2544, 2663, 2663, 2544, 2321, 2019, + 1669, 1308, 965, 666, 424, 244, 122, 55, + } }, +}; + +// IFIR prototype filter: fs=768000, pass=90000, stop=110000, decim=2, fout=384000 +constexpr fir_taps_real<16> taps_180k_wfm_decim_1 = { + .low_frequency_normalized = -90000.0f / 768000.0f, + .high_frequency_normalized = 90000.0f / 768000.0f, + .transition_normalized = 20000.0f / 768000.0f, + .taps = { { + 55, 19, -356, -916, -529, 2139, 6695, 10392, + 10392, 6695, 2139, -529, -916, -356, 19, 55, + } }, +}; + + + +// WFM 40kHZ filter for NOAA APT reception in 137Mhz band with sharp transition ////////////////////////////////////////////// + +// IFIR image-reject filter: fs=3072000, pass=20000, stop=97000, decim=4, fout=768000 +constexpr fir_taps_real<24> taps_40k_wfm_decim_0 = { + .low_frequency_normalized = -20000.0f / 3072000.0f, + .high_frequency_normalized = 20000.0f / 3072000.0f, + .transition_normalized = 67000.0f / 3072000.0f, + .taps = { { + 46, 112, 230, 408, 650, 953, 1301, 1671, + 2029, 2340, 2570, 2692, 2692, 2570, 2340, 2029, + 1671, 1301, 953, 650, 408, 230, 112, 46, + } }, +}; + +// IFIR prototype filter: fs=768000, pass=20000, stop=55000, decim=2, fout=384000 +constexpr fir_taps_real<16> taps_40k_wfm_decim_1 = { + .low_frequency_normalized = -20000.0f / 768000.0f, + .high_frequency_normalized = 20000.0f / 768000.0f, + .transition_normalized = 35000.0f / 768000.0f, + .taps = { { + 83, 299, 743, 1456, 2396, 3418, 4297, 4808, + 4808, 4297, 3418, 2396, 1456, 743, 299, 83, + } }, +}; + + // TPMS decimation filters //////////////////////////////////////////////// // IFIR image-reject filter: fs=2457600, pass=100000, stop=407200, decim=4, fout=614400