#include #include #include #include #include #include #include #include #include #include #include #include #include #include "ryfi/receiver.h" #define CONCAT(a, b) ((std::string(a) + b).c_str()) SDRPP_MOD_INFO{ /* Name: */ "ryfi_decoder", /* Description: */ "RyFi decoder for SDR++", /* Author: */ "Ryzerth", /* Version: */ 0, 1, 0, /* Max instances */ -1 }; #define INPUT_BANDWIDTH 600e3 #define INPUT_SAMPLE_RATE 1000e3 #define INPUT_BAUDRATE 500e3 #define SYMBOL_DIAG_RATE 30 #define SYMBOL_DIAG_COUNT 1024 class RyFiDecoderModule : public ModuleManager::Instance { public: RyFiDecoderModule(std::string name) { this->name = name; vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, INPUT_BANDWIDTH, INPUT_SAMPLE_RATE, INPUT_BANDWIDTH, INPUT_BANDWIDTH, true); rx.init(vfo->output, INPUT_BAUDRATE, INPUT_SAMPLE_RATE); reshape.init(rx.softOut, SYMBOL_DIAG_COUNT, (INPUT_BAUDRATE / SYMBOL_DIAG_RATE) - SYMBOL_DIAG_COUNT); symSink.init(&reshape.out, symSinkHandler, this); rx.onPacket.bind(&RyFiDecoderModule::packetHandler, this); rx.start(); reshape.start(); symSink.start(); gui::menu.registerEntry(name, menuHandler, this, this); } ~RyFiDecoderModule() { rx.stop(); reshape.stop(); symSink.stop(); sigpath::vfoManager.deleteVFO(vfo); gui::menu.removeEntry(name); } void postInit() {} 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); rx.setInput(vfo->output); rx.start(); reshape.start(); symSink.start(); enabled = true; } void disable() { rx.stop(); reshape.stop(); symSink.stop(); sigpath::vfoManager.deleteVFO(vfo); enabled = false; } bool isEnabled() { return enabled; } private: void packetHandler(ryfi::Packet pkt) { flog::debug("Got a {} byte packet!", pkt.size()); } static void menuHandler(void* ctx) { RyFiDecoderModule* _this = (RyFiDecoderModule*)ctx; float menuWidth = ImGui::GetContentRegionAvail().x; if (!_this->enabled) { style::beginDisabled(); } ImGui::SetNextItemWidth(menuWidth); _this->constDiagram.draw(); if (!_this->enabled) { style::endDisabled(); } } static void symSinkHandler(dsp::complex_t* data, int count, void* ctx) { RyFiDecoderModule* _this = (RyFiDecoderModule*)ctx; dsp::complex_t* buf = _this->constDiagram.acquireBuffer(); memcpy(buf, data, 1024 * sizeof(dsp::complex_t)); _this->constDiagram.releaseBuffer(); } std::string name; bool enabled = true; // DSP Chain VFOManager::VFO* vfo; ryfi::Receiver rx; dsp::buffer::Reshaper reshape; dsp::sink::Handler symSink; ImGui::ConstellationDiagram constDiagram; }; MOD_EXPORT void _INIT_() { } MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) { return new RyFiDecoderModule(name); } MOD_EXPORT void _DELETE_INSTANCE_(void* instance) { delete (RyFiDecoderModule*)instance; } MOD_EXPORT void _END_() { }