Skip to content

Commit c4b0cb3

Browse files
Merge pull request #1315 from AlexandreRouma/master
keep new_sinks branch up to date
2 parents cd7dabd + 7ab743d commit c4b0cb3

File tree

16 files changed

+1297
-3
lines changed

16 files changed

+1297
-3
lines changed

CMakeLists.txt

+11-1
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,14 @@ option(OPT_BUILD_FALCON9_DECODER "Build the falcon9 live decoder (Dependencies:
4343
option(OPT_BUILD_KG_SSTV_DECODER "Build the KG SSTV (KG-STV) decoder module (no dependencies required)" OFF)
4444
option(OPT_BUILD_M17_DECODER "Build the M17 decoder module (Dependencies: codec2)" OFF)
4545
option(OPT_BUILD_METEOR_DEMODULATOR "Build the meteor demodulator module (no dependencies required)" ON)
46+
option(OPT_BUILD_PAGER_DECODER "Build the pager decoder module (no dependencies required)" OFF)
4647
option(OPT_BUILD_RADIO "Main audio modulation decoder (AM, FM, SSB, etc...)" ON)
4748
option(OPT_BUILD_WEATHER_SAT_DECODER "Build the HRPT decoder module (no dependencies required)" OFF)
4849

4950
# Misc
5051
option(OPT_BUILD_DISCORD_PRESENCE "Build the Discord Rich Presence module" ON)
5152
option(OPT_BUILD_FREQUENCY_MANAGER "Build the Frequency Manager module" ON)
53+
option(OPT_BUILD_IQ_EXPORTER "Build the IQ Exporter module" OFF)
5254
option(OPT_BUILD_RECORDER "Audio and baseband recorder" ON)
5355
option(OPT_BUILD_RIGCTL_CLIENT "Rigctl client to make SDR++ act as a panadapter" ON)
5456
option(OPT_BUILD_RIGCTL_SERVER "Rigctl backend for controlling SDR++ with software like gpredict" ON)
@@ -234,6 +236,10 @@ if (OPT_BUILD_METEOR_DEMODULATOR)
234236
add_subdirectory("decoder_modules/meteor_demodulator")
235237
endif (OPT_BUILD_METEOR_DEMODULATOR)
236238

239+
if (OPT_BUILD_PAGER_DECODER)
240+
add_subdirectory("decoder_modules/pager_decoder")
241+
endif (OPT_BUILD_PAGER_DECODER)
242+
237243
if (OPT_BUILD_RADIO)
238244
add_subdirectory("decoder_modules/radio")
239245
endif (OPT_BUILD_RADIO)
@@ -252,6 +258,10 @@ if (OPT_BUILD_FREQUENCY_MANAGER)
252258
add_subdirectory("misc_modules/frequency_manager")
253259
endif (OPT_BUILD_FREQUENCY_MANAGER)
254260

261+
if (OPT_BUILD_IQ_EXPORTER)
262+
add_subdirectory("misc_modules/iq_exporter")
263+
endif (OPT_BUILD_IQ_EXPORTER)
264+
255265
if (OPT_BUILD_RECORDER)
256266
add_subdirectory("misc_modules/recorder")
257267
endif (OPT_BUILD_RECORDER)
@@ -302,7 +312,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
302312
add_custom_target(do_always ALL cp \"$<TARGET_FILE_DIR:sdrpp_core>/libsdrpp_core.dylib\" \"$<TARGET_FILE_DIR:sdrpp>\")
303313
endif ()
304314

305-
# cmake .. "-DCMAKE_TOOLCHAIN_FILE=C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_SCANNER=ON -DOPT_BUILD_SCHEDULER=ON -DOPT_BUILD_USRP_SOURCE=ON
315+
# cmake .. "-DCMAKE_TOOLCHAIN_FILE=C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake" -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_SCANNER=ON -DOPT_BUILD_SCHEDULER=ON -DOPT_BUILD_USRP_SOURCE=ON -DOPT_BUILD_PAGER_DECODER=ON
306316

307317
# Create module cmake file
308318
configure_file(${CMAKE_SOURCE_DIR}/sdrpp_module.cmake ${CMAKE_CURRENT_BINARY_DIR}/sdrpp_module.cmake @ONLY)

core/src/utils/net.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,16 @@ namespace net {
138138
}
139139

140140
int Socket::send(const uint8_t* data, size_t len, const Address* dest) {
141-
return sendto(sock, (const char*)data, len, 0, (sockaddr*)(dest ? &dest->addr : (raddr ? &raddr->addr : NULL)), sizeof(sockaddr_in));
141+
// Send data
142+
int err = sendto(sock, (const char*)data, len, 0, (sockaddr*)(dest ? &dest->addr : (raddr ? &raddr->addr : NULL)), sizeof(sockaddr_in));
143+
144+
// On error, close socket
145+
if (err <= 0 && !WOULD_BLOCK) {
146+
close();
147+
return err;
148+
}
149+
150+
return err;
142151
}
143152

144153
int Socket::sendstr(const std::string& str, const Address* dest) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
cmake_minimum_required(VERSION 3.13)
2+
project(pager_decoder)
3+
4+
file(GLOB_RECURSE SRC "src/*.cpp" "src/*.c")
5+
6+
include(${SDRPP_MODULE_CMAKE})
7+
8+
target_include_directories(pager_decoder PRIVATE "src/")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
#include <signal_path/vfo_manager.h>
3+
4+
class Decoder {
5+
public:
6+
virtual ~Decoder() {}
7+
virtual void showMenu() {};
8+
virtual void setVFO(VFOManager::VFO* vfo) = 0;
9+
virtual void start() = 0;
10+
virtual void stop() = 0;
11+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#pragma once
2+
#include "../decoder.h"
3+
#include <signal_path/vfo_manager.h>
4+
#include <utils/optionlist.h>
5+
#include <gui/widgets/symbol_diagram.h>
6+
#include <gui/style.h>
7+
#include <dsp/sink/handler_sink.h>
8+
#include "flex.h"
9+
10+
class FLEXDecoder : public Decoder {
11+
dsp::stream<float> dummy1;
12+
dsp::stream<uint8_t> dummy2;
13+
public:
14+
FLEXDecoder(const std::string& name, VFOManager::VFO* vfo) : diag(0.6, 1600) {
15+
this->name = name;
16+
this->vfo = vfo;
17+
18+
// Define baudrate options
19+
baudrates.define(1600, "1600 Baud", 1600);
20+
baudrates.define(3200, "3200 Baud", 3200);
21+
baudrates.define(6400, "6400 Baud", 6400);
22+
23+
// Init DSP
24+
vfo->setBandwidthLimits(12500, 12500, true);
25+
vfo->setSampleRate(16000, 12500);
26+
reshape.init(&dummy1, 1600.0, (1600 / 30.0) - 1600.0);
27+
dataHandler.init(&dummy2, _dataHandler, this);
28+
diagHandler.init(&reshape.out, _diagHandler, this);
29+
}
30+
31+
~FLEXDecoder() {
32+
stop();
33+
}
34+
35+
void showMenu() {
36+
ImGui::LeftLabel("Baudrate");
37+
ImGui::FillWidth();
38+
if (ImGui::Combo(("##pager_decoder_flex_br_" + name).c_str(), &brId, baudrates.txt)) {
39+
// TODO
40+
}
41+
42+
ImGui::FillWidth();
43+
diag.draw();
44+
}
45+
46+
void setVFO(VFOManager::VFO* vfo) {
47+
this->vfo = vfo;
48+
vfo->setBandwidthLimits(12500, 12500, true);
49+
vfo->setSampleRate(24000, 12500);
50+
// dsp.setInput(vfo->output);
51+
}
52+
53+
void start() {
54+
flog::debug("FLEX start");
55+
// dsp.start();
56+
reshape.start();
57+
dataHandler.start();
58+
diagHandler.start();
59+
}
60+
61+
void stop() {
62+
flog::debug("FLEX stop");
63+
// dsp.stop();
64+
reshape.stop();
65+
dataHandler.stop();
66+
diagHandler.stop();
67+
}
68+
69+
private:
70+
static void _dataHandler(uint8_t* data, int count, void* ctx) {
71+
FLEXDecoder* _this = (FLEXDecoder*)ctx;
72+
// _this->decoder.process(data, count);
73+
}
74+
75+
static void _diagHandler(float* data, int count, void* ctx) {
76+
FLEXDecoder* _this = (FLEXDecoder*)ctx;
77+
float* buf = _this->diag.acquireBuffer();
78+
memcpy(buf, data, count * sizeof(float));
79+
_this->diag.releaseBuffer();
80+
}
81+
82+
std::string name;
83+
84+
VFOManager::VFO* vfo;
85+
dsp::buffer::Reshaper<float> reshape;
86+
dsp::sink::Handler<uint8_t> dataHandler;
87+
dsp::sink::Handler<float> diagHandler;
88+
89+
flex::Decoder decoder;
90+
91+
ImGui::SymbolDiagram diag;
92+
93+
int brId = 0;
94+
95+
OptionList<int, int> baudrates;
96+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include "flex.h"
2+
3+
namespace flex {
4+
// TODO
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
3+
namespace flex {
4+
class Decoder {
5+
public:
6+
// TODO
7+
8+
private:
9+
// TODO
10+
};
11+
}
+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
#include <imgui.h>
2+
#include <config.h>
3+
#include <core.h>
4+
#include <gui/style.h>
5+
#include <gui/gui.h>
6+
#include <signal_path/signal_path.h>
7+
#include <module.h>
8+
#include <gui/widgets/folder_select.h>
9+
#include <utils/optionlist.h>
10+
#include "decoder.h"
11+
#include "pocsag/decoder.h"
12+
#include "flex/decoder.h"
13+
14+
#define CONCAT(a, b) ((std::string(a) + b).c_str())
15+
16+
SDRPP_MOD_INFO{
17+
/* Name: */ "pager_decoder",
18+
/* Description: */ "POCSAG and Flex Pager Decoder"
19+
/* Author: */ "Ryzerth",
20+
/* Version: */ 0, 1, 0,
21+
/* Max instances */ -1
22+
};
23+
24+
ConfigManager config;
25+
26+
enum Protocol {
27+
PROTOCOL_INVALID = -1,
28+
PROTOCOL_POCSAG,
29+
PROTOCOL_FLEX
30+
};
31+
32+
class PagerDecoderModule : public ModuleManager::Instance {
33+
public:
34+
PagerDecoderModule(std::string name) {
35+
this->name = name;
36+
37+
// Define protocols
38+
protocols.define("POCSAG", PROTOCOL_POCSAG);
39+
protocols.define("FLEX", PROTOCOL_FLEX);
40+
41+
// Initialize VFO with default values
42+
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 12500, 24000, 12500, 12500, true);
43+
vfo->setSnapInterval(1);
44+
45+
// Select the protocol
46+
selectProtocol(PROTOCOL_POCSAG);
47+
48+
gui::menu.registerEntry(name, menuHandler, this, this);
49+
}
50+
51+
~PagerDecoderModule() {
52+
gui::menu.removeEntry(name);
53+
// Stop DSP
54+
if (enabled) {
55+
decoder->stop();
56+
decoder.reset();
57+
sigpath::vfoManager.deleteVFO(vfo);
58+
}
59+
60+
sigpath::sinkManager.unregisterStream(name);
61+
}
62+
63+
void postInit() {}
64+
65+
void enable() {
66+
double bw = gui::waterfall.getBandwidth();
67+
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp<double>(0, -bw / 2.0, bw / 2.0), 12500, 24000, 12500, 12500, true);
68+
vfo->setSnapInterval(1);
69+
70+
decoder->setVFO(vfo);
71+
decoder->start();
72+
73+
enabled = true;
74+
}
75+
76+
void disable() {
77+
decoder->stop();
78+
sigpath::vfoManager.deleteVFO(vfo);
79+
enabled = false;
80+
}
81+
82+
bool isEnabled() {
83+
return enabled;
84+
}
85+
86+
void selectProtocol(Protocol newProto) {
87+
// Cannot change while disabled
88+
if (!enabled) { return; }
89+
90+
// If the protocol hasn't changed, no need to do anything
91+
if (newProto == proto) { return; }
92+
93+
// Delete current decoder
94+
decoder.reset();
95+
96+
// Create a new decoder
97+
switch (newProto) {
98+
case PROTOCOL_POCSAG:
99+
decoder = std::make_unique<POCSAGDecoder>(name, vfo);
100+
break;
101+
case PROTOCOL_FLEX:
102+
decoder = std::make_unique<FLEXDecoder>(name, vfo);
103+
break;
104+
default:
105+
flog::error("Tried to select unknown pager protocol");
106+
return;
107+
}
108+
109+
// Start the new decoder
110+
decoder->start();
111+
112+
// Save selected protocol
113+
proto = newProto;
114+
}
115+
116+
private:
117+
static void menuHandler(void* ctx) {
118+
PagerDecoderModule* _this = (PagerDecoderModule*)ctx;
119+
120+
float menuWidth = ImGui::GetContentRegionAvail().x;
121+
122+
if (!_this->enabled) { style::beginDisabled(); }
123+
124+
ImGui::LeftLabel("Protocol");
125+
ImGui::FillWidth();
126+
if (ImGui::Combo(("##pager_decoder_proto_" + _this->name).c_str(), &_this->protoId, _this->protocols.txt)) {
127+
_this->selectProtocol(_this->protocols.value(_this->protoId));
128+
}
129+
130+
if (_this->decoder) { _this->decoder->showMenu(); }
131+
132+
ImGui::Button(("Record##pager_decoder_show_" + _this->name).c_str(), ImVec2(menuWidth, 0));
133+
ImGui::Button(("Show Messages##pager_decoder_show_" + _this->name).c_str(), ImVec2(menuWidth, 0));
134+
135+
if (!_this->enabled) { style::endDisabled(); }
136+
}
137+
138+
std::string name;
139+
bool enabled = true;
140+
141+
Protocol proto = PROTOCOL_INVALID;
142+
int protoId = 0;
143+
144+
OptionList<std::string, Protocol> protocols;
145+
146+
// DSP Chain
147+
VFOManager::VFO* vfo;
148+
std::unique_ptr<Decoder> decoder;
149+
150+
bool showLines = false;
151+
};
152+
153+
MOD_EXPORT void _INIT_() {
154+
// Create default recording directory
155+
json def = json({});
156+
config.setPath(core::args["root"].s() + "/pager_decoder_config.json");
157+
config.load(def);
158+
config.enableAutoSave();
159+
}
160+
161+
MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) {
162+
return new PagerDecoderModule(name);
163+
}
164+
165+
MOD_EXPORT void _DELETE_INSTANCE_(void* instance) {
166+
delete (PagerDecoderModule*)instance;
167+
}
168+
169+
MOD_EXPORT void _END_() {
170+
config.disableAutoSave();
171+
config.save();
172+
}

0 commit comments

Comments
 (0)