mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-08-21 06:59:02 +00:00
Isolate filtered spectrum collection from WFM
This commit is contained in:
@@ -124,6 +124,7 @@ set(CPPSRC
|
||||
dsp_goertzel.cpp
|
||||
matched_filter.cpp
|
||||
spectrum_collector.cpp
|
||||
filtered_spectrum_collector.cpp
|
||||
tv_collector.cpp
|
||||
stream_input.cpp
|
||||
stream_output.cpp
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include "filtered_spectrum_collector.hpp"
|
||||
|
||||
#include "dsp_fir_taps.hpp"
|
||||
#include "event_m4.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
void FilteredSpectrumCollector::on_message(const Message* const message) {
|
||||
if (message->id == Message::ID::UpdateSpectrum) {
|
||||
update();
|
||||
}
|
||||
SpectrumCollector::on_message(message);
|
||||
}
|
||||
|
||||
void FilteredSpectrumCollector::start_capture(
|
||||
const size_t decimation_factor) {
|
||||
capture_decimation_ = decimation_factor;
|
||||
capture_count_ = 0;
|
||||
capture_ready_ = false;
|
||||
}
|
||||
|
||||
bool FilteredSpectrumCollector::feed(
|
||||
const buffer_c16_t& channel,
|
||||
const int32_t filter_low_frequency,
|
||||
const int32_t filter_high_frequency,
|
||||
const int32_t filter_transition) {
|
||||
set_filter(
|
||||
filter_low_frequency,
|
||||
filter_high_frequency,
|
||||
filter_transition);
|
||||
|
||||
const size_t required_samples = 256 * capture_decimation_;
|
||||
const size_t copy_count = std::min(
|
||||
channel.count, required_samples - capture_count_);
|
||||
std::copy_n(
|
||||
channel.p,
|
||||
copy_count,
|
||||
capture_.begin() + capture_count_);
|
||||
capture_count_ += copy_count;
|
||||
|
||||
if (capture_count_ == required_samples) {
|
||||
sampling_rate_ = channel.sampling_rate / capture_decimation_;
|
||||
capture_ready_ = true;
|
||||
EventDispatcher::events_flag(EVT_MASK_SPECTRUM);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FilteredSpectrumCollector::update() {
|
||||
if (!capture_ready_) {
|
||||
return;
|
||||
}
|
||||
|
||||
decim_0_.configure(taps_audio_spectrum_halfband.taps);
|
||||
const buffer_c16_t capture{
|
||||
capture_.data(),
|
||||
256 * capture_decimation_,
|
||||
sampling_rate_ * capture_decimation_};
|
||||
const buffer_c16_t stage_0{
|
||||
stage_0_.data(),
|
||||
stage_0_.size()};
|
||||
const auto filtered = decim_0_.execute(capture, stage_0);
|
||||
|
||||
if (capture_decimation_ == 4) {
|
||||
decim_1_.configure(taps_audio_spectrum_halfband.taps);
|
||||
const buffer_c16_t stage_1{
|
||||
stage_1_.data(),
|
||||
stage_1_.size()};
|
||||
post_message(decim_1_.execute(filtered, stage_1));
|
||||
} else {
|
||||
post_message(filtered);
|
||||
}
|
||||
capture_ready_ = false;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#ifndef __FILTERED_SPECTRUM_COLLECTOR_H__
|
||||
#define __FILTERED_SPECTRUM_COLLECTOR_H__
|
||||
|
||||
#include "dsp_decimate.hpp"
|
||||
#include "spectrum_collector.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
class FilteredSpectrumCollector : public SpectrumCollector {
|
||||
public:
|
||||
void on_message(const Message* const message);
|
||||
|
||||
void start_capture(const size_t decimation_factor);
|
||||
bool feed(
|
||||
const buffer_c16_t& channel,
|
||||
const int32_t filter_low_frequency,
|
||||
const int32_t filter_high_frequency,
|
||||
const int32_t filter_transition);
|
||||
|
||||
private:
|
||||
std::array<complex16_t, 1024> capture_{};
|
||||
std::array<complex16_t, 512> stage_0_{};
|
||||
std::array<complex16_t, 256> stage_1_{};
|
||||
dsp::decimate::FIRC16xR16x63HalfbandDecim2 decim_0_{};
|
||||
dsp::decimate::FIRC16xR16x63HalfbandDecim2 decim_1_{};
|
||||
size_t capture_count_{0};
|
||||
size_t capture_decimation_{1};
|
||||
uint32_t sampling_rate_{0};
|
||||
bool capture_ready_{false};
|
||||
|
||||
void update();
|
||||
};
|
||||
|
||||
#endif /*__FILTERED_SPECTRUM_COLLECTOR_H__*/
|
||||
@@ -51,12 +51,12 @@ void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) {
|
||||
if (!spectrum_capture_active &&
|
||||
spectrum_samples >= spectrum_interval_samples) {
|
||||
spectrum_samples -= spectrum_interval_samples;
|
||||
channel_spectrum.start_filtered_capture(spectrum_zoom_x2 ? 4 : 2);
|
||||
channel_spectrum.start_capture(spectrum_zoom_x2 ? 4 : 2);
|
||||
spectrum_capture_active = true;
|
||||
}
|
||||
|
||||
if (spectrum_capture_active &&
|
||||
channel_spectrum.feed_filtered(
|
||||
channel_spectrum.feed(
|
||||
audio_decim_0_out,
|
||||
channel_filter_low_f,
|
||||
channel_filter_high_f,
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "audio_compressor.hpp"
|
||||
|
||||
#include "audio_output.hpp"
|
||||
#include "spectrum_collector.hpp"
|
||||
#include "filtered_spectrum_collector.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
@@ -80,7 +80,7 @@ class NarrowbandAMAudio : public BasebandProcessor {
|
||||
FeedForwardCompressor audio_compressor{};
|
||||
AudioOutput audio_output{};
|
||||
|
||||
SpectrumCollector channel_spectrum{};
|
||||
FilteredSpectrumCollector channel_spectrum{};
|
||||
|
||||
/* NB: Threads should be the last members in the class definition. */
|
||||
#ifdef PRALINE
|
||||
|
||||
@@ -57,12 +57,12 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) {
|
||||
if (!spectrum_capture_active &&
|
||||
spectrum_samples >= spectrum_interval_samples) {
|
||||
spectrum_samples -= spectrum_interval_samples;
|
||||
channel_spectrum.start_filtered_capture(2);
|
||||
channel_spectrum.start_capture(2);
|
||||
spectrum_capture_active = true;
|
||||
}
|
||||
|
||||
if (spectrum_capture_active &&
|
||||
channel_spectrum.feed_filtered(
|
||||
channel_spectrum.feed(
|
||||
audio_decim_0_out,
|
||||
channel_filter_low_f,
|
||||
channel_filter_high_f,
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "dsp_iir.hpp"
|
||||
|
||||
#include "audio_output.hpp"
|
||||
#include "spectrum_collector.hpp"
|
||||
#include "filtered_spectrum_collector.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
@@ -87,7 +87,7 @@ class NarrowbandFMAudio : public BasebandProcessor {
|
||||
|
||||
AudioOutput audio_output{};
|
||||
|
||||
SpectrumCollector channel_spectrum{};
|
||||
FilteredSpectrumCollector channel_spectrum{};
|
||||
size_t spectrum_interval_samples{0};
|
||||
size_t spectrum_samples{0};
|
||||
bool spectrum_capture_active{false};
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "spectrum_collector.hpp"
|
||||
|
||||
#include "dsp_fft.hpp"
|
||||
#include "dsp_fir_taps.hpp"
|
||||
|
||||
#include "utility.hpp"
|
||||
#include "event_m4.hpp"
|
||||
@@ -80,9 +79,10 @@ bool SpectrumCollector::feed(
|
||||
const int32_t filter_high_frequency,
|
||||
const int32_t filter_transition) {
|
||||
// Called from baseband processing thread.
|
||||
channel_filter_low_frequency = filter_low_frequency;
|
||||
channel_filter_high_frequency = filter_high_frequency;
|
||||
channel_filter_transition = filter_transition;
|
||||
set_filter(
|
||||
filter_low_frequency,
|
||||
filter_high_frequency,
|
||||
filter_transition);
|
||||
|
||||
bool block_completed = false;
|
||||
channel_spectrum_decimator.feed(
|
||||
@@ -94,40 +94,13 @@ bool SpectrumCollector::feed(
|
||||
return block_completed;
|
||||
}
|
||||
|
||||
void SpectrumCollector::start_filtered_capture(
|
||||
const size_t decimation_factor) {
|
||||
filtered_capture_decimation_ = decimation_factor;
|
||||
filtered_capture_count_ = 0;
|
||||
filtered_capture_ready_ = false;
|
||||
}
|
||||
|
||||
bool SpectrumCollector::feed_filtered(
|
||||
const buffer_c16_t& channel,
|
||||
void SpectrumCollector::set_filter(
|
||||
const int32_t filter_low_frequency,
|
||||
const int32_t filter_high_frequency,
|
||||
const int32_t filter_transition) {
|
||||
channel_filter_low_frequency = filter_low_frequency;
|
||||
channel_filter_high_frequency = filter_high_frequency;
|
||||
channel_filter_transition = filter_transition;
|
||||
|
||||
const size_t required_samples = 256 * filtered_capture_decimation_;
|
||||
const size_t copy_count = std::min(
|
||||
channel.count, required_samples - filtered_capture_count_);
|
||||
std::copy_n(
|
||||
channel.p,
|
||||
copy_count,
|
||||
filtered_capture_.begin() + filtered_capture_count_);
|
||||
filtered_capture_count_ += copy_count;
|
||||
|
||||
if (filtered_capture_count_ == required_samples) {
|
||||
channel_spectrum_sampling_rate =
|
||||
channel.sampling_rate / filtered_capture_decimation_;
|
||||
filtered_capture_ready_ = true;
|
||||
channel_spectrum_request_update = true;
|
||||
EventDispatcher::events_flag(EVT_MASK_SPECTRUM);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SpectrumCollector::post_message(const buffer_c16_t& data) {
|
||||
@@ -171,31 +144,6 @@ static typename T::value_type spectrum_window_blackman_3(const T& s, const size_
|
||||
void SpectrumCollector::update() {
|
||||
// Called from idle thread (after EVT_MASK_SPECTRUM is flagged)
|
||||
if (streaming && channel_spectrum_request_update) {
|
||||
if (filtered_capture_ready_) {
|
||||
filtered_decim_0_.configure(taps_audio_spectrum_halfband.taps);
|
||||
const buffer_c16_t capture{
|
||||
filtered_capture_.data(),
|
||||
256 * filtered_capture_decimation_,
|
||||
channel_spectrum_sampling_rate * filtered_capture_decimation_};
|
||||
const buffer_c16_t stage_0{
|
||||
filtered_stage_0_.data(),
|
||||
filtered_stage_0_.size()};
|
||||
const auto filtered = filtered_decim_0_.execute(capture, stage_0);
|
||||
|
||||
if (filtered_capture_decimation_ == 4) {
|
||||
filtered_decim_1_.configure(taps_audio_spectrum_halfband.taps);
|
||||
const buffer_c16_t stage_1{
|
||||
filtered_stage_1_.data(),
|
||||
filtered_stage_1_.size()};
|
||||
const auto zoom_filtered =
|
||||
filtered_decim_1_.execute(filtered, stage_1);
|
||||
fft_swap(zoom_filtered, channel_spectrum);
|
||||
} else {
|
||||
fft_swap(filtered, channel_spectrum);
|
||||
}
|
||||
filtered_capture_ready_ = false;
|
||||
}
|
||||
|
||||
/* Decimated buffer is full. Compute spectrum. */
|
||||
fft_c_preswapped(channel_spectrum, 0, 8);
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "complex.hpp"
|
||||
|
||||
#include "block_decimator.hpp"
|
||||
#include "dsp_decimate.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
@@ -51,12 +50,12 @@ class SpectrumCollector {
|
||||
const int32_t filter_high_frequency,
|
||||
const int32_t filter_transition);
|
||||
|
||||
void start_filtered_capture(const size_t decimation_factor);
|
||||
bool feed_filtered(
|
||||
const buffer_c16_t& channel,
|
||||
protected:
|
||||
void set_filter(
|
||||
const int32_t filter_low_frequency,
|
||||
const int32_t filter_high_frequency,
|
||||
const int32_t filter_transition);
|
||||
void post_message(const buffer_c16_t& data);
|
||||
|
||||
private:
|
||||
BlockDecimator<complex16_t, 256> channel_spectrum_decimator{1};
|
||||
@@ -66,22 +65,12 @@ class SpectrumCollector {
|
||||
volatile bool channel_spectrum_request_update{false};
|
||||
bool streaming{false};
|
||||
std::array<std::complex<float>, 256> channel_spectrum{};
|
||||
std::array<complex16_t, 1024> filtered_capture_{};
|
||||
std::array<complex16_t, 512> filtered_stage_0_{};
|
||||
std::array<complex16_t, 256> filtered_stage_1_{};
|
||||
dsp::decimate::FIRC16xR16x63HalfbandDecim2 filtered_decim_0_{};
|
||||
dsp::decimate::FIRC16xR16x63HalfbandDecim2 filtered_decim_1_{};
|
||||
size_t filtered_capture_count_{0};
|
||||
size_t filtered_capture_decimation_{1};
|
||||
bool filtered_capture_ready_{false};
|
||||
uint32_t channel_spectrum_sampling_rate{0};
|
||||
int32_t channel_filter_low_frequency{0};
|
||||
int32_t channel_filter_high_frequency{0};
|
||||
int32_t channel_filter_transition{0};
|
||||
int32_t channel_filter_offset{0};
|
||||
|
||||
void post_message(const buffer_c16_t& data);
|
||||
|
||||
void set_state(const SpectrumStreamingConfigMessage& message);
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
Reference in New Issue
Block a user