diff --git a/firmware/application/capture_app.cpp b/firmware/application/capture_app.cpp index 173eefd6..97ca6ec7 100644 --- a/firmware/application/capture_app.cpp +++ b/firmware/application/capture_app.cpp @@ -36,6 +36,7 @@ CaptureAppView::CaptureAppView(NavigationView& nav) { &field_frequency, &field_lna, &field_vga, + &waterfall, } }); field_frequency.set_value(receiver_model.tuning_frequency()); @@ -79,6 +80,20 @@ CaptureAppView::~CaptureAppView() { receiver_model.disable(); } +void CaptureAppView::on_hide() { + // TODO: Terrible kludge because widget system doesn't notify Waterfall that + // it's being shown or hidden. + waterfall.on_hide(); + View::on_hide(); +} + +void CaptureAppView::set_parent_rect(const Rect new_parent_rect) { + View::set_parent_rect(new_parent_rect); + + const ui::Rect waterfall_rect { 0, header_height, new_parent_rect.width(), static_cast(new_parent_rect.height() - header_height) }; + waterfall.set_parent_rect(waterfall_rect); +} + void CaptureAppView::focus() { button_start_stop.focus(); } diff --git a/firmware/application/capture_app.hpp b/firmware/application/capture_app.hpp index b62ab8c5..ac09816f 100644 --- a/firmware/application/capture_app.hpp +++ b/firmware/application/capture_app.hpp @@ -25,6 +25,7 @@ #include "ui_widget.hpp" #include "ui_navigation.hpp" #include "ui_receiver.hpp" +#include "ui_spectrum.hpp" #include "audio_thread.hpp" @@ -84,11 +85,17 @@ public: CaptureAppView(NavigationView& nav); ~CaptureAppView(); + void on_hide() override; + + void set_parent_rect(const Rect new_parent_rect) override; + void focus() override; std::string title() const override { return "Capture"; }; private: + static constexpr ui::Dim header_height = 2 * 16; + static constexpr uint32_t sampling_rate = 2457600; static constexpr uint32_t baseband_bandwidth = 1750000; @@ -126,6 +133,8 @@ private: VGAGainField field_vga { { 18 * 8, 0 * 16 } }; + + spectrum::WaterfallWidget waterfall; }; } /* namespace ui */ diff --git a/firmware/baseband/proc_capture.cpp b/firmware/baseband/proc_capture.cpp index 6e24c5fe..f069c206 100644 --- a/firmware/baseband/proc_capture.cpp +++ b/firmware/baseband/proc_capture.cpp @@ -26,8 +26,29 @@ #include "utility.hpp" CaptureProcessor::CaptureProcessor() { - decim_0.configure(taps_200k_decim_0.taps, 33554432); - decim_1.configure(taps_200k_decim_1.taps, 131072); + const auto& decim_0_filter = taps_200k_decim_0; + constexpr size_t decim_0_input_fs = baseband_fs; + constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0.decimation_factor; + + const auto& decim_1_filter = taps_200k_decim_1; + constexpr size_t decim_1_input_fs = decim_0_output_fs; + constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor; + + const auto& channel_filter = decim_1_filter; + constexpr size_t channel_filter_input_fs = decim_1_output_fs; + constexpr size_t channel_decimation = 1; + const size_t channel_filter_output_fs = channel_filter_input_fs / channel_decimation; + + decim_0.configure(decim_0_filter.taps, 33554432); + decim_1.configure(decim_1_filter.taps, 131072); + + channel_filter_pass_f = channel_filter.pass_frequency_normalized * channel_filter_input_fs; + channel_filter_stop_f = channel_filter.stop_frequency_normalized * channel_filter_input_fs; + + spectrum_interval_samples = channel_filter_output_fs / spectrum_rate_hz; + spectrum_samples = 0; + + channel_spectrum.set_decimation_factor(1); stream = std::make_unique(15); } @@ -36,12 +57,31 @@ void CaptureProcessor::execute(const buffer_c8_t& buffer) { /* 2.4576MHz, 2048 samples */ const auto decim_0_out = decim_0.execute(buffer, dst_buffer); const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); - const auto decimator_out = decim_1_out; + const auto& decimator_out = decim_1_out; + const auto& channel = decimator_out; if( stream ) { const size_t bytes_to_write = sizeof(*decimator_out.p) * decimator_out.count; const auto result = stream->write(decimator_out.p, bytes_to_write); } - feed_channel_stats(decimator_out); + feed_channel_stats(channel); + + spectrum_samples += channel.count; + if( spectrum_samples >= spectrum_interval_samples ) { + spectrum_samples -= spectrum_interval_samples; + channel_spectrum.feed(channel, channel_filter_pass_f, channel_filter_stop_f); + } +} + +void CaptureProcessor::on_message(const Message* const message) { + switch(message->id) { + case Message::ID::UpdateSpectrum: + case Message::ID::SpectrumStreamingConfig: + channel_spectrum.on_message(message); + break; + + default: + break; + } } diff --git a/firmware/baseband/proc_capture.hpp b/firmware/baseband/proc_capture.hpp index 9e77a8ce..008c10d2 100644 --- a/firmware/baseband/proc_capture.hpp +++ b/firmware/baseband/proc_capture.hpp @@ -25,6 +25,8 @@ #include "baseband_processor.hpp" #include "dsp_decimate.hpp" +#include "spectrum_collector.hpp" + #include "stream_input.hpp" #include @@ -36,7 +38,12 @@ public: void execute(const buffer_c8_t& buffer) override; + void on_message(const Message* const message) override; + private: + static constexpr size_t baseband_fs = 2457600; + static constexpr auto spectrum_rate_hz = 50.0f; + std::array dst; const buffer_c16_t dst_buffer { dst.data(), @@ -45,8 +52,14 @@ private: dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0; dsp::decimate::FIRC16xR16x16Decim2 decim_1; + uint32_t channel_filter_pass_f = 0; + uint32_t channel_filter_stop_f = 0; std::unique_ptr stream; + + SpectrumCollector channel_spectrum; + size_t spectrum_interval_samples = 0; + size_t spectrum_samples = 0; }; #endif/*__PROC_CAPTURE_HPP__*/