mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2025-06-25 20:07:51 +02:00
Added M17 decoder module (unfinished)
This commit is contained in:
@ -73,4 +73,74 @@ namespace dsp {
|
||||
|
||||
|
||||
};
|
||||
|
||||
class DCBlocker : public generic_block<DCBlocker> {
|
||||
public:
|
||||
DCBlocker() {}
|
||||
|
||||
DCBlocker(stream<float>* in, float rate) { init(in, rate); }
|
||||
|
||||
void init(stream<float>* in, float rate) {
|
||||
_in = in;
|
||||
correctionRate = rate;
|
||||
offset = 0;
|
||||
generic_block<DCBlocker>::registerInput(_in);
|
||||
generic_block<DCBlocker>::registerOutput(&out);
|
||||
generic_block<DCBlocker>::_block_init = true;
|
||||
}
|
||||
|
||||
void setInput(stream<float>* in) {
|
||||
assert(generic_block<DCBlocker>::_block_init);
|
||||
std::lock_guard<std::mutex> lck(generic_block<DCBlocker>::ctrlMtx);
|
||||
generic_block<DCBlocker>::tempStop();
|
||||
generic_block<DCBlocker>::unregisterInput(_in);
|
||||
_in = in;
|
||||
generic_block<DCBlocker>::registerInput(_in);
|
||||
generic_block<DCBlocker>::tempStart();
|
||||
}
|
||||
|
||||
void setCorrectionRate(float rate) {
|
||||
correctionRate = rate;
|
||||
}
|
||||
|
||||
int run() {
|
||||
int count = _in->read();
|
||||
if (count < 0) { return -1; }
|
||||
|
||||
if (bypass) {
|
||||
memcpy(out.writeBuf, _in->readBuf, count * sizeof(complex_t));
|
||||
|
||||
_in->flush();
|
||||
|
||||
if (!out.swap(count)) { return -1; }
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
out.writeBuf[i] = _in->readBuf[i] - offset;
|
||||
offset = offset + (out.writeBuf[i] * correctionRate);
|
||||
}
|
||||
|
||||
_in->flush();
|
||||
|
||||
if (!out.swap(count)) { return -1; }
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
stream<float> out;
|
||||
|
||||
// TEMPORARY FOR DEBUG PURPOSES
|
||||
bool bypass = false;
|
||||
float offset;
|
||||
|
||||
private:
|
||||
stream<float>* _in;
|
||||
float correctionRate = 0.00001;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
@ -11,6 +11,7 @@
|
||||
#include <dsp/conversion.h>
|
||||
#include <dsp/audio.h>
|
||||
#include <dsp/stereo_fm.h>
|
||||
#include <dsp/correction.h>
|
||||
|
||||
#define FAST_ATAN2_COEF1 FL_M_PI / 4.0f
|
||||
#define FAST_ATAN2_COEF2 3.0f * FAST_ATAN2_COEF1
|
||||
@ -371,11 +372,11 @@ namespace dsp {
|
||||
|
||||
};
|
||||
|
||||
class MSKDemod : public generic_hier_block<MSKDemod> {
|
||||
class FSKDemod : public generic_hier_block<FSKDemod> {
|
||||
public:
|
||||
MSKDemod() {}
|
||||
FSKDemod() {}
|
||||
|
||||
MSKDemod(stream<complex_t>* input, float sampleRate, float deviation, float baudRate, float omegaGain = (0.01*0.01) / 4, float muGain = 0.01f, float omegaRelLimit = 0.005f) {
|
||||
FSKDemod(stream<complex_t>* input, float sampleRate, float deviation, float baudRate, float omegaGain = (0.01*0.01) / 4, float muGain = 0.01f, float omegaRelLimit = 0.005f) {
|
||||
init(input, sampleRate, deviation, baudRate, omegaGain, muGain, omegaRelLimit);
|
||||
}
|
||||
|
||||
@ -391,47 +392,47 @@ namespace dsp {
|
||||
recov.init(&demod.out, _sampleRate / _baudRate, _omegaGain, _muGain, _omegaRelLimit);
|
||||
out = &recov.out;
|
||||
|
||||
generic_hier_block<MSKDemod>::registerBlock(&demod);
|
||||
generic_hier_block<MSKDemod>::registerBlock(&recov);
|
||||
generic_hier_block<MSKDemod>::_block_init = true;
|
||||
generic_hier_block<FSKDemod>::registerBlock(&demod);
|
||||
generic_hier_block<FSKDemod>::registerBlock(&recov);
|
||||
generic_hier_block<FSKDemod>::_block_init = true;
|
||||
}
|
||||
|
||||
void setInput(stream<complex_t>* input) {
|
||||
assert((generic_hier_block<MSKDemod>::_block_init));
|
||||
assert((generic_hier_block<FSKDemod>::_block_init));
|
||||
demod.setInput(input);
|
||||
}
|
||||
|
||||
void setSampleRate(float sampleRate) {
|
||||
assert(generic_hier_block<MSKDemod>::_block_init);
|
||||
generic_hier_block<MSKDemod>::tempStop();
|
||||
assert(generic_hier_block<FSKDemod>::_block_init);
|
||||
generic_hier_block<FSKDemod>::tempStop();
|
||||
_sampleRate = sampleRate;
|
||||
demod.setSampleRate(_sampleRate);
|
||||
recov.setOmega(_sampleRate / _baudRate, _omegaRelLimit);
|
||||
generic_hier_block<MSKDemod>::tempStart();
|
||||
generic_hier_block<FSKDemod>::tempStart();
|
||||
}
|
||||
|
||||
void setDeviation(float deviation) {
|
||||
assert(generic_hier_block<MSKDemod>::_block_init);
|
||||
assert(generic_hier_block<FSKDemod>::_block_init);
|
||||
_deviation = deviation;
|
||||
demod.setDeviation(deviation);
|
||||
}
|
||||
|
||||
void setBaudRate(float baudRate, float omegaRelLimit) {
|
||||
assert(generic_hier_block<MSKDemod>::_block_init);
|
||||
assert(generic_hier_block<FSKDemod>::_block_init);
|
||||
_baudRate = baudRate;
|
||||
_omegaRelLimit = omegaRelLimit;
|
||||
recov.setOmega(_sampleRate / _baudRate, _omegaRelLimit);
|
||||
}
|
||||
|
||||
void setMMGains(float omegaGain, float myGain) {
|
||||
assert(generic_hier_block<MSKDemod>::_block_init);
|
||||
assert(generic_hier_block<FSKDemod>::_block_init);
|
||||
_omegaGain = omegaGain;
|
||||
_muGain = myGain;
|
||||
recov.setGains(_omegaGain, _muGain);
|
||||
}
|
||||
|
||||
void setOmegaRelLimit(float omegaRelLimit) {
|
||||
assert(generic_hier_block<MSKDemod>::_block_init);
|
||||
assert(generic_hier_block<FSKDemod>::_block_init);
|
||||
_omegaRelLimit = omegaRelLimit;
|
||||
recov.setOmegaRelLimit(_omegaRelLimit);
|
||||
}
|
||||
@ -450,6 +451,105 @@ namespace dsp {
|
||||
float _omegaRelLimit;
|
||||
};
|
||||
|
||||
class GFSKDemod : public generic_hier_block<GFSKDemod> {
|
||||
public:
|
||||
GFSKDemod() {}
|
||||
|
||||
GFSKDemod(stream<complex_t>* input, float sampleRate, float deviation, float rrcAlpha, float baudRate, float omegaGain = (0.01*0.01) / 4, float muGain = 0.01f, float omegaRelLimit = 0.005f) {
|
||||
init(input, sampleRate, deviation, rrcAlpha, baudRate, omegaGain, muGain, omegaRelLimit);
|
||||
}
|
||||
|
||||
void init(stream<complex_t>* input, float sampleRate, float deviation, float rrcAlpha, float baudRate, float omegaGain = (0.01*0.01) / 4, float muGain = 0.01f, float omegaRelLimit = 0.005f) {
|
||||
_sampleRate = sampleRate;
|
||||
_deviation = deviation;
|
||||
_rrcAlpha = rrcAlpha;
|
||||
_baudRate = baudRate;
|
||||
_omegaGain = omegaGain;
|
||||
_muGain = muGain;
|
||||
_omegaRelLimit = omegaRelLimit;
|
||||
|
||||
demod.init(input, _sampleRate, _deviation);
|
||||
rrc.init(31, _sampleRate, _baudRate, _rrcAlpha);
|
||||
fir.init(&demod.out, &rrc);
|
||||
recov.init(&fir.out, _sampleRate / _baudRate, _omegaGain, _muGain, _omegaRelLimit);
|
||||
out = &recov.out;
|
||||
|
||||
generic_hier_block<GFSKDemod>::registerBlock(&demod);
|
||||
generic_hier_block<GFSKDemod>::registerBlock(&fir);
|
||||
generic_hier_block<GFSKDemod>::registerBlock(&recov);
|
||||
generic_hier_block<GFSKDemod>::_block_init = true;
|
||||
}
|
||||
|
||||
void setInput(stream<complex_t>* input) {
|
||||
assert((generic_hier_block<GFSKDemod>::_block_init));
|
||||
demod.setInput(input);
|
||||
}
|
||||
|
||||
void setSampleRate(float sampleRate) {
|
||||
assert(generic_hier_block<GFSKDemod>::_block_init);
|
||||
generic_hier_block<GFSKDemod>::tempStop();
|
||||
_sampleRate = sampleRate;
|
||||
demod.setSampleRate(_sampleRate);
|
||||
recov.setOmega(_sampleRate / _baudRate, _omegaRelLimit);
|
||||
rrc.setSampleRate(_sampleRate);
|
||||
fir.updateWindow(&rrc);
|
||||
generic_hier_block<GFSKDemod>::tempStart();
|
||||
}
|
||||
|
||||
void setDeviation(float deviation) {
|
||||
assert(generic_hier_block<GFSKDemod>::_block_init);
|
||||
_deviation = deviation;
|
||||
demod.setDeviation(deviation);
|
||||
}
|
||||
|
||||
void setRRCAlpha(float rrcAlpha) {
|
||||
assert(generic_hier_block<GFSKDemod>::_block_init);
|
||||
_rrcAlpha = rrcAlpha;
|
||||
rrc.setAlpha(_rrcAlpha);
|
||||
fir.updateWindow(&rrc);
|
||||
}
|
||||
|
||||
void setBaudRate(float baudRate, float omegaRelLimit) {
|
||||
assert(generic_hier_block<GFSKDemod>::_block_init);
|
||||
_baudRate = baudRate;
|
||||
_omegaRelLimit = omegaRelLimit;
|
||||
generic_hier_block<GFSKDemod>::tempStop();
|
||||
recov.setOmega(_sampleRate / _baudRate, _omegaRelLimit);
|
||||
rrc.setBaudRate(_baudRate);
|
||||
fir.updateWindow(&rrc);
|
||||
generic_hier_block<GFSKDemod>::tempStart();
|
||||
}
|
||||
|
||||
void setMMGains(float omegaGain, float myGain) {
|
||||
assert(generic_hier_block<GFSKDemod>::_block_init);
|
||||
_omegaGain = omegaGain;
|
||||
_muGain = myGain;
|
||||
recov.setGains(_omegaGain, _muGain);
|
||||
}
|
||||
|
||||
void setOmegaRelLimit(float omegaRelLimit) {
|
||||
assert(generic_hier_block<GFSKDemod>::_block_init);
|
||||
_omegaRelLimit = omegaRelLimit;
|
||||
recov.setOmegaRelLimit(_omegaRelLimit);
|
||||
}
|
||||
|
||||
stream<float>* out = NULL;
|
||||
|
||||
private:
|
||||
FloatFMDemod demod;
|
||||
RRCTaps rrc;
|
||||
FIR<float> fir;
|
||||
MMClockRecovery<float> recov;
|
||||
|
||||
float _sampleRate;
|
||||
float _deviation;
|
||||
float _rrcAlpha;
|
||||
float _baudRate;
|
||||
float _omegaGain;
|
||||
float _muGain;
|
||||
float _omegaRelLimit;
|
||||
};
|
||||
|
||||
template<int ORDER, bool OFFSET>
|
||||
class PSKDemod : public generic_hier_block<PSKDemod<ORDER, OFFSET>> {
|
||||
public:
|
||||
|
@ -65,6 +65,54 @@ namespace dsp {
|
||||
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class StreamDoubler : public generic_block<StreamDoubler<T>> {
|
||||
public:
|
||||
StreamDoubler() {}
|
||||
|
||||
StreamDoubler(stream<T>* in) { init(in); }
|
||||
|
||||
void init(stream<T>* in) {
|
||||
_in = in;
|
||||
generic_block<StreamDoubler>::registerInput(_in);
|
||||
generic_block<StreamDoubler>::registerOutput(&outA);
|
||||
generic_block<StreamDoubler>::registerOutput(&outB);
|
||||
generic_block<StreamDoubler>::_block_init = true;
|
||||
}
|
||||
|
||||
void setInput(stream<T>* in) {
|
||||
assert(generic_block<StreamDoubler>::_block_init);
|
||||
std::lock_guard<std::mutex> lck(generic_block<StreamDoubler>::ctrlMtx);
|
||||
generic_block<StreamDoubler>::tempStop();
|
||||
generic_block<StreamDoubler>::unregisterInput(_in);
|
||||
_in = in;
|
||||
generic_block<StreamDoubler>::registerInput(_in);
|
||||
generic_block<StreamDoubler>::tempStart();
|
||||
}
|
||||
|
||||
stream<T> outA;
|
||||
stream<T> outB;
|
||||
|
||||
private:
|
||||
int run() {
|
||||
int count = _in->read();
|
||||
if (count < 0) { return -1; }
|
||||
|
||||
memcpy(outA.writeBuf, _in->readBuf, count * sizeof(T));
|
||||
memcpy(outB.writeBuf, _in->readBuf, count * sizeof(T));
|
||||
|
||||
_in->flush();
|
||||
|
||||
if (!outA.swap(count)) { return -1; }
|
||||
if (!outB.swap(count)) { return -1; }
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
stream<T>* _in;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// NOTE: I'm not proud of this, it's BAD and just taken from the previous DSP, but it works...
|
||||
template <class T>
|
||||
|
Reference in New Issue
Block a user