mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-12 01:29:29 +00:00
Merge remote-tracking branch 'upstream/master'
Conflicts: firmware/application/Makefile firmware/application/analog_audio_app.cpp firmware/application/analog_audio_app.hpp firmware/application/event.cpp firmware/application/irq_ipc.hpp firmware/application/portapack.hpp firmware/application/receiver_model.cpp firmware/application/receiver_model.hpp firmware/application/recent_entries.cpp firmware/application/string_format.hpp firmware/application/ui_debug.cpp firmware/application/ui_debug.hpp firmware/application/ui_menu.cpp firmware/application/ui_navigation.cpp firmware/application/ui_navigation.hpp firmware/application/ui_receiver.cpp firmware/application/ui_receiver.hpp firmware/application/ui_sd_card_status_view.cpp firmware/application/ui_sd_card_status_view.hpp firmware/application/ui_setup.cpp firmware/application/ui_setup.hpp firmware/application/ui_spectrum.hpp firmware/baseband-tx/dsp_fir_taps.cpp firmware/baseband-tx/dsp_fir_taps.hpp firmware/baseband-tx/irq_ipc_m4.cpp firmware/baseband-tx/irq_ipc_m4.hpp firmware/baseband-tx/proc_audiotx.cpp firmware/baseband/Makefile firmware/baseband/audio_output.cpp firmware/baseband/audio_output.hpp firmware/baseband/block_decimator.hpp firmware/baseband/dsp_decimate.cpp firmware/baseband/dsp_decimate.hpp firmware/baseband/dsp_demodulate.cpp firmware/baseband/dsp_demodulate.hpp firmware/baseband/dsp_fir_taps.cpp firmware/baseband/irq_ipc_m4.cpp firmware/baseband/irq_ipc_m4.hpp firmware/baseband/proc_am_audio.cpp firmware/baseband/proc_am_audio.hpp firmware/baseband/proc_nfm_audio.cpp firmware/baseband/proc_nfm_audio.hpp firmware/baseband/proc_wfm_audio.cpp firmware/baseband/proc_wfm_audio.hpp firmware/baseband/spectrum_collector.hpp firmware/common/dsp_fir_taps.cpp firmware/common/dsp_fir_taps.hpp firmware/common/event.hpp firmware/common/message.hpp firmware/common/ui_painter.cpp firmware/common/ui_painter.hpp
This commit is contained in:
@@ -57,6 +57,17 @@ void AudioOutput::write(
|
||||
|
||||
void AudioOutput::write(
|
||||
const buffer_f32_t& audio
|
||||
) {
|
||||
block_buffer.feed(
|
||||
audio,
|
||||
[this](const buffer_f32_t& buffer) {
|
||||
this->on_block(buffer);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void AudioOutput::on_block(
|
||||
const buffer_f32_t& audio
|
||||
) {
|
||||
const auto audio_present_now = squelch.execute(audio);
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "dsp_iir.hpp"
|
||||
#include "dsp_squelch.hpp"
|
||||
|
||||
#include "block_decimator.hpp"
|
||||
#include "audio_stats_collector.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
@@ -43,6 +44,8 @@ public:
|
||||
void write(const buffer_f32_t& audio);
|
||||
|
||||
private:
|
||||
BlockDecimator<float, 32> block_buffer { 1 };
|
||||
|
||||
IIRBiquadFilter hpf;
|
||||
IIRBiquadFilter deemph;
|
||||
FMSquelch squelch;
|
||||
@@ -51,6 +54,7 @@ private:
|
||||
|
||||
uint64_t audio_present_history = 0;
|
||||
|
||||
void on_block(const buffer_f32_t& audio);
|
||||
void fill_audio_buffer(const buffer_f32_t& audio);
|
||||
void feed_audio_stats(const buffer_f32_t& audio);
|
||||
};
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "dsp_types.hpp"
|
||||
#include "complex.hpp"
|
||||
|
||||
template<size_t N>
|
||||
template<typename T, size_t N>
|
||||
class BlockDecimator {
|
||||
public:
|
||||
constexpr BlockDecimator(
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
}
|
||||
|
||||
template<typename BlockCallback>
|
||||
void feed(const buffer_c16_t& src, BlockCallback callback) {
|
||||
void feed(const buffer_t<T>& src, BlockCallback callback) {
|
||||
/* NOTE: Input block size must be >= factor */
|
||||
|
||||
set_input_sampling_rate(src.sampling_rate);
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<complex16_t, N> buffer;
|
||||
std::array<T, N> buffer;
|
||||
uint32_t input_sampling_rate_ { 0 };
|
||||
size_t factor_ { 1 };
|
||||
size_t src_i { 0 };
|
||||
|
||||
@@ -179,10 +179,6 @@ static inline uint32_t scale_round_and_pack(
|
||||
|
||||
// FIRC8xR16x24FS4Decim4 //////////////////////////////////////////////////
|
||||
|
||||
FIRC8xR16x24FS4Decim4::FIRC8xR16x24FS4Decim4() {
|
||||
z_.fill({});
|
||||
}
|
||||
|
||||
void FIRC8xR16x24FS4Decim4::configure(
|
||||
const std::array<tap_t, taps_count>& taps,
|
||||
const int32_t scale,
|
||||
@@ -196,6 +192,7 @@ void FIRC8xR16x24FS4Decim4::configure(
|
||||
taps_[i+3] = taps[i+3] * negate_factor;
|
||||
}
|
||||
output_scale = scale;
|
||||
z_.fill({});
|
||||
}
|
||||
|
||||
buffer_c16_t FIRC8xR16x24FS4Decim4::execute(
|
||||
@@ -244,10 +241,6 @@ buffer_c16_t FIRC8xR16x24FS4Decim4::execute(
|
||||
|
||||
// FIRC8xR16x24FS4Decim8 //////////////////////////////////////////////////
|
||||
|
||||
FIRC8xR16x24FS4Decim8::FIRC8xR16x24FS4Decim8() {
|
||||
z_.fill({});
|
||||
}
|
||||
|
||||
void FIRC8xR16x24FS4Decim8::configure(
|
||||
const std::array<tap_t, taps_count>& taps,
|
||||
const int32_t scale,
|
||||
@@ -261,6 +254,7 @@ void FIRC8xR16x24FS4Decim8::configure(
|
||||
taps_[i+3] = taps[i+3] * negate_factor;
|
||||
}
|
||||
output_scale = scale;
|
||||
z_.fill({});
|
||||
}
|
||||
|
||||
buffer_c16_t FIRC8xR16x24FS4Decim8::execute(
|
||||
@@ -309,16 +303,13 @@ buffer_c16_t FIRC8xR16x24FS4Decim8::execute(
|
||||
|
||||
// FIRC16xR16x16Decim2 ////////////////////////////////////////////////////
|
||||
|
||||
FIRC16xR16x16Decim2::FIRC16xR16x16Decim2() {
|
||||
z_.fill({});
|
||||
}
|
||||
|
||||
void FIRC16xR16x16Decim2::configure(
|
||||
const std::array<tap_t, taps_count>& taps,
|
||||
const int32_t scale
|
||||
) {
|
||||
std::copy(taps.cbegin(), taps.cend(), taps_.begin());
|
||||
output_scale = scale;
|
||||
z_.fill({});
|
||||
}
|
||||
|
||||
buffer_c16_t FIRC16xR16x16Decim2::execute(
|
||||
@@ -363,16 +354,13 @@ buffer_c16_t FIRC16xR16x16Decim2::execute(
|
||||
|
||||
// FIRC16xR16x32Decim8 ////////////////////////////////////////////////////
|
||||
|
||||
FIRC16xR16x32Decim8::FIRC16xR16x32Decim8() {
|
||||
z_.fill({});
|
||||
}
|
||||
|
||||
void FIRC16xR16x32Decim8::configure(
|
||||
const std::array<tap_t, taps_count>& taps,
|
||||
const int32_t scale
|
||||
) {
|
||||
std::copy(taps.cbegin(), taps.cend(), taps_.begin());
|
||||
output_scale = scale;
|
||||
z_.fill({});
|
||||
}
|
||||
|
||||
buffer_c16_t FIRC16xR16x32Decim8::execute(
|
||||
@@ -657,18 +645,6 @@ buffer_s16_t FIR64AndDecimateBy2Real::execute(
|
||||
return { dst.p, src.count / 2, src.sampling_rate / 2 };
|
||||
}
|
||||
|
||||
void FIRAndDecimateComplex::configure(
|
||||
const int16_t* const taps,
|
||||
const size_t taps_count,
|
||||
const size_t decimation_factor
|
||||
) {
|
||||
samples_ = std::make_unique<samples_t>(taps_count);
|
||||
taps_reversed_ = std::make_unique<taps_t>(taps_count);
|
||||
taps_count_ = taps_count;
|
||||
decimation_factor_ = decimation_factor;
|
||||
std::reverse_copy(&taps[0], &taps[taps_count], &taps_reversed_[0]);
|
||||
}
|
||||
|
||||
buffer_c16_t FIRAndDecimateComplex::execute(
|
||||
const buffer_c16_t& src,
|
||||
const buffer_c16_t& dst
|
||||
|
||||
@@ -103,8 +103,6 @@ public:
|
||||
Up = false
|
||||
};
|
||||
|
||||
FIRC8xR16x24FS4Decim4();
|
||||
|
||||
void configure(
|
||||
const std::array<tap_t, taps_count>& taps,
|
||||
const int32_t scale,
|
||||
@@ -135,8 +133,6 @@ public:
|
||||
Up = false
|
||||
};
|
||||
|
||||
FIRC8xR16x24FS4Decim8();
|
||||
|
||||
void configure(
|
||||
const std::array<tap_t, taps_count>& taps,
|
||||
const int32_t scale,
|
||||
@@ -162,8 +158,6 @@ public:
|
||||
using sample_t = complex16_t;
|
||||
using tap_t = int16_t;
|
||||
|
||||
FIRC16xR16x16Decim2();
|
||||
|
||||
void configure(
|
||||
const std::array<tap_t, taps_count>& taps,
|
||||
const int32_t scale
|
||||
@@ -188,8 +182,6 @@ public:
|
||||
using sample_t = complex16_t;
|
||||
using tap_t = int16_t;
|
||||
|
||||
FIRC16xR16x32Decim8();
|
||||
|
||||
void configure(
|
||||
const std::array<tap_t, taps_count>& taps,
|
||||
const int32_t scale
|
||||
@@ -243,11 +235,18 @@ private:
|
||||
size_t taps_count_;
|
||||
size_t decimation_factor_;
|
||||
|
||||
template<typename T>
|
||||
void configure(
|
||||
const int16_t* const taps,
|
||||
const T* const taps,
|
||||
const size_t taps_count,
|
||||
const size_t decimation_factor
|
||||
);
|
||||
) {
|
||||
samples_ = std::make_unique<samples_t>(taps_count);
|
||||
taps_reversed_ = std::make_unique<taps_t>(taps_count);
|
||||
taps_count_ = taps_count;
|
||||
decimation_factor_ = decimation_factor;
|
||||
std::reverse_copy(&taps[0], &taps[taps_count], &taps_reversed_[0]);
|
||||
}
|
||||
};
|
||||
|
||||
class DecimateBy2CIC4Real {
|
||||
|
||||
@@ -34,17 +34,10 @@ buffer_f32_t AM::execute(
|
||||
const buffer_c16_t& src,
|
||||
const buffer_f32_t& dst
|
||||
) {
|
||||
/* Intermediate maximum value: 46341 (when input is -32768,-32768). */
|
||||
/* Normalized to maximum 32767 for int16_t representation. */
|
||||
|
||||
const auto src_p = src.p;
|
||||
const auto src_end = &src.p[src.count];
|
||||
auto dst_p = dst.p;
|
||||
while(src_p < src_end) {
|
||||
// const auto s = *(src_p++);
|
||||
// const uint32_t r_sq = s.real() * s.real();
|
||||
// const uint32_t i_sq = s.imag() * s.imag();
|
||||
// const uint32_t mag_sq = r_sq + i_sq;
|
||||
const uint32_t sample0 = *__SIMD32(src_p)++;
|
||||
const uint32_t sample1 = *__SIMD32(src_p)++;
|
||||
const uint32_t mag_sq0 = __SMUAD(sample0, sample0);
|
||||
@@ -55,6 +48,23 @@ buffer_f32_t AM::execute(
|
||||
|
||||
return { dst.p, src.count, src.sampling_rate };
|
||||
}
|
||||
|
||||
buffer_f32_t SSB::execute(
|
||||
const buffer_c16_t& src,
|
||||
const buffer_f32_t& dst
|
||||
) {
|
||||
const complex16_t* src_p = src.p;
|
||||
const auto src_end = &src.p[src.count];
|
||||
auto dst_p = dst.p;
|
||||
while(src_p < src_end) {
|
||||
*(dst_p++) = (src_p++)->real();
|
||||
*(dst_p++) = (src_p++)->real();
|
||||
*(dst_p++) = (src_p++)->real();
|
||||
*(dst_p++) = (src_p++)->real();
|
||||
}
|
||||
|
||||
return { dst.p, src.count, src.sampling_rate };
|
||||
}
|
||||
/*
|
||||
static inline float angle_approx_4deg0(const complex32_t t) {
|
||||
const auto x = static_cast<float>(t.imag()) / static_cast<float>(t.real());
|
||||
@@ -89,8 +99,8 @@ buffer_f32_t FM::execute(
|
||||
const auto t0 = multiply_conjugate_s16_s32(s0, z);
|
||||
const auto t1 = multiply_conjugate_s16_s32(s1, s0);
|
||||
z = s1;
|
||||
*(dst_p++) = angle_approx_0deg27(t0) * k;
|
||||
*(dst_p++) = angle_approx_0deg27(t1) * k;
|
||||
*(dst_p++) = angle_precise(t0) * k;
|
||||
*(dst_p++) = angle_precise(t1) * k;
|
||||
}
|
||||
z_ = z;
|
||||
|
||||
|
||||
@@ -35,6 +35,14 @@ public:
|
||||
);
|
||||
};
|
||||
|
||||
class SSB {
|
||||
public:
|
||||
buffer_f32_t execute(
|
||||
const buffer_c16_t& src,
|
||||
const buffer_f32_t& dst
|
||||
);
|
||||
};
|
||||
|
||||
class FM {
|
||||
public:
|
||||
buffer_f32_t execute(
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __DSP_IIR_H__
|
||||
#define __DSP_IIR_H__
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "dsp_types.hpp"
|
||||
|
||||
struct iir_biquad_config_t {
|
||||
std::array<float, 3> b;
|
||||
std::array<float, 3> a;
|
||||
};
|
||||
|
||||
constexpr iir_biquad_config_t iir_config_passthrough {
|
||||
{ { 1.0f, 0.0f, 0.0f } },
|
||||
{ { 0.0f, 0.0f, 0.0f } },
|
||||
};
|
||||
|
||||
constexpr iir_biquad_config_t iir_config_no_pass {
|
||||
{ { 0.0f, 0.0f, 0.0f } },
|
||||
{ { 0.0f, 0.0f, 0.0f } },
|
||||
};
|
||||
|
||||
class IIRBiquadFilter {
|
||||
public:
|
||||
// http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
|
||||
constexpr IIRBiquadFilter(
|
||||
) : IIRBiquadFilter(iir_config_no_pass)
|
||||
{
|
||||
}
|
||||
|
||||
// Assume all coefficients are normalized so that a0=1.0
|
||||
constexpr IIRBiquadFilter(
|
||||
const iir_biquad_config_t& config
|
||||
) : config(config)
|
||||
{
|
||||
}
|
||||
|
||||
void configure(const iir_biquad_config_t& new_config);
|
||||
|
||||
void execute(const buffer_f32_t& buffer_in, const buffer_f32_t& buffer_out);
|
||||
void execute_in_place(const buffer_f32_t& buffer);
|
||||
|
||||
private:
|
||||
iir_biquad_config_t config;
|
||||
std::array<float, 3> x { { 0.0f, 0.0f, 0.0f } };
|
||||
std::array<float, 3> y { { 0.0f, 0.0f, 0.0f } };
|
||||
};
|
||||
|
||||
#endif/*__DSP_IIR_H__*/
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __DSP_IIR_CONFIG_H__
|
||||
#define __DSP_IIR_CONFIG_H__
|
||||
|
||||
#include "dsp_iir.hpp"
|
||||
|
||||
// scipy.signal.butter(2, 30 / 24000.0, 'highpass', analog=False)
|
||||
constexpr iir_biquad_config_t audio_hpf_30hz_config {
|
||||
{ 0.99722705f, -1.99445410f, 0.99722705f },
|
||||
{ 1.00000000f, -1.99444641f, 0.99446179f }
|
||||
};
|
||||
|
||||
// scipy.signal.butter(2, 300 / 24000.0, 'highpass', analog=False)
|
||||
constexpr iir_biquad_config_t audio_hpf_300hz_config {
|
||||
{ 0.97261390f, -1.94522780f, 0.97261390f },
|
||||
{ 1.00000000f, -1.94447766f, 0.94597794f }
|
||||
};
|
||||
|
||||
// scipy.signal.iirdesign(wp=8000 / 24000.0, ws= 4000 / 24000.0, gpass=1, gstop=18, ftype='ellip')
|
||||
constexpr iir_biquad_config_t non_audio_hpf_config {
|
||||
{ 0.51891061f, -0.95714180f, 0.51891061f },
|
||||
{ 1.0f , -0.79878302f, 0.43960231f }
|
||||
};
|
||||
|
||||
// scipy.signal.butter(1, 300 / 24000.0, 'lowpass', analog=False)
|
||||
// NOTE: Technically, order-1 filter, b[2] = a[2] = 0.
|
||||
constexpr iir_biquad_config_t audio_deemph_300_6_config {
|
||||
{ 0.01925927f, 0.01925927f, 0.00000000f },
|
||||
{ 1.00000000f, -0.96148145f, 0.00000000f }
|
||||
};
|
||||
|
||||
// 75us RC time constant, used in broadcast FM in Americas, South Korea
|
||||
// scipy.signal.butter(1, 2122 / 24000.0, 'lowpass', analog=False)
|
||||
// NOTE: Technically, order-1 filter, b[2] = a[2] = 0.
|
||||
constexpr iir_biquad_config_t audio_deemph_2122_6_config {
|
||||
{ 0.12264116f, 0.12264116f, 0.00000000f },
|
||||
{ 1.00000000f, -0.75471767f, 0.00000000f }
|
||||
};
|
||||
|
||||
#endif/*__DSP_IIR_CONFIG_H__*/
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include "proc_am_audio.hpp"
|
||||
|
||||
#include "dsp_iir_config.hpp"
|
||||
#include "audio_output.hpp"
|
||||
|
||||
#include <array>
|
||||
@@ -33,17 +32,25 @@ void NarrowbandAMAudio::execute(const buffer_c8_t& buffer) {
|
||||
|
||||
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 channel_out = channel_filter.execute(decim_1_out, dst_buffer);
|
||||
const auto decim_2_out = decim_2.execute(decim_1_out, dst_buffer);
|
||||
const auto channel_out = channel_filter.execute(decim_2_out, dst_buffer);
|
||||
|
||||
// TODO: Feed channel_stats post-decimation data?
|
||||
feed_channel_stats(channel_out);
|
||||
channel_spectrum.feed(channel_out, channel_filter_pass_f, channel_filter_stop_f);
|
||||
|
||||
auto audio = demod.execute(channel_out, work_audio_buffer);
|
||||
|
||||
auto audio = demodulate(channel_out);
|
||||
audio_output.write(audio);
|
||||
}
|
||||
|
||||
buffer_f32_t NarrowbandAMAudio::demodulate(const buffer_c16_t& channel) {
|
||||
if( modulation_ssb ) {
|
||||
return demod_ssb.execute(channel, audio_buffer);
|
||||
} else {
|
||||
return demod_am.execute(channel, audio_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void NarrowbandAMAudio::on_message(const Message* const message) {
|
||||
switch(message->id) {
|
||||
case Message::ID::UpdateSpectrum:
|
||||
@@ -61,27 +68,27 @@ void NarrowbandAMAudio::on_message(const Message* const message) {
|
||||
}
|
||||
|
||||
void NarrowbandAMAudio::configure(const AMConfigureMessage& message) {
|
||||
constexpr size_t baseband_fs = 3072000;
|
||||
|
||||
constexpr size_t decim_0_input_fs = baseband_fs;
|
||||
constexpr size_t decim_0_decimation_factor = 8;
|
||||
constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0_decimation_factor;
|
||||
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 = 8;
|
||||
constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1_decimation_factor;
|
||||
constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor;
|
||||
|
||||
constexpr size_t channel_filter_input_fs = decim_1_output_fs;
|
||||
constexpr size_t channel_filter_decimation_factor = 1;
|
||||
constexpr size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor;
|
||||
constexpr size_t decim_2_input_fs = decim_1_output_fs;
|
||||
constexpr size_t decim_2_output_fs = decim_2_input_fs / decim_2_decimation_factor;
|
||||
|
||||
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_2.configure(message.decim_2_filter.taps, decim_2_decimation_factor);
|
||||
channel_filter.configure(message.channel_filter.taps, channel_filter_decimation_factor);
|
||||
channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs;
|
||||
channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs;
|
||||
channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2)));
|
||||
audio_output.configure(audio_hpf_300hz_config);
|
||||
modulation_ssb = (message.modulation == AMConfigureMessage::Modulation::SSB);
|
||||
audio_output.configure(message.audio_hpf_config);
|
||||
|
||||
configured = true;
|
||||
}
|
||||
|
||||
@@ -39,23 +39,31 @@ public:
|
||||
void on_message(const Message* const message) override;
|
||||
|
||||
private:
|
||||
static constexpr size_t baseband_fs = 3072000;
|
||||
static constexpr size_t decim_2_decimation_factor = 4;
|
||||
static constexpr size_t channel_filter_decimation_factor = 1;
|
||||
|
||||
std::array<complex16_t, 512> dst;
|
||||
const buffer_c16_t dst_buffer {
|
||||
dst.data(),
|
||||
dst.size()
|
||||
};
|
||||
const buffer_f32_t work_audio_buffer {
|
||||
(float*)dst.data(),
|
||||
sizeof(dst) / sizeof(float)
|
||||
std::array<float, 32> audio;
|
||||
const buffer_f32_t audio_buffer {
|
||||
audio.data(),
|
||||
audio.size()
|
||||
};
|
||||
|
||||
dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0;
|
||||
dsp::decimate::FIRC16xR16x32Decim8 decim_1;
|
||||
dsp::decimate::FIRAndDecimateComplex decim_2;
|
||||
dsp::decimate::FIRAndDecimateComplex channel_filter;
|
||||
uint32_t channel_filter_pass_f;
|
||||
uint32_t channel_filter_stop_f;
|
||||
uint32_t channel_filter_pass_f = 0;
|
||||
uint32_t channel_filter_stop_f = 0;
|
||||
|
||||
dsp::demodulate::AM demod;
|
||||
bool modulation_ssb = false;
|
||||
dsp::demodulate::AM demod_am;
|
||||
dsp::demodulate::SSB demod_ssb;
|
||||
|
||||
AudioOutput audio_output;
|
||||
|
||||
@@ -63,6 +71,8 @@ private:
|
||||
|
||||
bool configured { false };
|
||||
void configure(const AMConfigureMessage& message);
|
||||
|
||||
buffer_f32_t demodulate(const buffer_c16_t& channel);
|
||||
};
|
||||
|
||||
#endif/*__PROC_AM_AUDIO_H__*/
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include "proc_nfm_audio.hpp"
|
||||
|
||||
#include "dsp_iir_config.hpp"
|
||||
#include "audio_output.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
@@ -39,8 +38,7 @@ void NarrowbandFMAudio::execute(const buffer_c8_t& buffer) {
|
||||
feed_channel_stats(channel_out);
|
||||
channel_spectrum.feed(channel_out, channel_filter_pass_f, channel_filter_stop_f);
|
||||
|
||||
auto audio = demod.execute(channel_out, work_audio_buffer);
|
||||
|
||||
auto audio = demod.execute(channel_out, audio_buffer);
|
||||
audio_output.write(audio);
|
||||
}
|
||||
|
||||
@@ -61,30 +59,25 @@ void NarrowbandFMAudio::on_message(const Message* const message) {
|
||||
}
|
||||
|
||||
void NarrowbandFMAudio::configure(const NBFMConfigureMessage& message) {
|
||||
constexpr size_t baseband_fs = 3072000;
|
||||
|
||||
constexpr size_t decim_0_input_fs = baseband_fs;
|
||||
constexpr size_t decim_0_decimation_factor = 8;
|
||||
constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0_decimation_factor;
|
||||
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 = 8;
|
||||
constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1_decimation_factor;
|
||||
constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor;
|
||||
|
||||
constexpr size_t channel_filter_input_fs = decim_1_output_fs;
|
||||
constexpr size_t channel_filter_decimation_factor = 1;
|
||||
constexpr size_t channel_filter_output_fs = channel_filter_input_fs / channel_filter_decimation_factor;
|
||||
const size_t channel_filter_output_fs = channel_filter_input_fs / message.channel_decimation;
|
||||
|
||||
constexpr size_t demod_input_fs = channel_filter_output_fs;
|
||||
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);
|
||||
channel_filter.configure(message.channel_filter.taps, channel_filter_decimation_factor);
|
||||
channel_filter.configure(message.channel_filter.taps, message.channel_decimation);
|
||||
demod.configure(demod_input_fs, message.deviation);
|
||||
channel_filter_pass_f = message.channel_filter.pass_frequency_normalized * channel_filter_input_fs;
|
||||
channel_filter_stop_f = message.channel_filter.stop_frequency_normalized * channel_filter_input_fs;
|
||||
channel_spectrum.set_decimation_factor(std::floor((channel_filter_output_fs / 2) / ((channel_filter_pass_f + channel_filter_stop_f) / 2)));
|
||||
audio_output.configure(audio_hpf_300hz_config, audio_deemph_300_6_config, 6144);
|
||||
audio_output.configure(message.audio_hpf_config, message.audio_deemph_config, 12288);
|
||||
|
||||
configured = true;
|
||||
}
|
||||
|
||||
@@ -24,12 +24,15 @@
|
||||
|
||||
#include "baseband_processor.hpp"
|
||||
|
||||
#include "channel_decimator.hpp"
|
||||
#include "dsp_decimate.hpp"
|
||||
#include "dsp_demodulate.hpp"
|
||||
|
||||
#include "audio_output.hpp"
|
||||
#include "spectrum_collector.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class NarrowbandFMAudio : public BasebandProcessor {
|
||||
public:
|
||||
void execute(const buffer_c8_t& buffer) override;
|
||||
@@ -37,19 +40,21 @@ public:
|
||||
void on_message(const Message* const message) override;
|
||||
|
||||
private:
|
||||
static constexpr size_t baseband_fs = 3072000;
|
||||
|
||||
std::array<complex16_t, 512> dst;
|
||||
const buffer_c16_t dst_buffer {
|
||||
dst.data(),
|
||||
dst.size()
|
||||
};
|
||||
const buffer_f32_t work_audio_buffer {
|
||||
(float*)dst.data(),
|
||||
sizeof(dst) / sizeof(float)
|
||||
std::array<float, 32> audio;
|
||||
const buffer_f32_t audio_buffer {
|
||||
audio.data(),
|
||||
audio.size()
|
||||
};
|
||||
|
||||
dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0;
|
||||
dsp::decimate::FIRC16xR16x32Decim8 decim_1;
|
||||
|
||||
dsp::decimate::FIRAndDecimateComplex channel_filter;
|
||||
uint32_t channel_filter_pass_f = 0;
|
||||
uint32_t channel_filter_stop_f = 0;
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
#include "proc_wfm_audio.hpp"
|
||||
|
||||
#include "dsp_iir_config.hpp"
|
||||
#include "audio_output.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
@@ -88,19 +87,14 @@ void WidebandFMAudio::on_message(const Message* const message) {
|
||||
}
|
||||
|
||||
void WidebandFMAudio::configure(const WFMConfigureMessage& message) {
|
||||
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_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 decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor;
|
||||
|
||||
constexpr size_t demod_input_fs = decim_1_output_fs;
|
||||
|
||||
constexpr auto spectrum_rate_hz = 50.0f;
|
||||
spectrum_interval_samples = decim_1_output_fs / spectrum_rate_hz;
|
||||
spectrum_samples = 0;
|
||||
|
||||
@@ -110,7 +104,7 @@ void WidebandFMAudio::configure(const WFMConfigureMessage& message) {
|
||||
channel_filter_stop_f = message.decim_1_filter.stop_frequency_normalized * decim_1_input_fs;
|
||||
demod.configure(demod_input_fs, message.deviation);
|
||||
audio_filter.configure(message.audio_filter.taps);
|
||||
audio_output.configure(audio_hpf_30hz_config, audio_deemph_2122_6_config);
|
||||
audio_output.configure(message.audio_hpf_config, message.audio_deemph_config);
|
||||
|
||||
channel_spectrum.set_decimation_factor(1);
|
||||
|
||||
|
||||
@@ -37,6 +37,9 @@ public:
|
||||
void on_message(const Message* const message) override;
|
||||
|
||||
private:
|
||||
static constexpr size_t baseband_fs = 3072000;
|
||||
static constexpr auto spectrum_rate_hz = 50.0f;
|
||||
|
||||
std::array<complex16_t, 512> dst;
|
||||
const buffer_c16_t dst_buffer {
|
||||
dst.data(),
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
);
|
||||
|
||||
private:
|
||||
BlockDecimator<256> channel_spectrum_decimator;
|
||||
BlockDecimator<complex16_t, 256> channel_spectrum_decimator;
|
||||
ChannelSpectrumFIFO fifo;
|
||||
|
||||
volatile bool channel_spectrum_request_update { false };
|
||||
|
||||
Reference in New Issue
Block a user