From ef42ea01d8e2b85a06ff335506577629e7b3ffc2 Mon Sep 17 00:00:00 2001 From: AlexandreRouma Date: Thu, 1 Feb 2024 00:55:17 +0100 Subject: [PATCH] add flex decoder menu entry and fix pocsag decoding --- decoder_modules/pager_decoder/src/decoder.h | 9 +- decoder_modules/pager_decoder/src/main.cpp | 189 +++++------------- .../pager_decoder/src/pocsag/decoder.h | 83 +++++++- .../pager_decoder/src/pocsag/dsp.h | 2 +- 4 files changed, 141 insertions(+), 142 deletions(-) diff --git a/decoder_modules/pager_decoder/src/decoder.h b/decoder_modules/pager_decoder/src/decoder.h index dd2328e8..b1436431 100644 --- a/decoder_modules/pager_decoder/src/decoder.h +++ b/decoder_modules/pager_decoder/src/decoder.h @@ -1,8 +1,11 @@ #pragma once +#include class Decoder { public: - - virtual void showMenu(); - + virtual ~Decoder() {} + virtual void showMenu() {}; + virtual void setVFO(VFOManager::VFO* vfo) = 0; + virtual void start() = 0; + virtual void stop() = 0; }; \ No newline at end of file diff --git a/decoder_modules/pager_decoder/src/main.cpp b/decoder_modules/pager_decoder/src/main.cpp index 482dca43..aacd76cb 100644 --- a/decoder_modules/pager_decoder/src/main.cpp +++ b/decoder_modules/pager_decoder/src/main.cpp @@ -5,24 +5,11 @@ #include #include #include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include "pocsag/pocsag.h" +#include "decoder.h" +#include "pocsag/decoder.h" +#include "flex/decoder.h" #define CONCAT(a, b) ((std::string(a) + b).c_str()) @@ -34,77 +21,29 @@ SDRPP_MOD_INFO{ /* Max instances */ -1 }; -const char* msgTypes[] = { - "Numeric", - "Unknown (0b01)", - "Unknown (0b10)", - "Alphanumeric", -}; - ConfigManager config; -#define INPUT_SAMPLE_RATE 24000.0 -#define INPUT_BANDWIDTH 12500.0 -#define INPUT_BAUD_RATE 2400.0 - enum Protocol { + PROTOCOL_INVALID = -1, PROTOCOL_POCSAG, PROTOCOL_FLEX }; class PagerDecoderModule : public ModuleManager::Instance { public: - PagerDecoderModule(std::string name) : diag(0.6, 2400) { + PagerDecoderModule(std::string name) { this->name = name; // Define protocols protocols.define("POCSAG", PROTOCOL_POCSAG); protocols.define("FLEX", PROTOCOL_FLEX); - // Load config - config.acquire(); - if (!config.conf.contains(name)) { - config.conf[name]["showLines"] = false; - } - showLines = config.conf[name]["showLines"]; - if (showLines) { - diag.lines.push_back(-1.0); - diag.lines.push_back(-1.0/3.0); - diag.lines.push_back(1.0/3.0); - diag.lines.push_back(1.0); - } - config.release(true); - - // Initialize VFO - vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, INPUT_BANDWIDTH, INPUT_SAMPLE_RATE, INPUT_BANDWIDTH, INPUT_BANDWIDTH, true); + // Initialize VFO with default values + vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 12500, 24000, 12500, 12500, true); vfo->setSnapInterval(1); - // Initialize DSP here (negative dev to invert signal) - demod.init(vfo->output, -4500.0, INPUT_SAMPLE_RATE); - dcBlock.init(&demod.out, 0.001); - float taps[] = { 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f }; - shape = dsp::taps::fromArray(10, taps); - fir.init(&dcBlock.out, shape); - recov.init(&fir.out, INPUT_SAMPLE_RATE/INPUT_BAUD_RATE, 1e5, 0.1, 0.05); - doubler.init(&recov.out); - slicer.init(&doubler.outB); - dataHandler.init(&slicer.out, _dataHandler, this); - reshape.init(&doubler.outA, 2400.0, (INPUT_BAUD_RATE / 30.0) - 2400.0); - diagHandler.init(&reshape.out, _diagHandler, this); - - // Initialize decode - decoder.onMessage.bind(&PagerDecoderModule::messageHandler, this); - - // Start DSP Here - demod.start(); - dcBlock.start(); - fir.start(); - recov.start(); - doubler.start(); - slicer.start(); - dataHandler.start(); - reshape.start(); - diagHandler.start(); + // Select the protocol + selectProtocol(PROTOCOL_POCSAG); gui::menu.registerEntry(name, menuHandler, this, this); } @@ -113,15 +52,8 @@ public: gui::menu.removeEntry(name); // Stop DSP if (enabled) { - demod.stop(); - dcBlock.stop(); - fir.stop(); - recov.stop(); - doubler.stop(); - slicer.stop(); - dataHandler.stop(); - reshape.stop(); - diagHandler.stop(); + decoder->stop(); + decoder.reset(); sigpath::vfoManager.deleteVFO(vfo); } @@ -132,36 +64,17 @@ public: void enable() { double bw = gui::waterfall.getBandwidth(); - vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp(0, -bw / 2.0, bw / 2.0), INPUT_BANDWIDTH, INPUT_SAMPLE_RATE, INPUT_BANDWIDTH, INPUT_BANDWIDTH, true); - vfo->setSnapInterval(250); + vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp(0, -bw / 2.0, bw / 2.0), 12500, 24000, 12500, 12500, true); + vfo->setSnapInterval(1); - // Start DSP - demod.start(); - dcBlock.start(); - fir.start(); - recov.start(); - doubler.start(); - slicer.start(); - dataHandler.start(); - reshape.start(); - diagHandler.start(); + decoder->setVFO(vfo); + decoder->start(); enabled = true; } void disable() { - demod.stop(); - dcBlock.stop(); - fir.stop(); - recov.stop(); - doubler.stop(); - slicer.stop(); - dataHandler.stop(); - reshape.stop(); - diagHandler.stop(); - reshape.stop(); - diagHandler.stop(); - + decoder->stop(); sigpath::vfoManager.deleteVFO(vfo); enabled = false; } @@ -170,6 +83,36 @@ public: return enabled; } + void selectProtocol(Protocol newProto) { + // Cannot change while disabled + if (!enabled) { return; } + + // If the protocol hasn't changed, no need to do anything + if (newProto == proto) { return; } + + // Delete current decoder + decoder.reset(); + + // Create a new decoder + switch (newProto) { + case PROTOCOL_POCSAG: + decoder = std::make_unique(name, vfo); + break; + case PROTOCOL_FLEX: + decoder = std::make_unique(name, vfo); + break; + default: + flog::error("Tried to select unknown pager protocol"); + return; + } + + // Start the new decoder + decoder->start(); + + // Save selected protocol + proto = newProto; + } + private: static void menuHandler(void* ctx) { PagerDecoderModule* _this = (PagerDecoderModule*)ctx; @@ -181,54 +124,28 @@ private: ImGui::LeftLabel("Protocol"); ImGui::FillWidth(); if (ImGui::Combo(("##pager_decoder_proto_" + _this->name).c_str(), &_this->protoId, _this->protocols.txt)) { - // TODO + _this->selectProtocol(_this->protocols.value(_this->protoId)); } - ImGui::SetNextItemWidth(menuWidth); - _this->diag.draw(); + if (_this->decoder) { _this->decoder->showMenu(); } + + ImGui::Button(("Record##pager_decoder_show_" + _this->name).c_str(), ImVec2(menuWidth, 0)); + ImGui::Button(("Show Messages##pager_decoder_show_" + _this->name).c_str(), ImVec2(menuWidth, 0)); if (!_this->enabled) { style::endDisabled(); } } - static void _dataHandler(uint8_t* data, int count, void* ctx) { - PagerDecoderModule* _this = (PagerDecoderModule*)ctx; - _this->decoder.process(data, count); - } - - static void _diagHandler(float* data, int count, void* ctx) { - PagerDecoderModule* _this = (PagerDecoderModule*)ctx; - float* buf = _this->diag.acquireBuffer(); - memcpy(buf, data, count * sizeof(float)); - _this->diag.releaseBuffer(); - } - - void messageHandler(pocsag::Address addr, pocsag::MessageType type, const std::string& msg) { - flog::debug("[{}]: '{}'", (uint32_t)addr, msg); - } - std::string name; bool enabled = true; + Protocol proto = PROTOCOL_INVALID; int protoId = 0; OptionList protocols; - pocsag::Decoder decoder; - // DSP Chain VFOManager::VFO* vfo; - dsp::demod::Quadrature demod; - dsp::correction::DCBlocker dcBlock; - dsp::tap shape; - dsp::filter::FIR fir; - dsp::clock_recovery::MM recov; - dsp::routing::Doubler doubler; - dsp::digital::BinarySlicer slicer; - dsp::buffer::Reshaper reshape; - dsp::sink::Handler dataHandler; - dsp::sink::Handler diagHandler; - - ImGui::SymbolDiagram diag; + std::unique_ptr decoder; bool showLines = false; }; diff --git a/decoder_modules/pager_decoder/src/pocsag/decoder.h b/decoder_modules/pager_decoder/src/pocsag/decoder.h index 93a03844..54923755 100644 --- a/decoder_modules/pager_decoder/src/pocsag/decoder.h +++ b/decoder_modules/pager_decoder/src/pocsag/decoder.h @@ -1,28 +1,107 @@ #pragma once #include "../decoder.h" +#include #include #include #include +#include +#include "dsp.h" +#include "pocsag.h" + +const char* msgTypes[] = { + "Numeric", + "Unknown (0b01)", + "Unknown (0b10)", + "Alphanumeric", +}; class POCSAGDecoder : public Decoder { public: - POCSAGDecoder() : diag(0.6, 2400) { + POCSAGDecoder(const std::string& name, VFOManager::VFO* vfo) : diag(0.6, 2400) { + this->name = name; + this->vfo = vfo; + // Define baudrate options baudrates.define(512, "512 Baud", 512); baudrates.define(1200, "1200 Baud", 1200); baudrates.define(2400, "2400 Baud", 2400); + + // Init DSP + vfo->setBandwidthLimits(12500, 12500, true); + vfo->setSampleRate(24000, 12500); + dsp.init(vfo->output, 24000, 2400); + reshape.init(&dsp.soft, 2400.0, (2400 / 30.0) - 2400.0); + dataHandler.init(&dsp.out, _dataHandler, this); + diagHandler.init(&reshape.out, _diagHandler, this); + + // Init decoder + decoder.onMessage.bind(&POCSAGDecoder::messageHandler, this); + } + + ~POCSAGDecoder() { + stop(); } void showMenu() { ImGui::LeftLabel("Baudrate"); ImGui::FillWidth(); - if (ImGui::Combo(("##pager_decoder_proto_" + name).c_str(), &brId, baudrates.txt)) { + if (ImGui::Combo(("##pager_decoder_pocsag_br_" + name).c_str(), &brId, baudrates.txt)) { // TODO } + + ImGui::FillWidth(); + diag.draw(); + } + + void setVFO(VFOManager::VFO* vfo) { + this->vfo = vfo; + vfo->setBandwidthLimits(12500, 12500, true); + vfo->setSampleRate(24000, 12500); + dsp.setInput(vfo->output); + } + + void start() { + flog::debug("POCSAG start"); + dsp.start(); + reshape.start(); + dataHandler.start(); + diagHandler.start(); + } + + void stop() { + flog::debug("POCSAG stop"); + dsp.stop(); + reshape.stop(); + dataHandler.stop(); + diagHandler.stop(); } private: + static void _dataHandler(uint8_t* data, int count, void* ctx) { + POCSAGDecoder* _this = (POCSAGDecoder*)ctx; + _this->decoder.process(data, count); + } + + static void _diagHandler(float* data, int count, void* ctx) { + POCSAGDecoder* _this = (POCSAGDecoder*)ctx; + float* buf = _this->diag.acquireBuffer(); + memcpy(buf, data, count * sizeof(float)); + _this->diag.releaseBuffer(); + } + + void messageHandler(pocsag::Address addr, pocsag::MessageType type, const std::string& msg) { + flog::debug("[{}]: '{}'", (uint32_t)addr, msg); + } + std::string name; + VFOManager::VFO* vfo; + + POCSAGDSP dsp; + dsp::buffer::Reshaper reshape; + dsp::sink::Handler dataHandler; + dsp::sink::Handler diagHandler; + + pocsag::Decoder decoder; ImGui::SymbolDiagram diag; diff --git a/decoder_modules/pager_decoder/src/pocsag/dsp.h b/decoder_modules/pager_decoder/src/pocsag/dsp.h index 0dd241aa..3faca285 100644 --- a/decoder_modules/pager_decoder/src/pocsag/dsp.h +++ b/decoder_modules/pager_decoder/src/pocsag/dsp.h @@ -11,7 +11,7 @@ #include #include -class POCSAGDSP : dsp::Processor { +class POCSAGDSP : public dsp::Processor { using base_type = dsp::Processor; public: POCSAGDSP() {}