mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-10-01 01:26:06 -04:00
Explain and clean up decimator scalars (#1422)
This commit is contained in:
parent
4bc752b7a8
commit
f46e20c977
@ -23,19 +23,26 @@
|
||||
#define __DSP_DECIMATE_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include "dsp_types.hpp"
|
||||
|
||||
#include "simd.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace dsp {
|
||||
namespace decimate {
|
||||
|
||||
/* "Saturating" scalars used by decimators to scale either
|
||||
* 8 or 16 bit complex values into 32 bit complex values.
|
||||
* Some of the decimators accept a scale factor as part of
|
||||
* configuration, which is then passed to scale_round_and_pack. */
|
||||
// c8_to_c32_sat_scalar == 2^25. 2^25 * 2^7 (signed C8 Max) == 2^32.
|
||||
constexpr int32_t c8_to_c32_sat_scalar = 0x2000000;
|
||||
// c16_to_c32_sat_scalar == 2^17. 2^17 * 2^15 (signed C16 Max) == 2^32.
|
||||
constexpr int32_t c16_to_c32_sat_scalar = 0x20000;
|
||||
|
||||
class Complex8DecimateBy2CIC3 {
|
||||
public:
|
||||
buffer_c16_t execute(
|
||||
@ -100,7 +107,7 @@ class FIRC8xR16x24FS4Decim4 {
|
||||
|
||||
void configure(
|
||||
const std::array<tap_t, taps_count>& taps,
|
||||
const int32_t scale,
|
||||
const int32_t scale = c8_to_c32_sat_scalar,
|
||||
const Shift shift = Shift::Down);
|
||||
|
||||
buffer_c16_t execute(
|
||||
@ -128,7 +135,7 @@ class FIRC8xR16x24FS4Decim8 {
|
||||
|
||||
void configure(
|
||||
const std::array<tap_t, taps_count>& taps,
|
||||
const int32_t scale,
|
||||
const int32_t scale = c8_to_c32_sat_scalar,
|
||||
const Shift shift = Shift::Down);
|
||||
|
||||
buffer_c16_t execute(
|
||||
@ -151,7 +158,7 @@ class FIRC16xR16x16Decim2 {
|
||||
|
||||
void configure(
|
||||
const std::array<tap_t, taps_count>& taps,
|
||||
const int32_t scale);
|
||||
const int32_t scale = c16_to_c32_sat_scalar);
|
||||
|
||||
buffer_c16_t execute(
|
||||
const buffer_c16_t& src,
|
||||
@ -173,7 +180,7 @@ class FIRC16xR16x32Decim8 {
|
||||
|
||||
void configure(
|
||||
const std::array<tap_t, taps_count>& taps,
|
||||
const int32_t scale);
|
||||
const int32_t scale = c16_to_c32_sat_scalar);
|
||||
|
||||
buffer_c16_t execute(
|
||||
const buffer_c16_t& src,
|
||||
|
@ -29,8 +29,8 @@
|
||||
#include "event_m4.hpp"
|
||||
|
||||
ACARSProcessor::ACARSProcessor() {
|
||||
decim_0.configure(taps_11k0_decim_0.taps, 33554432);
|
||||
decim_1.configure(taps_11k0_decim_1.taps, 131072);
|
||||
decim_0.configure(taps_11k0_decim_0.taps);
|
||||
decim_1.configure(taps_11k0_decim_1.taps);
|
||||
packet.clear();
|
||||
baseband_thread.start();
|
||||
}
|
||||
|
@ -154,8 +154,8 @@ void AFSKRxProcessor::configure(const AFSKRxConfigureMessage& message) {
|
||||
|
||||
const size_t demod_input_fs = channel_filter_output_fs;*/
|
||||
|
||||
decim_0.configure(taps_11k0_decim_0.taps, 33554432);
|
||||
decim_1.configure(taps_11k0_decim_1.taps, 131072);
|
||||
decim_0.configure(taps_11k0_decim_0.taps);
|
||||
decim_1.configure(taps_11k0_decim_1.taps);
|
||||
channel_filter.configure(taps_11k0_channel.taps, 2);
|
||||
demod.configure(audio_fs, 5000);
|
||||
|
||||
|
@ -28,8 +28,8 @@
|
||||
#include "event_m4.hpp"
|
||||
|
||||
AISProcessor::AISProcessor() {
|
||||
decim_0.configure(taps_11k0_decim_0.taps, 33554432);
|
||||
decim_1.configure(taps_11k0_decim_1.taps, 131072);
|
||||
decim_0.configure(taps_11k0_decim_0.taps);
|
||||
decim_1.configure(taps_11k0_decim_1.taps);
|
||||
baseband_thread.start();
|
||||
}
|
||||
|
||||
|
@ -89,8 +89,8 @@ 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);
|
||||
decim_1.configure(message.decim_1_filter.taps, 131072);
|
||||
decim_0.configure(message.decim_0_filter.taps);
|
||||
decim_1.configure(message.decim_1_filter.taps);
|
||||
decim_2.configure(message.decim_2_filter.taps, decim_2_decimation_factor);
|
||||
channel_filter.configure(message.channel_filter.taps, channel_filter_decimation_factor);
|
||||
channel_filter_low_f = message.channel_filter.low_frequency_normalized * channel_filter_input_fs;
|
||||
|
@ -223,8 +223,8 @@ void APRSRxProcessor::capture_config(const CaptureConfigMessage& message) {
|
||||
}
|
||||
|
||||
void APRSRxProcessor::configure(const APRSRxConfigureMessage& message) {
|
||||
decim_0.configure(taps_11k0_decim_0.taps, 33554432);
|
||||
decim_1.configure(taps_11k0_decim_1.taps, 131072);
|
||||
decim_0.configure(taps_11k0_decim_0.taps);
|
||||
decim_1.configure(taps_11k0_decim_1.taps);
|
||||
channel_filter.configure(taps_11k0_channel.taps, 2);
|
||||
demod.configure(audio_fs, 5000);
|
||||
|
||||
|
@ -276,8 +276,8 @@ void BTLERxProcessor::on_message(const Message* const message) {
|
||||
|
||||
void BTLERxProcessor::configure(const BTLERxConfigureMessage& message) {
|
||||
(void)message; // avoid warning
|
||||
decim_0.configure(taps_200k_wfm_decim_0.taps, 33554432);
|
||||
decim_1.configure(taps_200k_wfm_decim_1.taps, 131072);
|
||||
decim_0.configure(taps_200k_wfm_decim_0.taps);
|
||||
decim_1.configure(taps_200k_wfm_decim_1.taps);
|
||||
demod.configure(audio_fs, 5000);
|
||||
|
||||
configured = true;
|
||||
|
@ -104,43 +104,38 @@ void CaptureProcessor::sample_rate_config(const SampleRateConfigMessage& message
|
||||
if (sample_rate >= 1'500'000)
|
||||
spectrum_interval_samples /= (sample_rate / 750'000);
|
||||
|
||||
// Mystery scalars for decimator configuration.
|
||||
// TODO: figure these out and add a real comment.
|
||||
constexpr int decim_0_scale = 0x2000000;
|
||||
constexpr int decim_1_scale = 0x20000;
|
||||
|
||||
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, decim_0_scale);
|
||||
decim_0.set<FIRC8xR16x24FS4Decim4>().configure(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, decim_0_scale);
|
||||
decim_1.set<FIRC16xR16x16Decim2>().configure(taps_200k_decim_1.taps, decim_1_scale);
|
||||
decim_0.set<FIRC8xR16x24FS4Decim4>().configure(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, decim_0_scale);
|
||||
decim_0.set<FIRC8xR16x24FS4Decim8>().configure(taps_180k_wfm_decim_0.taps);
|
||||
decim_1.set<NoopDecim>();
|
||||
}
|
||||
break;
|
||||
|
||||
case OversampleRate::x16:
|
||||
decim_0.set<FIRC8xR16x24FS4Decim8>().configure(taps_200k_decim_0.taps, decim_0_scale);
|
||||
decim_1.set<FIRC16xR16x16Decim2>().configure(taps_200k_decim_1.taps, decim_1_scale);
|
||||
decim_0.set<FIRC8xR16x24FS4Decim8>().configure(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, decim_0_scale);
|
||||
decim_1.set<FIRC16xR16x32Decim8>().configure(taps_16k0_decim_1.taps, decim_1_scale);
|
||||
decim_0.set<FIRC8xR16x24FS4Decim4>().configure(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, decim_0_scale);
|
||||
decim_1.set<FIRC16xR16x32Decim8>().configure(taps_16k0_decim_1.taps, decim_1_scale);
|
||||
decim_0.set<FIRC8xR16x24FS4Decim8>().configure(taps_200k_decim_0.taps);
|
||||
decim_1.set<FIRC16xR16x32Decim8>().configure(taps_16k0_decim_1.taps);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -144,8 +144,8 @@ 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);
|
||||
decim_1.configure(message.decim_1_filter.taps, 131072);
|
||||
decim_0.configure(message.decim_0_filter.taps);
|
||||
decim_1.configure(message.decim_1_filter.taps);
|
||||
channel_filter.configure(message.channel_filter.taps, message.channel_decimation);
|
||||
demod.configure(demod_input_fs, message.deviation);
|
||||
channel_filter_low_f = message.channel_filter.low_frequency_normalized * channel_filter_input_fs;
|
||||
|
@ -243,8 +243,8 @@ void NRFRxProcessor::on_message(const Message* const message) {
|
||||
|
||||
void NRFRxProcessor::configure(const NRFRxConfigureMessage& message) {
|
||||
(void)message; // avoir unused warning
|
||||
decim_0.configure(taps_200k_wfm_decim_0.taps, 33554432);
|
||||
decim_1.configure(taps_200k_wfm_decim_1.taps, 131072);
|
||||
decim_0.configure(taps_200k_wfm_decim_0.taps);
|
||||
decim_1.configure(taps_200k_wfm_decim_1.taps);
|
||||
demod.configure(audio_fs, 5000);
|
||||
|
||||
configured = true;
|
||||
|
@ -107,8 +107,8 @@ void POCSAGProcessor::configure() {
|
||||
|
||||
const size_t demod_input_fs = channel_filter_output_fs;
|
||||
|
||||
decim_0.configure(taps_11k0_decim_0.taps, 33554432);
|
||||
decim_1.configure(taps_11k0_decim_1.taps, 131072);
|
||||
decim_0.configure(taps_11k0_decim_0.taps);
|
||||
decim_1.configure(taps_11k0_decim_1.taps);
|
||||
channel_filter.configure(taps_11k0_channel.taps, 2);
|
||||
demod.configure(demod_input_fs, 4'500); // FSK +/- 4k5Hz.
|
||||
|
||||
|
@ -29,8 +29,8 @@
|
||||
#include "audio_output.hpp"
|
||||
|
||||
SondeProcessor::SondeProcessor() {
|
||||
decim_0.configure(taps_11k0_decim_0.taps, 33554432);
|
||||
decim_1.configure(taps_11k0_decim_1.taps, 131072);
|
||||
decim_0.configure(taps_11k0_decim_0.taps);
|
||||
decim_1.configure(taps_11k0_decim_1.taps);
|
||||
|
||||
audio_output.configure(false);
|
||||
|
||||
|
@ -27,8 +27,8 @@
|
||||
#include "event_m4.hpp"
|
||||
|
||||
TestProcessor::TestProcessor() {
|
||||
decim_0.configure(taps_11k0_decim_0.taps, 33554432);
|
||||
decim_1.configure(taps_11k0_decim_1.taps, 131072);
|
||||
decim_0.configure(taps_11k0_decim_0.taps);
|
||||
decim_1.configure(taps_11k0_decim_1.taps);
|
||||
baseband_thread.start();
|
||||
}
|
||||
|
||||
|
@ -26,8 +26,8 @@
|
||||
#include "event_m4.hpp"
|
||||
|
||||
TPMSProcessor::TPMSProcessor() {
|
||||
decim_0.configure(taps_200k_decim_0.taps, 33554432);
|
||||
decim_1.configure(taps_200k_decim_1.taps, 131072);
|
||||
decim_0.configure(taps_200k_decim_0.taps);
|
||||
decim_1.configure(taps_200k_decim_1.taps);
|
||||
baseband_thread.start();
|
||||
}
|
||||
|
||||
|
@ -165,8 +165,8 @@ void WidebandFMAudio::configure(const WFMConfigureMessage& message) {
|
||||
spectrum_interval_samples = decim_1_output_fs / spectrum_rate_hz;
|
||||
spectrum_samples = 0;
|
||||
|
||||
decim_0.configure(message.decim_0_filter.taps, 33554432);
|
||||
decim_1.configure(message.decim_1_filter.taps, 131072);
|
||||
decim_0.configure(message.decim_0_filter.taps);
|
||||
decim_1.configure(message.decim_1_filter.taps);
|
||||
channel_filter_low_f = message.decim_1_filter.low_frequency_normalized * decim_1_input_fs;
|
||||
channel_filter_high_f = message.decim_1_filter.high_frequency_normalized * decim_1_input_fs;
|
||||
channel_filter_transition = message.decim_1_filter.transition_normalized * decim_1_input_fs;
|
||||
|
@ -36,24 +36,12 @@ struct complex<int8_t> {
|
||||
typedef int8_t value_type;
|
||||
typedef uint16_t rep_type;
|
||||
|
||||
// constexpr complex(
|
||||
// rep_type r
|
||||
// ) : _rep { r }
|
||||
// {
|
||||
// }
|
||||
|
||||
constexpr complex(
|
||||
int8_t re = 0,
|
||||
int8_t im = 0)
|
||||
: _v{re, im} {
|
||||
}
|
||||
|
||||
// constexpr complex(
|
||||
// const complex& o
|
||||
// ) : _rep { o._rep }
|
||||
// {
|
||||
// }
|
||||
|
||||
constexpr int8_t real() const { return _v[0]; }
|
||||
constexpr int8_t imag() const { return _v[1]; }
|
||||
|
||||
@ -77,24 +65,12 @@ struct complex<int16_t> {
|
||||
typedef int16_t value_type;
|
||||
typedef uint32_t rep_type;
|
||||
|
||||
// constexpr complex(
|
||||
// rep_type r
|
||||
// ) : _rep { r }
|
||||
// {
|
||||
// }
|
||||
|
||||
constexpr complex(
|
||||
int16_t re = 0,
|
||||
int16_t im = 0)
|
||||
: _v{re, im} {
|
||||
}
|
||||
|
||||
// constexpr complex(
|
||||
// const complex& o
|
||||
// ) : _rep { o._rep }
|
||||
// {
|
||||
// }
|
||||
|
||||
constexpr int16_t real() const { return _v[0]; }
|
||||
constexpr int16_t imag() const { return _v[1]; }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user