#pragma once #include "../taps/root_raised_cosine.h" #include "../filter/fir.h" #include "../loop/fast_agc.h" #include "../loop/costas.h" #include "../clock_recovery/mm.h" namespace dsp::demod { template class PSK : public Processor { using base_type = Processor; public: PSK() {} PSK(stream* in, double symbolrate, double samplerate, int rrcTapCount, double rrcBeta, double agcRate, double costasBandwidth, double omegaGain, double muGain, double omegaRelLimit = 0.01) { init(in, symbolrate, samplerate, rrcTapCount, rrcBeta, agcRate, costasBandwidth, omegaGain, muGain); } ~PSK() { if (!base_type::_block_init) { return; } base_type::stop(); taps::free(rrcTaps); } void init(stream* in, double symbolrate, double samplerate, int rrcTapCount, double rrcBeta, double agcRate, double costasBandwidth, double omegaGain, double muGain, double omegaRelLimit = 0.01) { _symbolrate = symbolrate; _samplerate = samplerate; _rrcTapCount = rrcTapCount; _rrcBeta = rrcBeta; rrcTaps = taps::rootRaisedCosine(_rrcTapCount, _rrcBeta, _symbolrate, _samplerate); rrc.init(NULL, rrcTaps); agc.init(NULL, 1.0, 10e6, agcRate); costas.init(NULL, costasBandwidth); recov.init(NULL, _samplerate / _symbolrate, omegaGain, muGain, omegaRelLimit); rrc.out.free(); agc.out.free(); costas.out.free(); recov.out.free(); base_type::init(in); } void setSymbolrate(double symbolrate) { assert(base_type::_block_init); std::lock_guard lck(base_type::ctrlMtx); base_type::tempStop(); _symbolrate = symbolrate; taps::free(rrcTaps); rrcTaps = taps::rootRaisedCosine(_rrcTapCount, _rrcBeta, _symbolrate, _samplerate); rrc.setTaps(rrcTaps); recov.setOmega(_samplerate / _symbolrate); base_type::tempStart(); } void setSamplerate(double samplerate) { assert(base_type::_block_init); std::lock_guard lck(base_type::ctrlMtx); base_type::tempStop(); _samplerate = samplerate; taps::free(rrcTaps); rrcTaps = taps::rootRaisedCosine(_rrcTapCount, _rrcBeta, _symbolrate, _samplerate); rrc.setTaps(rrcTaps); recov.setOmega(_samplerate / _symbolrate); base_type::tempStart(); } void setRRCParams(int rrcTapCount, double rrcBeta) { assert(base_type::_block_init); std::lock_guard lck(base_type::ctrlMtx); base_type::tempStop(); _rrcTapCount = rrcTapCount; _rrcBeta = rrcBeta; taps::free(rrcTaps); rrcTaps = taps::rootRaisedCosine(_rrcTapCount, _rrcBeta, _symbolrate, _samplerate); rrc.setTaps(rrcTaps); base_type::tempStart(); } void setRRCTapCount(int rrcTapCount) { setRRCParams(rrcTapCount, _rrcBeta); } void setRRCBeta(int rrcBeta) { setRRCParams(_rrcTapCount, rrcBeta); } void setAGCRate(double agcRate) { assert(base_type::_block_init); std::lock_guard lck(base_type::ctrlMtx); agc.setRate(agcRate); } void setCostasBandwidth(double bandwidth) { assert(base_type::_block_init); std::lock_guard lck(base_type::ctrlMtx); costas.setBandwidth(bandwidth); } void setMMParams(double omegaGain, double muGain, double omegaRelLimit = 0.01) { assert(base_type::_block_init); std::lock_guard lck(base_type::ctrlMtx); recov.setOmegaGain(omegaGain); recov.setMuGain(muGain); recov.setOmegaRelLimit(omegaRelLimit); } void setOmegaGain(double omegaGain) { assert(base_type::_block_init); std::lock_guard lck(base_type::ctrlMtx); recov.setOmegaGain(omegaGain); } void setMuGain(double muGain) { assert(base_type::_block_init); std::lock_guard lck(base_type::ctrlMtx); recov.setMuGain(muGain); } void setOmegaRelLimit(double omegaRelLimit) { assert(base_type::_block_init); std::lock_guard lck(base_type::ctrlMtx); recov.setOmegaRelLimit(omegaRelLimit); } void reset() { assert(base_type::_block_init); std::lock_guard lck(base_type::ctrlMtx); base_type::tempStop(); rrc.reset(); agc.reset(); costas.reset(); recov.reset(); base_type::tempStart(); } inline int process(int count, const complex_t* in, complex_t* out) { rrc.process(count, in, out); agc.process(count, out, out); costas.process(count, out, out); return recov.process(count, out, out); } int run() { int count = base_type::_in->read(); if (count < 0) { return -1; } int outCount = process(count, base_type::_in->readBuf, base_type::out.writeBuf); // Swap if some data was generated base_type::_in->flush(); if (outCount) { if (!base_type::out.swap(outCount)) { return -1; } } return outCount; } protected: double _symbolrate; double _samplerate; int _rrcTapCount; double _rrcBeta; tap rrcTaps; filter::FIR rrc; loop::FastAGC agc; loop::Costas costas; clock_recovery::MM recov; }; }