Oversample (#1336)

* WIP Oversample cleanup

* WIP

* WIP

* WIP dynamic interpolation

* WIP cleanup

* Fix math errors

* Add some optional assertions

* Add support for x32 interpolation

* Update proc_replay.cpp

Typo
This commit is contained in:
Kyle Reed
2023-08-02 12:59:26 -07:00
committed by GitHub
parent e2ad0a1b1a
commit 37386c29cb
20 changed files with 272 additions and 169 deletions

View File

@@ -49,6 +49,7 @@ using Timestamp = lpc43xx::rtc::RTC;
template <typename T>
struct buffer_t {
using Type = T;
T* const p;
const size_t count;
const uint32_t sampling_rate;

View File

@@ -78,7 +78,7 @@ class Message {
ReplayThreadDone = 21,
AFSKRxConfigure = 22,
StatusRefresh = 23,
SamplerateConfig = 24,
SampleRateConfig = 24,
BTLERxConfigure = 25,
NRFRxConfigure = 26,
TXProgress = 27,
@@ -111,7 +111,6 @@ class Message {
APRSRxConfigure = 54,
SpectrumPainterBufferRequestConfigure = 55,
SpectrumPainterBufferResponseConfigure = 56,
OversampleRateConfig = 57,
MAX
};
@@ -799,32 +798,37 @@ class RetuneMessage : public Message {
uint32_t range = 0;
};
class SamplerateConfigMessage : public Message {
public:
constexpr SamplerateConfigMessage(
const uint32_t sample_rate)
: Message{ID::SamplerateConfig},
sample_rate(sample_rate) {
}
const uint32_t sample_rate = 0;
};
/* Controls decimation handling in proc_capture. */
/* Oversample/Interpolation sample rate multipliers. */
enum class OversampleRate : uint8_t {
Rate8x = 8,
Rate16x = 16,
/* Use either to indicate there's no oversampling needed. */
None = 1,
x1 = None,
// 4x would make sense to have, but need to ensure it doesn't
// overrun the IQ read buffer in proc_replay.
/* Oversample rate of 8 times the sample rate. */
x8 = 8,
/* Oversample rate of 16 times the sample rate. */
x16 = 16,
/* Oversample rate of 32 times the sample rate. */
x32 = 32,
};
class OversampleRateConfigMessage : public Message {
class SampleRateConfigMessage : public Message {
public:
constexpr OversampleRateConfigMessage(
constexpr SampleRateConfigMessage(
uint32_t sample_rate,
OversampleRate oversample_rate)
: Message{ID::OversampleRateConfig},
: Message{ID::SampleRateConfig},
sample_rate(sample_rate),
oversample_rate(oversample_rate) {
}
const OversampleRate oversample_rate{OversampleRate::Rate8x};
const uint32_t sample_rate = 0;
const OversampleRate oversample_rate = OversampleRate::None;
};
class AudioLevelReportMessage : public Message {

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2023 Kyle Reed, zxkmm
*
* 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.
*/
/* Helpers for handling oversampling and interpolation. */
#ifndef __OVERSAMPLE_H__
#define __OVERSAMPLE_H__
#include "message.hpp"
#include "utility.hpp"
/* TODO:
* The decision to oversample/interpolate should only be a baseband concern.
* However, the baseband can't set up the radio (M0 code), so the apps also
* need to know about the "actual" sample rate so the radio settings can be
* applied correctly. Ideally the baseband would tell the apps what the
* actual sample rate is. Currently the apps are telling the baseband and
* that feels like a separation of concerns problem. */
/* HackRF suggests a minimum sample rate of 2M so a oversample rate is applied
* to the sample rate (pre-scale) to get the sample rate closer to that target.
* The baseband needs to know how to correctly decimate (or interpolate) so
* the set of allowed scalars is fixed (See OversampleRate enum).
* In testing, a minimum rate of 400kHz seems to the functional minimum.
*/
/* Gets the oversample rate for a given sample rate.
* The oversample rate is used to increase the sample rate to improve SNR and quality.
* This is also used as the interpolation rate when replaying captures. */
inline OversampleRate get_oversample_rate(uint32_t sample_rate) {
if (sample_rate < 25'000) return OversampleRate::x32;
if (sample_rate < 50'000) return OversampleRate::x16;
return OversampleRate::x8;
}
/* Gets the actual sample rate for a given sample rate.
* This is the rate with the correct oversampling rate applied. */
inline uint32_t get_actual_sample_rate(uint32_t sample_rate) {
return sample_rate * toUType(get_oversample_rate(sample_rate));
}
#endif /*__OVERSAMPLE_H__*/