From 74fd30f08c5cef621f1795f8a0d035738dd364ee Mon Sep 17 00:00:00 2001 From: AlexandreRouma Date: Sat, 2 Jul 2022 16:53:09 +0200 Subject: [PATCH] Added back the digital demodulators --- .github/workflows/build_all.yml | 6 +- CMakeLists.txt | 4 +- core/src/dsp/clock_recovery/mm.h | 199 ++++++++++++++++++ core/src/dsp/demod/gmsk.h | 162 ++++++++++++++ core/src/dsp/demod/psk.h | 170 +++++++++++++++ core/src/dsp/loop/fast_agc.h | 100 +++++++++ core/src/dsp/loop/phase_control_loop.h | 4 +- core/src/dsp/math/step.h | 12 +- core/src/dsp/routing/doubler.h | 45 ++++ core/src/dsp/taps/root_raised_cosine.h | 2 +- decoder_modules/m17_decoder/src/m17dsp.h | 185 ++++++++-------- decoder_modules/m17_decoder/src/main.cpp | 30 +-- .../meteor_demodulator/src/main.cpp | 26 +-- docker_builds/debian_bullseye/do_build.sh | 2 +- docker_builds/debian_buster/do_build.sh | 2 +- docker_builds/debian_sid/do_build.sh | 2 +- docker_builds/ubuntu_bionic/do_build.sh | 2 +- docker_builds/ubuntu_focal/do_build.sh | 2 +- docker_builds/ubuntu_hirsute/do_build.sh | 2 +- docker_builds/ubuntu_impish/do_build.sh | 2 +- docker_builds/ubuntu_jammy/do_build.sh | 2 +- root/res/bandplans/qo-100.json | 69 ++++++ 22 files changed, 881 insertions(+), 149 deletions(-) create mode 100644 core/src/dsp/clock_recovery/mm.h create mode 100644 core/src/dsp/demod/gmsk.h create mode 100644 core/src/dsp/demod/psk.h create mode 100644 core/src/dsp/loop/fast_agc.h create mode 100644 core/src/dsp/routing/doubler.h create mode 100644 root/res/bandplans/qo-100.json diff --git a/.github/workflows/build_all.yml b/.github/workflows/build_all.yml index d6f6233..1203bca 100644 --- a/.github/workflows/build_all.yml +++ b/.github/workflows/build_all.yml @@ -58,7 +58,7 @@ jobs: - name: Prepare CMake working-directory: ${{runner.workspace}}/build - run: cmake "$Env:GITHUB_WORKSPACE" "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=OFF + run: cmake "$Env:GITHUB_WORKSPACE" "-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON - name: Build working-directory: ${{runner.workspace}}/build @@ -106,7 +106,7 @@ jobs: - name: Prepare CMake working-directory: ${{runner.workspace}}/build - run: cmake $GITHUB_WORKSPACE -DOPT_BUILD_PLUTOSDR_SOURCE=OFF -DOPT_BUILD_SOAPY_SOURCE=OFF -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_AUDIO_SINK=OFF -DOPT_BUILD_PORTAUDIO_SINK=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=OFF -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release + run: cmake $GITHUB_WORKSPACE -DOPT_BUILD_PLUTOSDR_SOURCE=OFF -DOPT_BUILD_SOAPY_SOURCE=OFF -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_AUDIO_SINK=OFF -DOPT_BUILD_PORTAUDIO_SINK=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release - name: Build working-directory: ${{runner.workspace}}/build @@ -309,7 +309,7 @@ jobs: - name: Prepare CMake working-directory: ${{runner.workspace}}/build - run: cmake $GITHUB_WORKSPACE -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=OFF + run: cmake $GITHUB_WORKSPACE -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON - name: Build working-directory: ${{runner.workspace}}/build diff --git a/CMakeLists.txt b/CMakeLists.txt index 5bea7e9..1f05a9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,8 +51,8 @@ option(OPT_BUILD_NEW_PORTAUDIO_SINK "Build the new PortAudio Sink Module (Depend # Decoders option(OPT_BUILD_FALCON9_DECODER "Build the falcon9 live decoder (Dependencies: ffplay)" OFF) option(OPT_BUILD_KG_SSTV_DECODER "Build the M17 decoder module (no dependencies required)" OFF) -option(OPT_BUILD_M17_DECODER "Build the M17 decoder module (no dependencies required)" OFF) -option(OPT_BUILD_METEOR_DEMODULATOR "Build the meteor demodulator module (no dependencies required)" OFF) +option(OPT_BUILD_M17_DECODER "Build the M17 decoder module (Dependencies: codec2)" OFF) +option(OPT_BUILD_METEOR_DEMODULATOR "Build the meteor demodulator module (no dependencies required)" ON) option(OPT_BUILD_RADIO "Main audio modulation decoder (AM, FM, SSB, etc...)" ON) option(OPT_BUILD_WEATHER_SAT_DECODER "Build the HRPT decoder module (no dependencies required)" OFF) diff --git a/core/src/dsp/clock_recovery/mm.h b/core/src/dsp/clock_recovery/mm.h new file mode 100644 index 0000000..9c84a8c --- /dev/null +++ b/core/src/dsp/clock_recovery/mm.h @@ -0,0 +1,199 @@ +#pragma once +#include "../processor.h" +#include "../loop/phase_control_loop.h" +#include "../taps/windowed_sinc.h" +#include "../multirate/polyphase_bank.h" +#include "../math/step.h" + +namespace dsp::clock_recovery { + template + class MM : public Processor { + using base_type = Processor ; + public: + MM() {} + + MM(stream* in, double omega, double omegaGain, double muGain, double omegaRelLimit, int interpPhaseCount = 128, int interpTapCount = 8) { init(in, omega, omegaGain, muGain, omegaRelLimit, interpPhaseCount, interpTapCount); } + + ~MM() { + if (!base_type::_block_init) { return; } + base_type::stop(); + dsp::multirate::freePolyphaseBank(interpBank); + buffer::free(buffer); + } + + void init(stream* in, double omega, double omegaGain, double muGain, double omegaRelLimit, int interpPhaseCount = 128, int interpTapCount = 8) { + _omega = omega; + _omegaGain = omegaGain; + _muGain = muGain; + _omegaRelLimit = omegaRelLimit; + _interpPhaseCount = interpPhaseCount; + _interpTapCount = interpTapCount; + + pcl.init(_muGain, _omegaGain, 0.0, 0.0, 1.0, _omega, _omega * (1.0 - omegaRelLimit), _omega * (1.0 + omegaRelLimit)); + generateInterpTaps(); + buffer = buffer::alloc(STREAM_BUFFER_SIZE + _interpTapCount); + bufStart = &buffer[_interpTapCount - 1]; + + base_type::init(in); + } + + void setOmega(double omega) { + assert(base_type::_block_init); + std::lock_guard lck(base_type::ctrlMtx); + base_type::tempStop(); + _omega = omega; + offset = 0; + pcl.phase = 0.0f; + pcl.freq = _omega; + pcl.setFreqLimits(_omega * (1.0 - _omegaRelLimit), _omega * (1.0 + _omegaRelLimit)); + base_type::tempStart(); + } + + void setOmegaGain(double omegaGain) { + assert(base_type::_block_init); + std::lock_guard lck(base_type::ctrlMtx); + _omegaGain = omegaGain; + pcl.setCoefficients(_muGain, _omegaGain); + } + + void setMuGain(double muGain) { + assert(base_type::_block_init); + std::lock_guard lck(base_type::ctrlMtx); + _muGain = muGain; + pcl.setCoefficients(_muGain, _omegaGain); + } + + void setOmegaRelLimit(double omegaRelLimit) { + assert(base_type::_block_init); + std::lock_guard lck(base_type::ctrlMtx); + _omegaRelLimit = omegaRelLimit; + pcl.setFreqLimits(_omega * (1.0 - _omegaRelLimit), _omega * (1.0 + _omegaRelLimit)); + } + + void setInterpParams(int interpPhaseCount, int interpTapCount) { + assert(base_type::_block_init); + std::lock_guard lck(base_type::ctrlMtx); + base_type::tempStop(); + _interpPhaseCount = interpPhaseCount; + _interpTapCount = interpTapCount; + dsp::multirate::freePolyphaseBank(interpBank); + buffer::free(buffer); + generateInterpTaps(); + buffer = buffer::alloc(STREAM_BUFFER_SIZE + _interpTapCount); + bufStart = &buffer[_interpTapCount - 1]; + base_type::tempStart(); + } + + void reset() { + assert(base_type::_block_init); + std::lock_guard lck(base_type::ctrlMtx); + base_type::tempStop(); + offset = 0; + pcl.phase = 0.0f; + pcl.freq = _omega; + lastOut = 0.0f; + _p_0T = { 0.0f, 0.0f }; _p_1T = { 0.0f, 0.0f }; _p_2T = { 0.0f, 0.0f }; + _c_0T = { 0.0f, 0.0f }; _c_1T = { 0.0f, 0.0f }; _c_2T = { 0.0f, 0.0f }; + base_type::tempStart(); + } + + inline int process(int count, const T* in, T* out) { + // Copy data to work buffer + memcpy(bufStart, in, count * sizeof(T)); + + // Process all samples + int outCount = 0; + while (offset < count) { + float error; + T outVal; + + // Calculate new output value + int phase = std::clamp(floorf(pcl.phase * (float)_interpPhaseCount), 0, _interpPhaseCount - 1); + if constexpr (std::is_same_v) { + volk_32f_x2_dot_prod_32f(&outVal, &buffer[offset], interpBank.phases[phase], _interpTapCount); + } + if constexpr (std::is_same_v) { + volk_32fc_32f_dot_prod_32fc((lv_32fc_t*)&outVal, (lv_32fc_t*)&buffer[offset], interpBank.phases[phase], _interpTapCount); + } + out[outCount++] = outVal; + + // Calculate symbol phase error + if constexpr (std::is_same_v) { + error = (math::step(lastOut) * outVal) - (lastOut * math::step(outVal)); + lastOut = outVal; + } + if constexpr (std::is_same_v) { + // Propagate delay + _p_2T = _p_1T; + _p_1T = _p_0T; + _c_2T = _c_1T; + _c_1T = _c_0T; + + // Update the T0 values + _p_0T = outVal; + _c_0T = math::step(outVal); + + // Error + error = (((_p_0T - _p_2T) * _c_1T.conj()) - ((_c_0T - _c_2T) * _p_1T.conj())).re; + } + + // Clamp symbol phase error + if (error > 1.0f) { error = 1.0f; } + if (error < -1.0f) { error = -1.0f; } + + // Advance symbol offset and phase + pcl.advance(error); + float delta = floorf(pcl.phase); + offset += delta; + pcl.phase -= delta; + } + offset -= count; + + // Update delay buffer + memmove(buffer, &buffer[count], (_interpTapCount - 1) * sizeof(T)); + + return outCount; + } + + 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: + void generateInterpTaps() { + double bw = 0.5 / (double)_interpPhaseCount; + dsp::tap lp = dsp::taps::windowedSinc(_interpPhaseCount * _interpTapCount, dsp::math::freqToOmega(bw, 1.0), dsp::window::nuttall, _interpPhaseCount); + interpBank = dsp::multirate::buildPolyphaseBank(_interpPhaseCount, lp); + taps::free(lp); + } + + dsp::multirate::PolyphaseBank interpBank; + loop::PhaseControlLoop pcl; + + double _omega; + double _omegaGain; + double _muGain; + double _omegaRelLimit; + int _interpPhaseCount; + int _interpTapCount; + + // Previous output storage + float lastOut = 0.0f; + complex_t _p_0T = { 0.0f, 0.0f }, _p_1T = { 0.0f, 0.0f }, _p_2T = { 0.0f, 0.0f }; + complex_t _c_0T = { 0.0f, 0.0f }, _c_1T = { 0.0f, 0.0f }, _c_2T = { 0.0f, 0.0f }; + + int offset = 0; + T* buffer; + T* bufStart; + }; +} \ No newline at end of file diff --git a/core/src/dsp/demod/gmsk.h b/core/src/dsp/demod/gmsk.h new file mode 100644 index 0000000..b153394 --- /dev/null +++ b/core/src/dsp/demod/gmsk.h @@ -0,0 +1,162 @@ +#pragma once +#include "quadrature.h" +#include "../taps/root_raised_cosine.h" +#include "../filter/fir.h" +#include "../clock_recovery/mm.h" + +namespace dsp::demod { + // Note: I don't like how this demodulator reuses 90% of the code from the PSK demod. Same will be for the PM demod... + class GMSK : public Processor { + using base_type = Processor; + public: + GMSK() {} + + GMSK(stream* in, double symbolrate, double samplerate, double deviation, int rrcTapCount, double rrcBeta, double omegaGain, double muGain, double omegaRelLimit = 0.01) { + init(in, symbolrate, samplerate, deviation, rrcTapCount, rrcBeta, omegaGain, muGain); + } + + ~GMSK() { + if (!base_type::_block_init) { return; } + base_type::stop(); + taps::free(rrcTaps); + } + + void init(stream* in, double symbolrate, double samplerate, double deviation, int rrcTapCount, double rrcBeta, double omegaGain, double muGain, double omegaRelLimit = 0.01) { + _symbolrate = symbolrate; + _samplerate = samplerate; + _deviation = deviation; + _rrcTapCount = rrcTapCount; + _rrcBeta = rrcBeta; + + demod.init(NULL, _deviation, _samplerate); + rrcTaps = taps::rootRaisedCosine(_rrcTapCount, _rrcBeta, _symbolrate, _samplerate); + rrc.init(NULL, rrcTaps); + recov.init(NULL, _samplerate / _symbolrate, omegaGain, muGain, omegaRelLimit); + + demod.out.free(); + rrc.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; + demod.setDeviation(_deviation, _samplerate); + taps::free(rrcTaps); + rrcTaps = taps::rootRaisedCosine(_rrcTapCount, _rrcBeta, _symbolrate, _samplerate); + rrc.setTaps(rrcTaps); + recov.setOmega(_samplerate / _symbolrate); + base_type::tempStart(); + } + + void setDeviation(double deviation) { + assert(base_type::_block_init); + std::lock_guard lck(base_type::ctrlMtx); + _deviation = deviation; + demod.setDeviation(_deviation, _samplerate); + } + + 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); + base_type::tempStart(); + } + + void setRRCTapCount(int rrcTapCount) { + setRRCParams(rrcTapCount, _rrcBeta); + } + + void setRRCBeta(int rrcBeta) { + setRRCParams(_rrcTapCount, rrcBeta); + } + + 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(); + demod.reset(); + rrc.reset(); + recov.reset(); + base_type::tempStart(); + } + + inline int process(int count, complex_t* in, float* out) { + demod.process(count, in, out); + rrc.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; + double _deviation; + int _rrcTapCount; + double _rrcBeta; + + Quadrature demod; + tap rrcTaps; + filter::FIR rrc; + clock_recovery::MM recov; + }; +} \ No newline at end of file diff --git a/core/src/dsp/demod/psk.h b/core/src/dsp/demod/psk.h new file mode 100644 index 0000000..280a84f --- /dev/null +++ b/core/src/dsp/demod/psk.h @@ -0,0 +1,170 @@ +#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); + 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; + }; +} \ No newline at end of file diff --git a/core/src/dsp/loop/fast_agc.h b/core/src/dsp/loop/fast_agc.h new file mode 100644 index 0000000..db6ad71 --- /dev/null +++ b/core/src/dsp/loop/fast_agc.h @@ -0,0 +1,100 @@ +#pragma once +#include "../processor.h" + +namespace dsp::loop { + template + class FastAGC : public Processor { + using base_type = Processor; + public: + FastAGC() {} + + FastAGC(stream* in, double setPoint, double maxGain, double rate, double initGain = 1.0) { init(in, setPoint, maxGain, rate, initGain); } + + void init(stream* in, double setPoint, double maxGain, double rate, double initGain = 1.0) { + _setPoint = setPoint; + _maxGain = maxGain; + _rate = rate; + _initGain = initGain; + + _gain = _initGain; + + base_type::init(in); + } + + void setSetPoint(double setPoint) { + assert(base_type::_block_init); + std::lock_guard lck(base_type::ctrlMtx); + _setPoint = setPoint; + } + + void setMaxGain(double maxGain) { + assert(base_type::_block_init); + std::lock_guard lck(base_type::ctrlMtx); + _maxGain = maxGain; + } + + void setRate(double rate) { + assert(base_type::_block_init); + std::lock_guard lck(base_type::ctrlMtx); + _rate = rate; + } + + void setInitGain(double initGain) { + assert(base_type::_block_init); + std::lock_guard lck(base_type::ctrlMtx); + _initGain = initGain; + } + + void setGain(double gain) { + assert(base_type::_block_init); + std::lock_guard lck(base_type::ctrlMtx); + _gain = gain; + } + + void reset() { + assert(base_type::_block_init); + std::lock_guard lck(base_type::ctrlMtx); + _gain = _initGain; + } + + inline int process(int count, T* in, T* out) { + for (int i = 0; i < count; i++) { + // Output scaled input + out[i] = in[i] * _gain; + + // Calculate output amplitude + float amp; + if constexpr (std::is_same_v) { + amp = fabsf(out[i]); + } + if constexpr (std::is_same_v) { + amp = out[i].amplitude(); + } + + // Update and clamp gain + _gain += (_setPoint - amp) * _rate; + if (_gain > _maxGain) { _gain = _maxGain; } + } + 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: + float _gain; + float _setPoint; + float _rate; + float _maxGain; + float _initGain; + + }; +} \ No newline at end of file diff --git a/core/src/dsp/loop/phase_control_loop.h b/core/src/dsp/loop/phase_control_loop.h index 8099672..f5999bb 100644 --- a/core/src/dsp/loop/phase_control_loop.h +++ b/core/src/dsp/loop/phase_control_loop.h @@ -4,7 +4,7 @@ #include "../types.h" namespace dsp::loop { - template + template class PhaseControlLoop { public: PhaseControlLoop() {} @@ -62,7 +62,7 @@ namespace dsp::loop { // Increment and clamp phase phase += freq + (_alpha * error); - clampPhase(); + if constexpr(CLAMP_PHASE) { clampPhase(); } } T freq; diff --git a/core/src/dsp/math/step.h b/core/src/dsp/math/step.h index 961308f..5f17572 100644 --- a/core/src/dsp/math/step.h +++ b/core/src/dsp/math/step.h @@ -1,8 +1,18 @@ #pragma once +#include "../types.h" namespace dsp::math { template inline T step(T x) { - return (x > 0.0) ? 1.0 : -1.0; + // TODO: Switch to cursed bit manipulation instead! + if constexpr (std::is_same_v) { + return { (x.re > 0.0f) ? 1.0f : -1.0f, (x.im > 0.0f) ? 1.0f : -1.0f }; + } + else if constexpr (std::is_same_v) { + return { (x.l > 0.0f) ? 1.0f : -1.0f, (x.r > 0.0f) ? 1.0f : -1.0f }; + } + else { + return (x > 0.0) ? 1.0 : -1.0; + } } } \ No newline at end of file diff --git a/core/src/dsp/routing/doubler.h b/core/src/dsp/routing/doubler.h new file mode 100644 index 0000000..9852282 --- /dev/null +++ b/core/src/dsp/routing/doubler.h @@ -0,0 +1,45 @@ +#pragma once +#include "../sink.h" + +namespace dsp::routing { + template + class Doubler : public Sink { + using base_type = Sink; + public: + Doubler() {} + + Doubler(stream* in) { init(in); } + + void init(stream* in) { + base_type::registerOutput(&outA); + base_type::registerOutput(&outB); + base_type::init(in); + } + + int run() { + int count = base_type::_in->read(); + if (count < 0) { return -1; } + + memcpy(outA.writeBuf, base_type::_in->readBuf, count * sizeof(T)); + memcpy(outB.writeBuf, base_type::_in->readBuf, count * sizeof(T)); + if (!outA.swap(count)) { + base_type::_in->flush(); + return -1; + } + if (!outB.swap(count)) { + base_type::_in->flush(); + return -1; + } + + base_type::_in->flush(); + + return count; + } + + stream outA; + stream outB; + + protected: + + }; +} \ No newline at end of file diff --git a/core/src/dsp/taps/root_raised_cosine.h b/core/src/dsp/taps/root_raised_cosine.h index d137ff6..86f775e 100644 --- a/core/src/dsp/taps/root_raised_cosine.h +++ b/core/src/dsp/taps/root_raised_cosine.h @@ -3,7 +3,7 @@ #include "tap.h" #include "../math/constants.h" -namespace dsp { +namespace dsp::taps { template inline tap rootRaisedCosine(int count, double beta, double Ts) { // Allocate taps diff --git a/decoder_modules/m17_decoder/src/m17dsp.h b/decoder_modules/m17_decoder/src/m17dsp.h index 5429905..577650e 100644 --- a/decoder_modules/m17_decoder/src/m17dsp.h +++ b/decoder_modules/m17_decoder/src/m17dsp.h @@ -1,8 +1,11 @@ #pragma once #include +#include +#include +#include +#include #include #include -#include #include #include @@ -86,7 +89,7 @@ const uint8_t M17_PUNCTURING_P2[12] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 }; static const correct_convolutional_polynomial_t correct_conv_m17_polynomial[] = { 0b11001, 0b10111 }; namespace dsp { - class M17Slice4FSK : public generic_block { + class M17Slice4FSK : public block { public: M17Slice4FSK() {} @@ -94,19 +97,19 @@ namespace dsp { void init(stream* in) { _in = in; - generic_block::registerInput(_in); - generic_block::registerOutput(&out); - generic_block::_block_init = true; + block::registerInput(_in); + block::registerOutput(&out); + block::_block_init = true; } void setInput(stream* in) { - assert(generic_block::_block_init); - std::lock_guard lck(generic_block::ctrlMtx); - generic_block::tempStop(); - generic_block::unregisterInput(_in); + assert(block::_block_init); + std::lock_guard lck(block::ctrlMtx); + block::tempStop(); + block::unregisterInput(_in); _in = in; - generic_block::registerInput(_in); - generic_block::tempStart(); + block::registerInput(_in); + block::tempStart(); } int run() { @@ -132,15 +135,15 @@ namespace dsp { stream* _in; }; - class M17FrameDemux : public generic_block { + class M17FrameDemux : public block { public: M17FrameDemux() {} M17FrameDemux(stream* in) { init(in); } ~M17FrameDemux() { - if (!generic_block::_block_init) { return; } - generic_block::stop(); + if (!block::_block_init) { return; } + block::stop(); delete[] delay; } @@ -149,22 +152,22 @@ namespace dsp { delay = new uint8_t[STREAM_BUFFER_SIZE]; - generic_block::registerInput(_in); - generic_block::registerOutput(&linkSetupOut); - generic_block::registerOutput(&lichOut); - generic_block::registerOutput(&streamOut); - generic_block::registerOutput(&packetOut); - generic_block::_block_init = true; + block::registerInput(_in); + block::registerOutput(&linkSetupOut); + block::registerOutput(&lichOut); + block::registerOutput(&streamOut); + block::registerOutput(&packetOut); + block::_block_init = true; } void setInput(stream* in) { - assert(generic_block::_block_init); - std::lock_guard lck(generic_block::ctrlMtx); - generic_block::tempStop(); - generic_block::unregisterInput(_in); + assert(block::_block_init); + std::lock_guard lck(block::ctrlMtx); + block::tempStop(); + block::unregisterInput(_in); _in = in; - generic_block::registerInput(_in); - generic_block::tempStart(); + block::registerInput(_in); + block::tempStart(); } int run() { @@ -268,15 +271,15 @@ namespace dsp { int outCount = 0; }; - class M17LSFDecoder : public generic_block { + class M17LSFDecoder : public block { public: M17LSFDecoder() {} M17LSFDecoder(stream* in, void (*handler)(M17LSF& lsf, void* ctx), void* ctx) { init(in, handler, ctx); } ~M17LSFDecoder() { - if (!generic_block::_block_init) { return; } - generic_block::stop(); + if (!block::_block_init) { return; } + block::stop(); correct_convolutional_destroy(conv); } @@ -287,18 +290,18 @@ namespace dsp { conv = correct_convolutional_create(2, 5, correct_conv_m17_polynomial); - generic_block::registerInput(_in); - generic_block::_block_init = true; + block::registerInput(_in); + block::_block_init = true; } void setInput(stream* in) { - assert(generic_block::_block_init); - std::lock_guard lck(generic_block::ctrlMtx); - generic_block::tempStop(); - generic_block::unregisterInput(_in); + assert(block::_block_init); + std::lock_guard lck(block::ctrlMtx); + block::tempStop(); + block::unregisterInput(_in); _in = in; - generic_block::registerInput(_in); - generic_block::tempStart(); + block::registerInput(_in); + block::tempStart(); } int run() { @@ -346,15 +349,15 @@ namespace dsp { correct_convolutional* conv; }; - class M17PayloadFEC : public generic_block { + class M17PayloadFEC : public block { public: M17PayloadFEC() {} M17PayloadFEC(stream* in) { init(in); } ~M17PayloadFEC() { - if (!generic_block::_block_init) { return; } - generic_block::stop(); + if (!block::_block_init) { return; } + block::stop(); correct_convolutional_destroy(conv); } @@ -363,19 +366,19 @@ namespace dsp { conv = correct_convolutional_create(2, 5, correct_conv_m17_polynomial); - generic_block::registerInput(_in); - generic_block::registerOutput(&out); - generic_block::_block_init = true; + block::registerInput(_in); + block::registerOutput(&out); + block::_block_init = true; } void setInput(stream* in) { - assert(generic_block::_block_init); - std::lock_guard lck(generic_block::ctrlMtx); - generic_block::tempStop(); - generic_block::unregisterInput(_in); + assert(block::_block_init); + std::lock_guard lck(block::ctrlMtx); + block::tempStop(); + block::unregisterInput(_in); _in = in; - generic_block::registerInput(_in); - generic_block::tempStart(); + block::registerInput(_in); + block::tempStart(); } int run() { @@ -419,15 +422,15 @@ namespace dsp { correct_convolutional* conv; }; - class M17Codec2Decode : public generic_block { + class M17Codec2Decode : public block { public: M17Codec2Decode() {} M17Codec2Decode(stream* in) { init(in); } ~M17Codec2Decode() { - if (!generic_block::_block_init) { return; } - generic_block::stop(); + if (!block::_block_init) { return; } + block::stop(); codec2_destroy(codec); delete[] int16Audio; delete[] floatAudio; @@ -442,19 +445,19 @@ namespace dsp { int16Audio = new int16_t[sampsPerC2FrameDouble]; floatAudio = new float[sampsPerC2FrameDouble]; - generic_block::registerInput(_in); - generic_block::registerOutput(&out); - generic_block::_block_init = true; + block::registerInput(_in); + block::registerOutput(&out); + block::_block_init = true; } void setInput(stream* in) { - assert(generic_block::_block_init); - std::lock_guard lck(generic_block::ctrlMtx); - generic_block::tempStop(); - generic_block::unregisterInput(_in); + assert(block::_block_init); + std::lock_guard lck(block::ctrlMtx); + block::tempStop(); + block::unregisterInput(_in); _in = in; - generic_block::registerInput(_in); - generic_block::tempStart(); + block::registerInput(_in); + block::tempStart(); } int run() { @@ -490,7 +493,7 @@ namespace dsp { int sampsPerC2FrameDouble = 0; }; - class M17LICHDecoder : public generic_block { + class M17LICHDecoder : public block { public: M17LICHDecoder() {} @@ -500,18 +503,18 @@ namespace dsp { _in = in; _handler = handler; _ctx = ctx; - generic_block::registerInput(_in); - generic_block::_block_init = true; + block::registerInput(_in); + block::_block_init = true; } void setInput(stream* in) { - assert(generic_block::_block_init); - std::lock_guard lck(generic_block::ctrlMtx); - generic_block::tempStop(); - generic_block::unregisterInput(_in); + assert(block::_block_init); + std::lock_guard lck(block::ctrlMtx); + block::tempStop(); + block::unregisterInput(_in); _in = in; - generic_block::registerInput(_in); - generic_block::tempStart(); + block::registerInput(_in); + block::tempStart(); } int run() { @@ -590,7 +593,7 @@ namespace dsp { int lastId = 0; }; - class M17Decoder : public generic_hier_block { + class M17Decoder : public hier_block { public: M17Decoder() {} @@ -601,11 +604,8 @@ namespace dsp { void init(stream* input, float sampleRate, void (*handler)(M17LSF& lsf, void* ctx), void* ctx) { _sampleRate = sampleRate; - demod.init(input, _sampleRate, M17_DEVIATION); - rrc.init(31, _sampleRate, M17_BAUDRATE, M17_RRC_ALPHA); - fir.init(&demod.out, &rrc); - recov.init(&fir.out, _sampleRate / M17_BAUDRATE, 1e-6f, 0.01f, 0.01f); - doubler.init(&recov.out); + demod.init(input, M17_BAUDRATE, sampleRate, M17_DEVIATION, 31, M17_RRC_ALPHA, 1e-6f, 0.01f, 0.01f); + doubler.init(&demod.out); slice.init(&doubler.outA); demux.init(&slice.out); lsfFEC.init(&demux.linkSetupOut, handler, ctx); @@ -618,24 +618,22 @@ namespace dsp { diagOut = &doubler.outB; out = &decodeAudio.out; - generic_hier_block::registerBlock(&demod); - generic_hier_block::registerBlock(&fir); - generic_hier_block::registerBlock(&recov); - generic_hier_block::registerBlock(&doubler); - generic_hier_block::registerBlock(&slice); - generic_hier_block::registerBlock(&demux); - generic_hier_block::registerBlock(&lsfFEC); - generic_hier_block::registerBlock(&payloadFEC); - generic_hier_block::registerBlock(&decodeLICH); - generic_hier_block::registerBlock(&decodeAudio); + hier_block::registerBlock(&demod); + hier_block::registerBlock(&doubler); + hier_block::registerBlock(&slice); + hier_block::registerBlock(&demux); + hier_block::registerBlock(&lsfFEC); + hier_block::registerBlock(&payloadFEC); + hier_block::registerBlock(&decodeLICH); + hier_block::registerBlock(&decodeAudio); - generic_hier_block::registerBlock(&ns2); + hier_block::registerBlock(&ns2); - generic_hier_block::_block_init = true; + hier_block::_block_init = true; } void setInput(stream* input) { - assert(generic_hier_block::_block_init); + assert(hier_block::_block_init); demod.setInput(input); } @@ -643,11 +641,8 @@ namespace dsp { stream* out = NULL; private: - FloatFMDemod demod; - RRCTaps rrc; - FIR fir; - MMClockRecovery recov; - StreamDoubler doubler; + demod::GMSK demod; + routing::Doubler doubler; M17Slice4FSK slice; M17FrameDemux demux; M17LSFDecoder lsfFEC; @@ -655,7 +650,7 @@ namespace dsp { M17LICHDecoder decodeLICH; M17Codec2Decode decodeAudio; - NullSink ns2; + dsp::sink::Null ns2; float _sampleRate; diff --git a/decoder_modules/m17_decoder/src/main.cpp b/decoder_modules/m17_decoder/src/main.cpp index b02a569..3822445 100644 --- a/decoder_modules/m17_decoder/src/main.cpp +++ b/decoder_modules/m17_decoder/src/main.cpp @@ -6,14 +6,10 @@ #include #include #include -#include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include #include #include #include @@ -61,12 +57,7 @@ public: // Initialize DSP here decoder.init(vfo->output, INPUT_SAMPLE_RATE, lsfHandler, this); - - resampWin.init(4000, 4000, audioSampRate); - resamp.init(decoder.out, &resampWin, 8000, audioSampRate); - resampWin.setSampleRate(8000 * resamp.getInterpolation()); - resamp.updateWindow(&resampWin); - + resamp.init(decoder.out, 8000, audioSampRate); reshape.init(decoder.diagOut, 480, 0); diagHandler.init(&reshape.out, _diagHandler, this); @@ -250,11 +241,8 @@ private: M17DecoderModule* _this = (M17DecoderModule*)ctx; // TODO: If too slow, change all demods here and not when setting _this->audioSampRate = sampleRate; - _this->resampWin.setCutoff(std::min(sampleRate / 2, 4000)); _this->resamp.tempStop(); - _this->resamp.setOutSampleRate(sampleRate); - _this->resampWin.setSampleRate(8000 * _this->resamp.getInterpolation()); - _this->resamp.updateWindow(&_this->resampWin); + _this->resamp.setOutSamplerate(sampleRate); _this->resamp.tempStart(); } @@ -273,11 +261,9 @@ private: dsp::M17Decoder decoder; - dsp::Reshaper reshape; - dsp::HandlerSink diagHandler; - - dsp::filter_window::BlackmanWindow resampWin; - dsp::PolyphaseResampler resamp; + dsp::buffer::Reshaper reshape; + dsp::sink::Handler diagHandler; + dsp::multirate::RationalResampler resamp; ImGui::SymbolDiagram diag; diff --git a/decoder_modules/meteor_demodulator/src/main.cpp b/decoder_modules/meteor_demodulator/src/main.cpp index 35c4777..9002c28 100644 --- a/decoder_modules/meteor_demodulator/src/main.cpp +++ b/decoder_modules/meteor_demodulator/src/main.cpp @@ -6,14 +6,10 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include @@ -60,8 +56,8 @@ public: config.release(created); vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 150000, INPUT_SAMPLE_RATE, 150000, 150000, true); - demod.init(vfo->output, INPUT_SAMPLE_RATE, 72000.0f, 32, 0.6f, 0.1f, 0.005f); - split.init(demod.out); + demod.init(vfo->output, 72000.0f, INPUT_SAMPLE_RATE, 33, 0.6f, 0.1f, 0.005f, (0.01 * 0.01) / 4.0, 0.01); + split.init(&demod.out); split.bindStream(&symSinkStream); split.bindStream(&sinkStream); reshape.init(&symSinkStream, 1024, (72000 / 30) - 1024); @@ -220,14 +216,14 @@ private: // DSP Chain VFOManager::VFO* vfo; - dsp::PSKDemod<4, false> demod; - dsp::Splitter split; + dsp::demod::PSK<4> demod; + dsp::routing::Splitter split; dsp::stream symSinkStream; dsp::stream sinkStream; - dsp::Reshaper reshape; - dsp::HandlerSink symSink; - dsp::HandlerSink sink; + dsp::buffer::Reshaper reshape; + dsp::sink::Handler symSink; + dsp::sink::Handler sink; ImGui::ConstellationDiagram constDiagram; diff --git a/docker_builds/debian_bullseye/do_build.sh b/docker_builds/debian_bullseye/do_build.sh index 224321e..05a0a32 100644 --- a/docker_builds/debian_bullseye/do_build.sh +++ b/docker_builds/debian_bullseye/do_build.sh @@ -18,7 +18,7 @@ cp inc/* /usr/include/ cd SDRPlusPlus mkdir build cd build -cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=OFF +cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON make VERBOSE=1 -j2 cd .. diff --git a/docker_builds/debian_buster/do_build.sh b/docker_builds/debian_buster/do_build.sh index 2367bf9..cbefd63 100644 --- a/docker_builds/debian_buster/do_build.sh +++ b/docker_builds/debian_buster/do_build.sh @@ -18,7 +18,7 @@ cp inc/* /usr/include/ cd SDRPlusPlus mkdir build cd build -cmake .. -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=OFF -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=OFF +cmake .. -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=OFF -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON make VERBOSE=1 -j2 cd .. diff --git a/docker_builds/debian_sid/do_build.sh b/docker_builds/debian_sid/do_build.sh index 224321e..05a0a32 100644 --- a/docker_builds/debian_sid/do_build.sh +++ b/docker_builds/debian_sid/do_build.sh @@ -18,7 +18,7 @@ cp inc/* /usr/include/ cd SDRPlusPlus mkdir build cd build -cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=OFF +cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON make VERBOSE=1 -j2 cd .. diff --git a/docker_builds/ubuntu_bionic/do_build.sh b/docker_builds/ubuntu_bionic/do_build.sh index 3ac017d..92d0a75 100644 --- a/docker_builds/ubuntu_bionic/do_build.sh +++ b/docker_builds/ubuntu_bionic/do_build.sh @@ -47,7 +47,7 @@ echo 'Cflags: -I/usr/include/codec2' >> /usr/share/pkgconfig/codec2.pc cd SDRPlusPlus mkdir build cd build -cmake .. -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=OFF -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_OVERRIDE_STD_FILESYSTEM=ON -DOPT_BUILD_M17_DECODER=OFF +cmake .. -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_BLADERF_SOURCE=OFF -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_OVERRIDE_STD_FILESYSTEM=ON -DOPT_BUILD_M17_DECODER=ON make VERBOSE=1 -j2 # Generate package diff --git a/docker_builds/ubuntu_focal/do_build.sh b/docker_builds/ubuntu_focal/do_build.sh index 224321e..05a0a32 100644 --- a/docker_builds/ubuntu_focal/do_build.sh +++ b/docker_builds/ubuntu_focal/do_build.sh @@ -18,7 +18,7 @@ cp inc/* /usr/include/ cd SDRPlusPlus mkdir build cd build -cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=OFF +cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON make VERBOSE=1 -j2 cd .. diff --git a/docker_builds/ubuntu_hirsute/do_build.sh b/docker_builds/ubuntu_hirsute/do_build.sh index 224321e..05a0a32 100644 --- a/docker_builds/ubuntu_hirsute/do_build.sh +++ b/docker_builds/ubuntu_hirsute/do_build.sh @@ -18,7 +18,7 @@ cp inc/* /usr/include/ cd SDRPlusPlus mkdir build cd build -cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=OFF +cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON make VERBOSE=1 -j2 cd .. diff --git a/docker_builds/ubuntu_impish/do_build.sh b/docker_builds/ubuntu_impish/do_build.sh index 224321e..05a0a32 100644 --- a/docker_builds/ubuntu_impish/do_build.sh +++ b/docker_builds/ubuntu_impish/do_build.sh @@ -18,7 +18,7 @@ cp inc/* /usr/include/ cd SDRPlusPlus mkdir build cd build -cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=OFF +cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON make VERBOSE=1 -j2 cd .. diff --git a/docker_builds/ubuntu_jammy/do_build.sh b/docker_builds/ubuntu_jammy/do_build.sh index 224321e..05a0a32 100644 --- a/docker_builds/ubuntu_jammy/do_build.sh +++ b/docker_builds/ubuntu_jammy/do_build.sh @@ -18,7 +18,7 @@ cp inc/* /usr/include/ cd SDRPlusPlus mkdir build cd build -cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=OFF +cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON make VERBOSE=1 -j2 cd .. diff --git a/root/res/bandplans/qo-100.json b/root/res/bandplans/qo-100.json new file mode 100644 index 0000000..7109be2 --- /dev/null +++ b/root/res/bandplans/qo-100.json @@ -0,0 +1,69 @@ +{ + "name": "QO-100", + "country_name": "Worldwide", + "country_code": "--", + "author_name": "Ryzerth", + "author_url": "https://github.com/AlexandreRouma", + "bands": [ + { + "name": "Beacon", + "type": "broadcast", + "start": 10489500000, + "end": 10489505000 + }, + { + "name": "CW", + "type": "amateur", + "start": 10489505000, + "end": 10489540000 + }, + { + "name": "NB Digi", + "type": "amateur", + "start": 10489540000, + "end": 10489580000 + }, + { + "name": "Digi", + "type": "amateur", + "start": 10489580000, + "end": 10489650000 + }, + { + "name": "SSB", + "type": "amateur", + "start": 10489650000, + "end": 10489745000 + }, + { + "name": "Beacon", + "type": "broadcast", + "start": 10489745000, + "end": 10489755000 + }, + { + "name": "SSB", + "type": "amateur", + "start": 10489755000, + "end": 10489850000 + }, + { + "name": "Emergency", + "type": "amateur", + "start": 10489850000, + "end": 10489870000 + }, + { + "name": "Mixed/Contest", + "type": "amateur", + "start": 10489870000, + "end": 10489990000 + }, + { + "name": "Beacon", + "type": "broadcast", + "start": 10489990000, + "end": 10490000000 + } + ] +} \ No newline at end of file