mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-16 19:43:01 +00:00
Fix LF/MF RX centering with adaptive FS4 tuning (#3319)
* Fix LF/MF RX tuning with adaptive FS4 shift * Enable adaptive FS4 tuning in Waterfall Designer
This commit is contained in:
@@ -470,6 +470,18 @@ void set_hunter_config(uint32_t threshold, uint32_t hangtime_ms, bool start) {
|
||||
}
|
||||
|
||||
static bool baseband_image_running = false;
|
||||
static bool rx_fs4_supported = false;
|
||||
|
||||
bool supports_rx_fs4() {
|
||||
return baseband_image_running && rx_fs4_supported;
|
||||
}
|
||||
|
||||
void set_rx_fs4_direction(RxFs4Direction direction) {
|
||||
if (supports_rx_fs4()) {
|
||||
const RxFs4ConfigMessage message{direction};
|
||||
send_message(&message);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_image_running() {
|
||||
return baseband_image_running;
|
||||
@@ -484,6 +496,10 @@ void run_image(const spi_flash::image_tag_t image_tag, bool enforce_core_sync) {
|
||||
shared_memory.clear_baseband_ready();
|
||||
|
||||
m4_init(image_tag, memory::map::m4_code, false);
|
||||
rx_fs4_supported = image_tag == spi_flash::image_tag_am_audio ||
|
||||
image_tag == spi_flash::image_tag_nfm_audio ||
|
||||
image_tag == spi_flash::image_tag_wfm_audio ||
|
||||
image_tag == spi_flash::image_tag_capture;
|
||||
baseband_image_running = true;
|
||||
|
||||
creg::m4txevent::enable();
|
||||
@@ -499,7 +515,8 @@ void run_image(const spi_flash::image_tag_t image_tag, bool enforce_core_sync) {
|
||||
}
|
||||
}
|
||||
|
||||
void run_prepared_image(const uint32_t m4_code, bool enforce_core_sync) {
|
||||
void run_prepared_image(const uint32_t m4_code, bool enforce_core_sync, const spi_flash::image_tag_t prepared_image_tag) {
|
||||
rx_fs4_supported = false;
|
||||
if (baseband_image_running) {
|
||||
chDbgPanic("BBRunning");
|
||||
}
|
||||
@@ -508,6 +525,8 @@ void run_prepared_image(const uint32_t m4_code, bool enforce_core_sync) {
|
||||
shared_memory.clear_baseband_ready();
|
||||
|
||||
m4_init_prepared(m4_code, false);
|
||||
// Only explicitly identified Capture images support application FS4 control.
|
||||
rx_fs4_supported = prepared_image_tag == spi_flash::image_tag_capture;
|
||||
baseband_image_running = true;
|
||||
|
||||
creg::m4txevent::enable();
|
||||
@@ -524,6 +543,7 @@ void run_prepared_image(const uint32_t m4_code, bool enforce_core_sync) {
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
rx_fs4_supported = false;
|
||||
if (!baseband_image_running) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -132,8 +132,10 @@ void request_beep_stop();
|
||||
void request_audio_beep(uint32_t freq, uint32_t sample_rate, uint32_t duration_ms);
|
||||
|
||||
bool is_image_running();
|
||||
bool supports_rx_fs4();
|
||||
void set_rx_fs4_direction(RxFs4Direction direction);
|
||||
void run_image(const portapack::spi_flash::image_tag_t image_tag, bool enforce_core_sync = true);
|
||||
void run_prepared_image(const uint32_t m4_code, bool enforce_core_sync = true);
|
||||
void run_prepared_image(const uint32_t m4_code, bool enforce_core_sync = true, const portapack::spi_flash::image_tag_t prepared_image_tag = portapack::spi_flash::image_tag_none);
|
||||
void shutdown();
|
||||
|
||||
void spectrum_streaming_start();
|
||||
|
||||
@@ -71,7 +71,8 @@ bool is_color_level(const std::string& line) {
|
||||
|
||||
WaterfallDesignerView::WaterfallDesignerView(NavigationView& nav)
|
||||
: nav_{nav} {
|
||||
baseband::run_prepared_image(portapack::memory::map::m4_code.base());
|
||||
baseband::run_prepared_image(portapack::memory::map::m4_code.base(), true,
|
||||
portapack::spi_flash::image_tag_capture);
|
||||
|
||||
add_children({&labels,
|
||||
&field_frequency,
|
||||
|
||||
@@ -334,6 +334,8 @@ void ReceiverModel::disable() {
|
||||
|
||||
void ReceiverModel::initialize() {
|
||||
settings_ = settings_t{};
|
||||
hidden_offset = 0;
|
||||
application_fs4_direction_ = RxFs4Direction::Down;
|
||||
am_spectrum_zoom_ = spectrum_zoom_for_am_config(settings_.am_config_index);
|
||||
}
|
||||
|
||||
@@ -369,14 +371,29 @@ int32_t ReceiverModel::tuning_offset() {
|
||||
if ((modulation() == Mode::SpectrumAnalysis)) {
|
||||
return 0;
|
||||
} else {
|
||||
return -(sampling_rate() / 4);
|
||||
const int32_t quarter_rate = static_cast<int32_t>(sampling_rate() / 4);
|
||||
const rf::Frequency effective_frequency = target_frequency() + hidden_offset;
|
||||
return baseband::supports_rx_fs4() && effective_frequency - quarter_rate < 0
|
||||
? quarter_rate
|
||||
: -quarter_rate;
|
||||
}
|
||||
}
|
||||
|
||||
void ReceiverModel::update_tuning_frequency() {
|
||||
// TODO: use positive offset if freq < offset.
|
||||
if (enabled_) {
|
||||
radio::set_tuning_frequency(target_frequency() + hidden_offset + tuning_offset());
|
||||
const auto offset = tuning_offset();
|
||||
if (!radio::set_tuning_frequency(target_frequency() + hidden_offset + offset))
|
||||
return;
|
||||
|
||||
if (modulation() != Mode::SpectrumAnalysis && baseband::supports_rx_fs4()) {
|
||||
application_fs4_direction_ = offset > 0 ? RxFs4Direction::Up : RxFs4Direction::Down;
|
||||
// Re-send on enable too: the active processor may have restarted.
|
||||
baseband::set_rx_fs4_direction(application_fs4_direction_);
|
||||
}
|
||||
#ifdef PRALINE
|
||||
// A tune can change the FPGA shift (including the special zero entry).
|
||||
update_baseband_bandwidth();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -149,6 +149,7 @@ class ReceiverModel {
|
||||
AMConfigureMessage::Zoom_waterfall am_spectrum_zoom_{AMConfigureMessage::Zoom_waterfall::ZOOM_x_1};
|
||||
settings_t settings_{};
|
||||
bool enabled_ = false;
|
||||
RxFs4Direction application_fs4_direction_{RxFs4Direction::Down};
|
||||
rf::Frequency hidden_offset = 0; // when we need to hide the offset from user, we set this. like when WeFax needs -300Hz.
|
||||
|
||||
int32_t tuning_offset();
|
||||
|
||||
@@ -45,6 +45,10 @@ void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only the processing thread applies frequency-only direction changes.
|
||||
if (requested_fs4_direction_.load(std::memory_order_relaxed) != applied_fs4_direction_)
|
||||
configure_fs4(decim_0_taps_);
|
||||
|
||||
const auto decim_0_out = decim_0.execute(buffer, dst_buffer);
|
||||
const auto audio_decim_0_out = audio_decim_0.execute(decim_0_out, dst_buffer);
|
||||
|
||||
@@ -125,8 +129,26 @@ buffer_f32_t NarrowbandAMAudio::demodulate(const buffer_c16_t& channel) {
|
||||
}
|
||||
}
|
||||
|
||||
void NarrowbandAMAudio::configure_fs4(const std::array<int16_t, 24>& taps) {
|
||||
// Keep the short first-stage update coherent with the processing thread.
|
||||
chSysLock();
|
||||
decim_0_taps_ = taps;
|
||||
const auto direction = requested_fs4_direction_.load(std::memory_order_relaxed);
|
||||
using Shift = dsp::decimate::FIRC8xR16x24FS4Decim4::Shift;
|
||||
decim_0.configure(decim_0_taps_, 33554432,
|
||||
direction == RxFs4Direction::Up ? Shift::Up : Shift::Down);
|
||||
applied_fs4_direction_ = direction;
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
void NarrowbandAMAudio::on_message(const Message* const message) {
|
||||
switch (message->id) {
|
||||
case Message::ID::RxFs4Config:
|
||||
requested_fs4_direction_.store(
|
||||
static_cast<const RxFs4ConfigMessage*>(message)->direction,
|
||||
std::memory_order_relaxed);
|
||||
break;
|
||||
|
||||
case Message::ID::UpdateSpectrum:
|
||||
case Message::ID::SpectrumStreamingConfig:
|
||||
channel_spectrum.on_message(message);
|
||||
@@ -162,7 +184,7 @@ void NarrowbandAMAudio::configure(const AMConfigureMessage& message) {
|
||||
constexpr size_t channel_filter_input_fs = decim_2_output_fs;
|
||||
// const size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor;
|
||||
|
||||
decim_0.configure(message.decim_0_filter.taps, 33554432);
|
||||
configure_fs4(message.decim_0_filter.taps);
|
||||
audio_decim_0.configure(taps_audio_wide_halfband_0.taps);
|
||||
translating_decim_1.configure(
|
||||
message.decim_1_filter.taps, audio_decim_0_output_fs);
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "audio_output.hpp"
|
||||
#include "filtered_spectrum_collector.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
|
||||
class NarrowbandAMAudio : public BasebandProcessor {
|
||||
@@ -59,6 +60,10 @@ class NarrowbandAMAudio : public BasebandProcessor {
|
||||
audio.size()};
|
||||
|
||||
dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0{};
|
||||
std::array<int16_t, 24> decim_0_taps_{};
|
||||
std::atomic<RxFs4Direction> requested_fs4_direction_{RxFs4Direction::Down};
|
||||
RxFs4Direction applied_fs4_direction_{RxFs4Direction::Down};
|
||||
void configure_fs4(const std::array<int16_t, 24>& taps);
|
||||
dsp::decimate::FIRC16xR16x16Decim2 audio_decim_0{};
|
||||
dsp::FrequencyTranslatingDecimator32By8 translating_decim_1{};
|
||||
dsp::decimate::FIRAndDecimateComplex decim_2{};
|
||||
|
||||
@@ -34,6 +34,12 @@ CaptureProcessor::CaptureProcessor() {
|
||||
}
|
||||
|
||||
void CaptureProcessor::execute(const buffer_c8_t& buffer) {
|
||||
const auto direction = requested_fs4_direction_.load(std::memory_order_relaxed);
|
||||
if (direction != applied_fs4_direction_) {
|
||||
decim_0.configure_fs4(decim_0_taps_, direction);
|
||||
applied_fs4_direction_ = direction;
|
||||
}
|
||||
|
||||
auto decim_0_out = decim_0.execute(buffer, dst_buffer);
|
||||
auto out_buffer = decim_1.execute(decim_0_out, dst_buffer);
|
||||
|
||||
@@ -67,6 +73,12 @@ void CaptureProcessor::on_beep_message(const AudioBeepMessage& message) {
|
||||
|
||||
void CaptureProcessor::on_message(const Message* const message) {
|
||||
switch (message->id) {
|
||||
case Message::ID::RxFs4Config:
|
||||
requested_fs4_direction_.store(
|
||||
static_cast<const RxFs4ConfigMessage*>(message)->direction,
|
||||
std::memory_order_relaxed);
|
||||
break;
|
||||
|
||||
case Message::ID::UpdateSpectrum:
|
||||
case Message::ID::SpectrumStreamingConfig:
|
||||
channel_spectrum.on_message(message);
|
||||
@@ -125,34 +137,34 @@ void CaptureProcessor::sample_rate_config(const SampleRateConfigMessage& message
|
||||
switch (message.oversample_rate) {
|
||||
case OversampleRate::x4:
|
||||
// M4 can't handle 2 decimation passes for sample rates needing x4.
|
||||
decim_0.set<FIRC8xR16x24FS4Decim4>().configure(taps_200k_decim_0.taps);
|
||||
configure_fs4<FIRC8xR16x24FS4Decim4>(taps_200k_decim_0.taps);
|
||||
decim_1.set<NoopDecim>();
|
||||
break;
|
||||
|
||||
case OversampleRate::x8:
|
||||
// M4 can't handle 2 decimation passes for sample rates <= 600k.
|
||||
if (message.sample_rate < 600'000) {
|
||||
decim_0.set<FIRC8xR16x24FS4Decim4>().configure(taps_200k_decim_0.taps);
|
||||
configure_fs4<FIRC8xR16x24FS4Decim4>(taps_200k_decim_0.taps);
|
||||
decim_1.set<FIRC16xR16x16Decim2>().configure(taps_200k_decim_1.taps);
|
||||
} else {
|
||||
// Using 180k taps to provide better filtering with a single pass.
|
||||
decim_0.set<FIRC8xR16x24FS4Decim8>().configure(taps_180k_wfm_decim_0.taps);
|
||||
configure_fs4<FIRC8xR16x24FS4Decim8>(taps_180k_wfm_decim_0.taps);
|
||||
decim_1.set<NoopDecim>();
|
||||
}
|
||||
break;
|
||||
|
||||
case OversampleRate::x16:
|
||||
decim_0.set<FIRC8xR16x24FS4Decim8>().configure(taps_200k_decim_0.taps);
|
||||
configure_fs4<FIRC8xR16x24FS4Decim8>(taps_200k_decim_0.taps);
|
||||
decim_1.set<FIRC16xR16x16Decim2>().configure(taps_200k_decim_1.taps);
|
||||
break;
|
||||
|
||||
case OversampleRate::x32:
|
||||
decim_0.set<FIRC8xR16x24FS4Decim4>().configure(taps_200k_decim_0.taps);
|
||||
configure_fs4<FIRC8xR16x24FS4Decim4>(taps_200k_decim_0.taps);
|
||||
decim_1.set<FIRC16xR16x32Decim8>().configure(taps_16k0_decim_1.taps);
|
||||
break;
|
||||
|
||||
case OversampleRate::x64:
|
||||
decim_0.set<FIRC8xR16x24FS4Decim8>().configure(taps_200k_decim_0.taps);
|
||||
configure_fs4<FIRC8xR16x24FS4Decim8>(taps_200k_decim_0.taps);
|
||||
decim_1.set<FIRC16xR16x32Decim8>().configure(taps_16k0_decim_1.taps);
|
||||
break;
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#include "message.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <type_traits>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <variant>
|
||||
@@ -65,6 +67,16 @@ class MultiDecimator {
|
||||
decimator_);
|
||||
}
|
||||
|
||||
// Reconfigure only the active first-stage variant; preserve its factor.
|
||||
void configure_fs4(const std::array<int16_t, 24>& taps, RxFs4Direction direction) {
|
||||
std::visit([&](auto& decimator) {
|
||||
using Shift = typename std::decay_t<decltype(decimator)>::Shift;
|
||||
decimator.configure(taps, dsp::decimate::c8_to_c32_sat_scalar,
|
||||
direction == RxFs4Direction::Up ? Shift::Up : Shift::Down);
|
||||
},
|
||||
decimator_);
|
||||
}
|
||||
|
||||
size_t decimation_factor() const {
|
||||
return std::visit(
|
||||
[](auto&& arg) -> size_t {
|
||||
@@ -125,6 +137,21 @@ class CaptureProcessor : public BasebandProcessor {
|
||||
size_t spectrum_interval_samples = 0;
|
||||
size_t spectrum_samples = 0;
|
||||
|
||||
std::array<int16_t, 24> decim_0_taps_{};
|
||||
std::atomic<RxFs4Direction> requested_fs4_direction_{RxFs4Direction::Down};
|
||||
RxFs4Direction applied_fs4_direction_{RxFs4Direction::Down};
|
||||
|
||||
template <typename Decimator>
|
||||
void configure_fs4(const std::array<int16_t, 24>& taps) {
|
||||
// Variant selection, taps and direction must change together.
|
||||
chSysLock();
|
||||
decim_0.set<Decimator>();
|
||||
decim_0_taps_ = taps;
|
||||
applied_fs4_direction_ = requested_fs4_direction_.load(std::memory_order_relaxed);
|
||||
decim_0.configure_fs4(decim_0_taps_, applied_fs4_direction_);
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
/* NB: Threads should be the last members in the class definition. */
|
||||
BasebandThread baseband_thread{
|
||||
baseband_fs, this, baseband::Direction::Receive, /*auto_start*/ false};
|
||||
|
||||
@@ -50,6 +50,10 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only the processing thread applies frequency-only direction changes.
|
||||
if (requested_fs4_direction_.load(std::memory_order_relaxed) != applied_fs4_direction_)
|
||||
configure_fs4(decim_0_taps_);
|
||||
|
||||
const auto decim_0_out = decim_0.execute(buffer, dst_buffer);
|
||||
const auto audio_decim_0_out = audio_decim_0.execute(decim_0_out, dst_buffer);
|
||||
|
||||
@@ -137,8 +141,26 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
void NarrowbandFMAudio::configure_fs4(const std::array<int16_t, 24>& taps) {
|
||||
// Keep the short first-stage update coherent with the processing thread.
|
||||
chSysLock();
|
||||
decim_0_taps_ = taps;
|
||||
const auto direction = requested_fs4_direction_.load(std::memory_order_relaxed);
|
||||
using Shift = dsp::decimate::FIRC8xR16x24FS4Decim4::Shift;
|
||||
decim_0.configure(decim_0_taps_, 33554432,
|
||||
direction == RxFs4Direction::Up ? Shift::Up : Shift::Down);
|
||||
applied_fs4_direction_ = direction;
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
void NarrowbandFMAudio::on_message(const Message* const message) {
|
||||
switch (message->id) {
|
||||
case Message::ID::RxFs4Config:
|
||||
requested_fs4_direction_.store(
|
||||
static_cast<const RxFs4ConfigMessage*>(message)->direction,
|
||||
std::memory_order_relaxed);
|
||||
break;
|
||||
|
||||
case Message::ID::UpdateSpectrum:
|
||||
case Message::ID::SpectrumStreamingConfig:
|
||||
channel_spectrum.on_message(message);
|
||||
@@ -177,7 +199,7 @@ void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) {
|
||||
|
||||
const size_t demod_input_fs = channel_filter_output_fs;
|
||||
|
||||
decim_0.configure(message.decim_0_filter.taps, 33554432);
|
||||
configure_fs4(message.decim_0_filter.taps);
|
||||
audio_decim_0.configure(taps_audio_wide_halfband_0.taps);
|
||||
translating_decim_1.configure(
|
||||
message.decim_1_filter.taps, audio_decim_0_output_fs);
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "audio_output.hpp"
|
||||
#include "filtered_spectrum_collector.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
|
||||
#define Z_MIN_FILTER_COUNT 224
|
||||
@@ -72,6 +73,10 @@ class NarrowbandFMAudio : public BasebandProcessor {
|
||||
sizeof(tone) / sizeof(int16_t)};
|
||||
|
||||
dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0{};
|
||||
std::array<int16_t, 24> decim_0_taps_{};
|
||||
std::atomic<RxFs4Direction> requested_fs4_direction_{RxFs4Direction::Down};
|
||||
RxFs4Direction applied_fs4_direction_{RxFs4Direction::Down};
|
||||
void configure_fs4(const std::array<int16_t, 24>& taps);
|
||||
dsp::decimate::FIRC16xR16x16Decim2 audio_decim_0{};
|
||||
dsp::FrequencyTranslatingDecimator32By8 translating_decim_1{};
|
||||
dsp::decimate::FIRAndDecimateComplex channel_filter{};
|
||||
|
||||
@@ -35,6 +35,10 @@ void WidebandFMAudio::execute(const buffer_c8_t& buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only the processing thread applies frequency-only direction changes.
|
||||
if (requested_fs4_direction_.load(std::memory_order_relaxed) != applied_fs4_direction_)
|
||||
configure_fs4(decim_0_taps_);
|
||||
|
||||
const auto decim_0_out = decim_0.execute(buffer, dst_buffer);
|
||||
const auto channel = decim_1.execute(decim_0_out, dst_buffer);
|
||||
|
||||
@@ -159,8 +163,26 @@ void WidebandFMAudio::post_message(const buffer_c16_t& data) {
|
||||
fft_step = 0;
|
||||
}
|
||||
|
||||
void WidebandFMAudio::configure_fs4(const std::array<int16_t, 24>& taps) {
|
||||
// Keep the short first-stage update coherent with the processing thread.
|
||||
chSysLock();
|
||||
decim_0_taps_ = taps;
|
||||
const auto direction = requested_fs4_direction_.load(std::memory_order_relaxed);
|
||||
using Shift = dsp::decimate::FIRC8xR16x24FS4Decim4::Shift;
|
||||
decim_0.configure(decim_0_taps_, dsp::decimate::c8_to_c32_sat_scalar,
|
||||
direction == RxFs4Direction::Up ? Shift::Up : Shift::Down);
|
||||
applied_fs4_direction_ = direction;
|
||||
chSysUnlock();
|
||||
}
|
||||
|
||||
void WidebandFMAudio::on_message(const Message* const message) {
|
||||
switch (message->id) {
|
||||
case Message::ID::RxFs4Config:
|
||||
requested_fs4_direction_.store(
|
||||
static_cast<const RxFs4ConfigMessage*>(message)->direction,
|
||||
std::memory_order_relaxed);
|
||||
break;
|
||||
|
||||
case Message::ID::UpdateSpectrum:
|
||||
case Message::ID::SpectrumStreamingConfig:
|
||||
channel_spectrum.on_message(message);
|
||||
@@ -188,7 +210,7 @@ void WidebandFMAudio::configure_wfm(const WFMConfigureMessage& message) {
|
||||
constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0.decimation_factor;
|
||||
constexpr size_t decim_1_input_fs = decim_0_output_fs;
|
||||
|
||||
decim_0.configure(message.decim_0_filter.taps);
|
||||
configure_fs4(message.decim_0_filter.taps);
|
||||
// decim_1.configure(message.decim_1_filter.taps); // Original .
|
||||
|
||||
// TODO dynamic decim1 , with decimation 2 / 8 and 16 x taps , / 32 taps .
|
||||
@@ -219,7 +241,7 @@ void WidebandFMAudio::configure_wfmam(const WFMAMConfigureMessage& message) {
|
||||
constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0.decimation_factor;
|
||||
constexpr size_t decim_1_input_fs = decim_0_output_fs;
|
||||
|
||||
decim_0.configure(message.decim_0_filter.taps);
|
||||
configure_fs4(message.decim_0_filter.taps);
|
||||
|
||||
// decim_1.configure(message.decim_1_filter.taps); // Original .
|
||||
// TODO dynamic decim1 , with decimation 2 / 8 and 16 x taps , / 32 taps .
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#ifndef __PROC_WFM_AUDIO_H__
|
||||
#define __PROC_WFM_AUDIO_H__
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "baseband_processor.hpp"
|
||||
#include "baseband_thread.hpp"
|
||||
#include "rssi_thread.hpp"
|
||||
@@ -99,6 +101,10 @@ class WidebandFMAudio : public BasebandProcessor {
|
||||
complex_audio.size()};
|
||||
|
||||
dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0{};
|
||||
std::array<int16_t, 24> decim_0_taps_{};
|
||||
std::atomic<RxFs4Direction> requested_fs4_direction_{RxFs4Direction::Down};
|
||||
RxFs4Direction applied_fs4_direction_{RxFs4Direction::Down};
|
||||
void configure_fs4(const std::array<int16_t, 24>& taps);
|
||||
// dsp::decimate::FIRC16xR16x16Decim2 decim_1{}; //original condition , before adding wfmam
|
||||
|
||||
// decim_1 will handle different types of FIR filters depending on selection.
|
||||
|
||||
@@ -171,6 +171,7 @@ class Message {
|
||||
TetraBsch = 113,
|
||||
TetraDnb = 114,
|
||||
AudioDDCConfig = 115,
|
||||
RxFs4Config = 116,
|
||||
MAX
|
||||
};
|
||||
|
||||
@@ -311,6 +312,18 @@ class SpectrumStreamingConfigMessage : public Message {
|
||||
Mode mode{Mode::Stopped};
|
||||
};
|
||||
|
||||
// Application sample-rate translation, independent of PRALINE's AFE shift.
|
||||
enum class RxFs4Direction : uint8_t { Down,
|
||||
Up };
|
||||
|
||||
class RxFs4ConfigMessage : public Message {
|
||||
public:
|
||||
constexpr RxFs4ConfigMessage(RxFs4Direction direction)
|
||||
: Message{ID::RxFs4Config}, direction{direction} {}
|
||||
|
||||
const RxFs4Direction direction;
|
||||
};
|
||||
|
||||
class AudioDDCConfigMessage : public Message {
|
||||
public:
|
||||
constexpr AudioDDCConfigMessage(int32_t frequency)
|
||||
|
||||
Reference in New Issue
Block a user