mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-12-25 15:29:37 -05:00
Use IFIR decimation for broadcast FM receiver.
This commit is contained in:
parent
a02bfe55d0
commit
e720bfb054
@ -618,6 +618,12 @@ buffer_c16_t DecimateBy2CIC3::execute(
|
|||||||
return { dst.p, src.count / 2, src.sampling_rate / 2 };
|
return { dst.p, src.count / 2, src.sampling_rate / 2 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FIR64AndDecimateBy2Real::configure(
|
||||||
|
const std::array<int16_t, taps_count>& new_taps
|
||||||
|
) {
|
||||||
|
std::copy(new_taps.cbegin(), new_taps.cend(), taps.begin());
|
||||||
|
}
|
||||||
|
|
||||||
buffer_s16_t FIR64AndDecimateBy2Real::execute(
|
buffer_s16_t FIR64AndDecimateBy2Real::execute(
|
||||||
buffer_s16_t src,
|
buffer_s16_t src,
|
||||||
buffer_s16_t dst
|
buffer_s16_t dst
|
||||||
|
@ -76,11 +76,9 @@ class FIR64AndDecimateBy2Real {
|
|||||||
public:
|
public:
|
||||||
static constexpr size_t taps_count = 64;
|
static constexpr size_t taps_count = 64;
|
||||||
|
|
||||||
FIR64AndDecimateBy2Real(
|
void configure(
|
||||||
const std::array<int16_t, taps_count>& taps
|
const std::array<int16_t, taps_count>& taps
|
||||||
) : taps(taps)
|
);
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer_s16_t execute(
|
buffer_s16_t execute(
|
||||||
buffer_s16_t src,
|
buffer_s16_t src,
|
||||||
@ -89,7 +87,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<int16_t, taps_count + 2> z;
|
std::array<int16_t, taps_count + 2> z;
|
||||||
const std::array<int16_t, taps_count>& taps;
|
std::array<int16_t, taps_count> taps;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FIRC8xR16x24FS4Decim4 {
|
class FIRC8xR16x24FS4Decim4 {
|
||||||
|
@ -182,6 +182,27 @@ constexpr fir_taps_real<32> taps_6k0_channel {
|
|||||||
} },
|
} },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// WFM 200KF8E emission type //////////////////////////////////////////////
|
||||||
|
|
||||||
|
constexpr fir_taps_real<24> taps_200k_wfm_decim_0 = {
|
||||||
|
.pass_frequency_normalized = 100000.0f / 3072000.0f,
|
||||||
|
.stop_frequency_normalized = 484000.0f / 3072000.0f,
|
||||||
|
.taps = { {
|
||||||
|
48, -18, -151, -364, -557, -548, -139, 789,
|
||||||
|
2187, 3800, 5230, 6071, 6071, 5230, 3800, 2187,
|
||||||
|
789, -139, -548, -557, -364, -151, -18, 48,
|
||||||
|
} },
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr fir_taps_real<16> taps_200k_wfm_decim_1 = {
|
||||||
|
.pass_frequency_normalized = 100000.0f / 768000.0f,
|
||||||
|
.stop_frequency_normalized = 284000.0f / 768000.0f,
|
||||||
|
.taps = { {
|
||||||
|
-67, -123, 388, 622, -1342, -2185, 4599, 14486,
|
||||||
|
14486, 4599, -2185, -1342, 622, 388, -123, -67,
|
||||||
|
} },
|
||||||
|
};
|
||||||
|
|
||||||
/* Wideband audio filter */
|
/* Wideband audio filter */
|
||||||
/* 96kHz int16_t input
|
/* 96kHz int16_t input
|
||||||
* -> FIR filter, <15kHz (0.156fs) pass, >19kHz (0.198fs) stop
|
* -> FIR filter, <15kHz (0.156fs) pass, >19kHz (0.198fs) stop
|
||||||
|
@ -23,8 +23,34 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
WidebandFMAudio::WidebandFMAudio() {
|
||||||
|
constexpr size_t baseband_fs = 3072000;
|
||||||
|
|
||||||
|
constexpr size_t decim_0_input_fs = baseband_fs;
|
||||||
|
constexpr size_t decim_0_decimation_factor = 4;
|
||||||
|
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;
|
||||||
|
constexpr size_t decim_1_decimation_factor = 2;
|
||||||
|
constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1_decimation_factor;
|
||||||
|
|
||||||
|
constexpr size_t demod_input_fs = decim_1_output_fs;
|
||||||
|
|
||||||
|
decim_0.configure(taps_200k_wfm_decim_0.taps, 33554432);
|
||||||
|
decim_1.configure(taps_200k_wfm_decim_1.taps, 131072);
|
||||||
|
demod.configure(demod_input_fs, 75000);
|
||||||
|
audio_filter.configure(taps_64_lp_156_198.taps);
|
||||||
|
}
|
||||||
|
|
||||||
void WidebandFMAudio::execute(const buffer_c8_t& buffer) {
|
void WidebandFMAudio::execute(const buffer_c8_t& buffer) {
|
||||||
auto decimator_out = decimator.execute(buffer);
|
const buffer_c16_t dst_buffer {
|
||||||
|
dst.data(),
|
||||||
|
dst.size()
|
||||||
|
};
|
||||||
|
|
||||||
|
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 buffer_s16_t work_audio_buffer {
|
const buffer_s16_t work_audio_buffer {
|
||||||
(int16_t*)decimator_out.p,
|
(int16_t*)decimator_out.p,
|
||||||
@ -37,29 +63,24 @@ void WidebandFMAudio::execute(const buffer_c8_t& buffer) {
|
|||||||
feed_channel_stats(channel);
|
feed_channel_stats(channel);
|
||||||
//feed_channel_spectrum(channel);
|
//feed_channel_spectrum(channel);
|
||||||
|
|
||||||
/* 768kHz complex<int16_t>[512]
|
/* 384kHz complex<int16_t>[256]
|
||||||
* -> FM demodulation
|
* -> FM demodulation
|
||||||
* -> 768kHz int16_t[512] */
|
* -> 384kHz int16_t[256] */
|
||||||
/* TODO: To improve adjacent channel rejection, implement complex channel filter:
|
/* TODO: To improve adjacent channel rejection, implement complex channel filter:
|
||||||
* pass < +/- 100kHz, stop > +/- 200kHz
|
* pass < +/- 100kHz, stop > +/- 200kHz
|
||||||
*/
|
*/
|
||||||
|
|
||||||
auto audio_oversampled = demod.execute(decimator_out, work_audio_buffer);
|
auto audio_oversampled = demod.execute(decimator_out, work_audio_buffer);
|
||||||
|
|
||||||
/* 768kHz int16_t[512]
|
|
||||||
* -> 4th order CIC decimation by 2, gain of 1
|
|
||||||
* -> 384kHz int16_t[256] */
|
|
||||||
auto audio_8fs = audio_dec_1.execute(audio_oversampled, work_audio_buffer);
|
|
||||||
|
|
||||||
/* 384kHz int16_t[256]
|
/* 384kHz int16_t[256]
|
||||||
* -> 4th order CIC decimation by 2, gain of 1
|
* -> 4th order CIC decimation by 2, gain of 1
|
||||||
* -> 192kHz int16_t[128] */
|
* -> 192kHz int16_t[128] */
|
||||||
auto audio_4fs = audio_dec_2.execute(audio_8fs, work_audio_buffer);
|
auto audio_4fs = audio_dec_1.execute(audio_oversampled, work_audio_buffer);
|
||||||
|
|
||||||
/* 192kHz int16_t[128]
|
/* 192kHz int16_t[128]
|
||||||
* -> 4th order CIC decimation by 2, gain of 1
|
* -> 4th order CIC decimation by 2, gain of 1
|
||||||
* -> 96kHz int16_t[64] */
|
* -> 96kHz int16_t[64] */
|
||||||
auto audio_2fs = audio_dec_3.execute(audio_4fs, work_audio_buffer);
|
auto audio_2fs = audio_dec_2.execute(audio_4fs, work_audio_buffer);
|
||||||
|
|
||||||
/* 96kHz int16_t[64]
|
/* 96kHz int16_t[64]
|
||||||
* -> FIR filter, <15kHz (0.156fs) pass, >19kHz (0.198fs) stop, gain of 1
|
* -> FIR filter, <15kHz (0.156fs) pass, >19kHz (0.198fs) stop, gain of 1
|
||||||
|
@ -33,21 +33,19 @@
|
|||||||
|
|
||||||
class WidebandFMAudio : public BasebandProcessor {
|
class WidebandFMAudio : public BasebandProcessor {
|
||||||
public:
|
public:
|
||||||
WidebandFMAudio() {
|
WidebandFMAudio();
|
||||||
decimator.set_decimation_factor(ChannelDecimator::DecimationFactor::By4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void execute(const buffer_c8_t& buffer) override;
|
void execute(const buffer_c8_t& buffer) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ChannelDecimator decimator;
|
std::array<complex16_t, 512> dst;
|
||||||
|
dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0;
|
||||||
|
dsp::decimate::FIRC16xR16x16Decim2 decim_1;
|
||||||
|
|
||||||
dsp::demodulate::FM demod { 768000, 75000 };
|
dsp::demodulate::FM demod;
|
||||||
dsp::decimate::DecimateBy2CIC4Real audio_dec_1;
|
dsp::decimate::DecimateBy2CIC4Real audio_dec_1;
|
||||||
dsp::decimate::DecimateBy2CIC4Real audio_dec_2;
|
dsp::decimate::DecimateBy2CIC4Real audio_dec_2;
|
||||||
dsp::decimate::DecimateBy2CIC4Real audio_dec_3;
|
dsp::decimate::FIR64AndDecimateBy2Real audio_filter;
|
||||||
const fir_taps_real<64>& audio_filter_taps = taps_64_lp_156_198;
|
|
||||||
dsp::decimate::FIR64AndDecimateBy2Real audio_filter { audio_filter_taps.taps };
|
|
||||||
|
|
||||||
IIRBiquadFilter audio_hpf { audio_hpf_30hz_config };
|
IIRBiquadFilter audio_hpf { audio_hpf_30hz_config };
|
||||||
IIRBiquadFilter audio_deemph { audio_deemph_2122_6_config };
|
IIRBiquadFilter audio_deemph { audio_deemph_2122_6_config };
|
||||||
|
Loading…
Reference in New Issue
Block a user