even more stuff

This commit is contained in:
AlexandreRouma
2022-06-15 16:08:54 +02:00
parent 343ec6ca1c
commit d1318d3a0f
156 changed files with 24826 additions and 0 deletions

88
core/src/dsp/demod/am.h Normal file
View File

@@ -0,0 +1,88 @@
#pragma once
#include "../processor.h"
#include "../loop/agc.h"
namespace dsp::demod {
class AM : public Processor<dsp::complex_t, float> {
using base_type = Processor<dsp::complex_t, float>;
public:
enum AGCMode {
CARRIER,
AUDIO,
};
AM() {}
AM(stream<complex_t>* in, AGCMode agcMode, double agcRate) { init(in, agcMode, agcRate); }
void init(stream<complex_t>* in, AGCMode agcMode, double agcRate) {
_agcMode = agcMode;
carrierAgc.init(NULL, 1.0, agcRate);
audioAgc.init(NULL, 1.0, agcRate);
base_type::init(in);
}
void setAGCMode(AGCMode agcMode) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
_agcMode = agcMode;
reset();
base_type::tempStart();
}
void setAGCRate(double agcRate) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
carrierAgc.setRate(agcRate);
audioAgc.setRate(agcRate);
}
void reset() {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
carrierAgc.reset();
audioAgc.reset();
base_type::tempStart();
}
int process(int count, complex_t* in, float* out) {
// Apply carrier AGC if needed
if (_agcMode == AGCMode::CARRIER) {
carrierAgc.process(count, in, carrierAgc.out.writeBuf);
in = carrierAgc.out.writeBuf;
}
// Get magnitude of each sample (TODO: use block instead)
volk_32fc_magnitude_32f(out, (lv_32fc_t*)in, count);
// Apply audio AGC if needed
if (_agcMode == AGCMode::AUDIO) {
audioAgc.process(count, out, out);
}
return count;
}
int run() {
int count = base_type::_in->read();
if (count < 0) { return -1; }
process(count, base_type::_in->readBuf, base_type::out.writeBuf);
base_type::_in->flush();
if (!base_type::out.swap(count)) { return -1; }
return count;
}
protected:
AGCMode _agcMode;
loop::AGC<complex_t> carrierAgc;
loop::AGC<float> audioAgc;
};
}

View File

@@ -0,0 +1,156 @@
#pragma once
#include "fm.h"
#include "../taps/band_pass.h"
#include "../filter/fir.h"
#include "../loop/pll.h"
#include "../convert/l_r_to_stereo.h"
#include "../convert/real_to_complex.h"
#include "../convert/complex_to_real.h"
#include "../math/conjugate.h"
#include "../math/delay.h"
#include "../math/multiply.h"
#include "../math/add.h"
#include "../math/subtract.h"
namespace dsp::demod {
class BroadcastFM : public Processor<complex_t, stereo_t> {
using base_type = Processor<complex_t, stereo_t>;
public:
BroadcastFM() {}
BroadcastFM(stream<complex_t>* in, double deviation, double samplerate, bool stereo = true) { init(in, deviation, samplerate, stereo); }
~BroadcastFM() {
if (!base_type::_block_init) { return; }
base_type::stop();
buffer::free(lmr);
buffer::free(l);
buffer::free(r);
}
virtual void init(stream<complex_t>* in, double deviation, double samplerate, bool stereo = true) {
_deviation = deviation;
_samplerate = samplerate;
_stereo = stereo;
demod.init(NULL, _deviation, _samplerate);
pilotFirTaps = taps::bandPass<complex_t>(18750.0, 19250.0, 3000.0, _samplerate);
pilotFir.init(NULL, pilotFirTaps);
rtoc.init(NULL);
pilotPLL.init(NULL, 0.1/*TODO: adapt to samplerate*/, 0.0, math::freqToOmega(19000.0, _samplerate), math::freqToOmega(18750.0, _samplerate), math::freqToOmega(19250.0, _samplerate));
delay.init(NULL, pilotFirTaps.size / 2.0);
lmr = buffer::alloc<float>(STREAM_BUFFER_SIZE);
l = buffer::alloc<float>(STREAM_BUFFER_SIZE);
r = buffer::alloc<float>(STREAM_BUFFER_SIZE);
base_type::init(in);
}
void setDeviation(double deviation) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
_deviation = deviation;
demod.setDeviation(_deviation, _samplerate);
}
void setSamplerate(double samplerate) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
_samplerate = samplerate;
demod.setDeviation(_deviation, _samplerate);
taps::free(pilotFirTaps);
pilotFirTaps = taps::bandPass<complex_t>(18750.0, 19250.0, 3000.0, samplerate);
pilotFir.setTaps(pilotFirTaps);
pilotPLL.setFrequencyLimits(math::freqToOmega(18750.0, _samplerate), math::freqToOmega(19250.0, _samplerate));
pilotPLL.setInitialFreq(math::freqToOmega(19000.0, _samplerate));
delay.setDelay(pilotFirTaps.size / 2);
reset();
base_type::tempStart();
}
void setStereo(bool stereo) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
_stereo = stereo;
reset();
base_type::tempStart();
}
void reset() {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
demod.reset();
pilotFir.reset();
pilotPLL.reset();
delay.reset();
base_type::tempStart();
}
inline int process(int count, complex_t* in, stereo_t* out) {
// Demodulate
demod.process(count, in, demod.out.writeBuf);
if (_stereo) {
// Convert to complex
rtoc.process(count, demod.out.writeBuf, rtoc.out.writeBuf);
// Filter out pilot and run through PLL
pilotFir.process(count, rtoc.out.writeBuf, pilotFir.out.writeBuf);
pilotPLL.process(count, pilotFir.out.writeBuf, pilotPLL.out.writeBuf);
// Conjugate PLL output to down convert the L-R signal
math::Conjugate::process(count, pilotPLL.out.writeBuf, pilotPLL.out.writeBuf);
math::Multiply<dsp::complex_t>::process(count, rtoc.out.writeBuf, pilotPLL.out.writeBuf, rtoc.out.writeBuf);
// Convert output back to real for further processing
convert::ComplexToReal::process(count, rtoc.out.writeBuf, lmr);
// Do L = (L+R) + (L-R), R = (L+R) - (L-R)
math::Add<float>::process(count, demod.out.writeBuf, lmr, l);
math::Subtract<float>::process(count, demod.out.writeBuf, lmr, r);
// Interleave into stereo
convert::LRToStereo::process(count, l, r, out);
}
else {
// Interleave raw MPX to stereo
convert::LRToStereo::process(count, demod.out.writeBuf, demod.out.writeBuf, out);
}
return count;
}
int run() {
int count = base_type::_in->read();
if (count < 0) { return -1; }
process(count, base_type::_in->readBuf, base_type::out.writeBuf);
base_type::_in->flush();
if (!base_type::out.swap(count)) { return -1; }
return count;
}
protected:
double _deviation;
double _samplerate;
bool _stereo;
FM demod;
tap<complex_t> pilotFirTaps;
filter::FIR<complex_t, complex_t> pilotFir;
convert::RealToComplex rtoc;
loop::PLL pilotPLL;
math::Delay<float> delay;
float* lmr;
float* l;
float* r;
};
}

69
core/src/dsp/demod/fm.h Normal file
View File

@@ -0,0 +1,69 @@
#pragma once
#include "../processor.h"
#include "../math/fast_atan2.h"
#include "../math/freq_to_omega.h"
#include "../math/norm_phase_diff.h"
namespace dsp::demod {
class FM : public Processor<complex_t, float> {
using base_type = Processor<complex_t, float>;
public:
FM() {}
FM(stream<complex_t>* in, double deviation) { init(in, deviation); }
FM(stream<complex_t>* in, double deviation, double samplerate) { init(in, deviation, samplerate); }
virtual void init(stream<complex_t>* in, double deviation) {
_invDeviation = 1.0 / deviation;
base_type::init(in);
}
virtual void init(stream<complex_t>* in, double deviation, double samplerate) {
init(in, math::freqToOmega(deviation, samplerate));
}
void setDeviation(double deviation) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
_invDeviation = 1.0 / deviation;
}
void setDeviation(double deviation, double samplerate) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
_invDeviation = 1.0 / math::freqToOmega(deviation, samplerate);
}
inline int process(int count, complex_t* in, float* out) {
for (int i = 0; i < count; i++) {
float cphase = in[i].phase();
out[i] = math::normPhaseDiff(cphase - phase) * _invDeviation;
phase = cphase;
}
return count;
}
void reset() {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
phase = 0.0f;
}
int run() {
int count = base_type::_in->read();
if (count < 0) { return -1; }
process(count, base_type::_in->readBuf, base_type::out.writeBuf);
base_type::_in->flush();
if (!base_type::out.swap(count)) { return -1; }
return count;
}
protected:
float _invDeviation;
float phase = 0.0f;
};
}

133
core/src/dsp/demod/ssb.h Normal file
View File

@@ -0,0 +1,133 @@
#pragma once
#include "../processor.h"
#include "../channel/frequency_xlator.h"
#include "../convert/complex_to_real.h"
#include "../loop/agc.h"
namespace dsp::demod {
class SSB : public Processor<complex_t, float> {
using base_type = Processor<complex_t, float>;
public:
enum Mode {
USB,
LSB,
DSB
};
SSB() {}
/** Calls the init function
*/
SSB(stream<complex_t>* in, Mode mode, double bandwidth, double samplerate, double agcRate) { init(in, mode, bandwidth, samplerate, agcRate); }
/** Initialize the SSB/DSB Demodulator
* \param in Input stream
* \param mode Demodulation mode, can be USB, LSB or DSB
* \param bandwidth Bandwidth needed to shift back the IQ correctly
* \param samplerate Samplerate of the IQ data
* \param agcRate Speed at which the AGC corrects the audio level. This is NOT automatically scaled to the samplerate.
*/
void init(stream<complex_t>* in, Mode mode, double bandwidth, double samplerate, double agcRate) {
_mode = mode;
_bandwidth = bandwidth;
_samplerate = samplerate;
xlator.init(NULL, getTranslation(), _samplerate);
agc.init(NULL, 1.0, agcRate);
base_type::init(in);
}
/** Set demodulation mode
* \param mode Either USB, LSB or DSB
*/
void setMode(Mode mode) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
_mode = mode;
xlator.setOffset(getTranslation(), _samplerate);
base_type::tempStart();
}
/** Set bandwidth
* \param bandwidth Bandwidth in Hz
*/
void setBandwidth(double bandwidth) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
_bandwidth = bandwidth;
xlator.setOffset(getTranslation(), _samplerate);
base_type::tempStart();
}
/** Set samplerate
* \param samplerate Samplerate in Hz
*/
void setSamplerate(double samplerate) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
_samplerate = samplerate;
xlator.setOffset(getTranslation(), _samplerate);
base_type::tempStart();
}
/** Set AGC rate
* \param agcRate AGC rate in units per second
*/
void setAGCRate(double agcRate) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
agc.setRate(agcRate);
}
/** Process data
* \param count Number of samples
* \param in Input buffer
* \param out Output buffer
*/
int process(int count, const complex_t* in, float* out) {
// Move back sideband
xlator.process(count, in, xlator.out.writeBuf);
// Extract the real component
convert::ComplexToReal::process(count, xlator.out.writeBuf, out);
// Apply AGC
agc.process(count, out, out);
return count;
}
int run() {
int count = base_type::_in->read();
if (count < 0) { return -1; }
process(count, base_type::_in->readBuf, base_type::out.writeBuf);
base_type::_in->flush();
if (!base_type::out.swap(count)) { return -1; }
return count;
}
protected:
double getTranslation() {
if (_mode == Mode::USB) {
return _bandwidth / 2.0;
}
else if (_mode == Mode::LSB) {
return -_bandwidth / 2.0;
}
else if (_mode == Mode::DSB) {
return 0.0;
}
}
Mode _mode;
double _bandwidth;
double _samplerate;
channel::FrequencyXlator xlator;
loop::AGC<float> agc;
};
};