Files
stafur b2bf0f2459 Legacy Initialization, Analog Audio App, and Aliasing fixes. (#3052)
* Added PRO button to analog_audio.cpp for debugging metallic ringing sounds in Audio app. Ensured consitency to 4MHz in analog_audio.cpp

* Restored blutooth after loss.

* Added several sampling rates to analog_audio for testing.

* Ran format-code.sh

* Fixed 0x03 mode for DC/Q-INV/Q-SHFT being set at every tuning and sample rate change. This was the root cause for loss of bluetooth before. Sample rate, and frequency can now be changed without need for manually resetting DC/Q-INV/Q-SHIFT settings. Updated method for setting frequncies in praline so that we have more testing options.

* Ran format-code.sh and cleaned up stale comments.

* Addressed comments, and removed commented line, opting for higher register values, 5E and 5D. Added WFM Debug View to support testing demodulation ringing.

* Addressed comments in PR conversation to clean comments and ensure consistency at initializtion accross updated methods and displays.

* Ran format-code.sh

* Set initial legacy state. Improved readability of clocking initialization settings. Updated set_sampling_frequency, and udpate_bandwidth to set decimation values in the fpga_registers to avoid aliasing in low band frequencies.

* Updated clock_manager to use correct clock and clock parameters for audio pll. Ran format-code.sh.
2026-02-27 23:43:19 -05:00

153 lines
4.7 KiB
C++

/*
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
* Copyright (C) 2016 Furrtek
*
* 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 __PROC_WFM_AUDIO_H__
#define __PROC_WFM_AUDIO_H__
#include "baseband_processor.hpp"
#include "baseband_thread.hpp"
#include "rssi_thread.hpp"
#include "dsp_types.hpp"
#include "dsp_decimate.hpp"
#include "dsp_demodulate.hpp"
#include "block_decimator.hpp"
#include "audio_output.hpp"
#include "spectrum_collector.hpp"
#include <array>
#include <memory>
#include <tuple>
#include <variant>
template <typename... Args>
class MultiDecimator {
public:
/* Dispatches to the underlying type's execute. */
template <typename Source, typename Destination>
Destination execute(
const Source& src,
const Destination& dst) {
return std::visit(
[&src, &dst](auto&& arg) -> Destination {
return arg.execute(src, dst);
},
decimator_);
}
size_t decimation_factor() const {
return std::visit(
[](auto&& arg) -> size_t {
return arg.decimation_factor;
},
decimator_);
}
/* Sets this decimator to a new instance of the specified decimator type.
* NB: The instance is returned by-ref so 'configure' can easily be called. */
template <typename Decimator>
Decimator& set() {
decimator_ = Decimator{};
return std::get<Decimator>(decimator_);
}
private:
std::variant<Args...> decimator_{};
};
class WidebandFMAudio : public BasebandProcessor {
public:
void execute(const buffer_c8_t& buffer) override;
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(),
dst.size()};
// work_audio_buffer and dst_buffer use the same data pointer
const buffer_s16_t work_audio_buffer{
(int16_t*)dst.data(),
sizeof(dst) / sizeof(int16_t)};
std::array<complex16_t, 64> complex_audio{};
const buffer_c16_t complex_audio_buffer{
complex_audio.data(),
complex_audio.size()};
dsp::decimate::FIRC8xR16x24FS4Decim4 decim_0{};
// dsp::decimate::FIRC16xR16x16Decim2 decim_1{}; //original condition , before adding wfmam
// decim_1 will handle different types of FIR filters depending on selection.
MultiDecimator<
dsp::decimate::FIRC16xR16x16Decim2,
dsp::decimate::FIRC16xR16x32Decim8>
decim_1{};
// dsp::decimate::FIRC16xR16x32Decim8 decim_1{}; // For FMAM
int32_t channel_filter_low_f = 0;
int32_t channel_filter_high_f = 0;
int32_t channel_filter_transition = 0;
dsp::demodulate::FM demod{};
dsp::decimate::DecimateBy2CIC4Real audio_dec_1{};
dsp::decimate::DecimateBy2CIC4Real audio_dec_2{};
dsp::decimate::FIR64AndDecimateBy2Real audio_filter{};
AudioOutput audio_output{};
// For fs=96kHz FFT streaming
BlockDecimator<complex16_t, 256> audio_spectrum_decimator{1};
std::array<std::complex<float>, 256> audio_spectrum{};
uint32_t audio_spectrum_timer{0};
enum AudioSpectrumState {
IDLE = 0,
FEED,
FFT
};
AudioSpectrumState audio_spectrum_state{IDLE};
AudioSpectrum spectrum{};
uint32_t fft_step{0};
SpectrumCollector channel_spectrum{};
size_t spectrum_interval_samples = 0;
size_t spectrum_samples = 0;
bool configured{false};
/* NB: Threads should be the last members in the class definition. */
BasebandThread baseband_thread{baseband_fs, this, baseband::Direction::Receive};
RSSIThread rssi_thread{};
void configure_wfm(const WFMConfigureMessage& message);
void configure_wfmam(const WFMAMConfigureMessage& message);
void capture_config(const CaptureConfigMessage& message);
void post_message(const buffer_c16_t& data);
};
#endif /*__PROC_WFM_AUDIO_H__*/