Merge pull request #1385 from AlexandreRouma/master

Keep new_sinks branch up to date
This commit is contained in:
AlexandreRouma 2024-04-18 03:14:40 +02:00 committed by GitHub
commit 40f1ee5651
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
47 changed files with 1063 additions and 196 deletions

View File

@ -37,10 +37,10 @@ jobs:
run: 7z x libusb.7z -olibusb_old ; rm "C:/Program Files/PothosSDR/bin/libusb-1.0.dll" ; cp "libusb_old/MS64/dll/libusb-1.0.dll" "C:/Program Files/PothosSDR/bin/" ; rm "C:/Program Files/PothosSDR/lib/libusb-1.0.lib" ; cp "libusb_old/MS64/dll/libusb-1.0.lib" "C:/Program Files/PothosSDR/lib/"
- name: Download SDRPlay API
run: Invoke-WebRequest -Uri "https://drive.google.com/uc?id=12UHPMwkfa67A11QZDmpCT4iwHnyJHWuu&confirm=t" -OutFile ${{runner.workspace}}/SDRPlay.zip
run: Invoke-WebRequest -Uri "https://www.sdrpp.org/SDRplay.zip" -OutFile ${{runner.workspace}}/SDRplay.zip
- name: Install SDRPlay API
run: 7z x ${{runner.workspace}}/SDRPlay.zip -o"C:/Program Files/"
run: 7z x ${{runner.workspace}}/SDRplay.zip -o"C:/Program Files/"
- name: Download codec2
run: git clone https://github.com/AlexandreRouma/codec2
@ -84,8 +84,8 @@ jobs:
name: sdrpp_windows_x64
path: ${{runner.workspace}}/sdrpp_windows_x64.zip
build_macos:
runs-on: macos-latest
build_macos_intel:
runs-on: macos-12
steps:
- uses: actions/checkout@v4
@ -93,9 +93,6 @@ jobs:
- name: Create Build Environment
run: cmake -E make_directory ${{runner.workspace}}/build
- name: Update brew repositories
run: brew update
- name: Install dependencies
run: brew install pkg-config libusb fftw glfw airspy airspyhf portaudio hackrf libbladerf codec2 zstd autoconf automake libtool && pip3 install mako
@ -103,7 +100,7 @@ jobs:
run: git clone --recursive https://github.com/gnuradio/volk && cd volk && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Install SDRplay API
run: wget https://www.sdrplay.com/software/SDRplayAPI-macos-installer-universal-3.12.1.pkg && sudo installer -pkg SDRplayAPI-macos-installer-universal-3.12.1.pkg -target /
run: wget https://www.sdrplay.com/software/SDRplayAPI-macos-installer-universal-3.14.0.pkg && sudo installer -pkg SDRplayAPI-macos-installer-universal-3.14.0.pkg -target /
- name: Install libiio
run: wget https://github.com/analogdevicesinc/libiio/archive/refs/tags/v0.25.zip && 7z x v0.25.zip && cd libiio-0.25 && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
@ -122,7 +119,7 @@ jobs:
- name: Prepare CMake
working-directory: ${{runner.workspace}}/build
run: cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 $GITHUB_WORKSPACE -DOPT_BUILD_PLUTOSDR_SOURCE=ON -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 -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_AUDIO_SOURCE=OFF -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release
run: cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 $GITHUB_WORKSPACE -DOPT_BUILD_PLUTOSDR_SOURCE=ON -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 -DOPT_BUILD_PERSEUS_SOURCE=ON -DOPT_BUILD_AUDIO_SOURCE=OFF -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release
- name: Build
working-directory: ${{runner.workspace}}/build
@ -138,6 +135,57 @@ jobs:
name: sdrpp_macos_intel
path: ${{runner.workspace}}/sdrpp_macos_intel.zip
build_macos_arm:
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- name: Create Build Environment
run: cmake -E make_directory ${{runner.workspace}}/build
- name: Install dependencies
run: brew install pkg-config libusb fftw glfw airspy airspyhf portaudio hackrf libbladerf codec2 zstd autoconf automake libtool && pip3 install mako --break-system-packages
- name: Install volk
run: git clone --recursive https://github.com/gnuradio/volk && cd volk && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Install SDRplay API
run: wget https://www.sdrplay.com/software/SDRplayAPI-macos-installer-universal-3.14.0.pkg && sudo installer -pkg SDRplayAPI-macos-installer-universal-3.14.0.pkg -target /
- name: Install libiio
run: wget https://github.com/analogdevicesinc/libiio/archive/refs/tags/v0.25.zip && 7z x v0.25.zip && cd libiio-0.25 && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Install libad9361
run: git clone https://github.com/analogdevicesinc/libad9361-iio && cd libad9361-iio && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
- name: Install LimeSuite
run: git clone https://github.com/myriadrf/LimeSuite && cd LimeSuite && mkdir builddir && cd builddir && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 && sudo make install && cd ../../
# - name: Install libperseus
# run: git clone https://github.com/Microtelecom/libperseus-sdr && cd libperseus-sdr && autoreconf -i && ./configure --prefix=/usr/local && make && make install && cd ..
- name: Install more recent librtlsdr
run: git clone https://github.com/osmocom/rtl-sdr && cd rtl-sdr && mkdir build && cd build && cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=Release .. && make -j3 LIBRARY_PATH=$(pkg-config --libs-only-L libusb-1.0 | sed 's/\-L//') && sudo make install && cd ../../
- name: Prepare CMake
working-directory: ${{runner.workspace}}/build
run: cmake -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 $GITHUB_WORKSPACE -DOPT_BUILD_PLUTOSDR_SOURCE=ON -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 -DOPT_BUILD_PERSEUS_SOURCE=OFF -DOPT_BUILD_AUDIO_SOURCE=OFF -DUSE_BUNDLE_DEFAULTS=ON -DCMAKE_BUILD_TYPE=Release
- name: Build
working-directory: ${{runner.workspace}}/build
run: make VERBOSE=1 -j3
- name: Create Archive
working-directory: ${{runner.workspace}}
run: cd $GITHUB_WORKSPACE && sh make_macos_bundle.sh ${{runner.workspace}}/build ./SDR++.app && zip -r ${{runner.workspace}}/sdrpp_macos_arm.zip SDR++.app
- name: Save Archive
uses: actions/upload-artifact@v4
with:
name: sdrpp_macos_arm
path: ${{runner.workspace}}/sdrpp_macos_arm.zip
build_debian_buster:
runs-on: ubuntu-latest
@ -347,7 +395,7 @@ jobs:
path: ${{runner.workspace}}/sdrpp.apk
create_full_archive:
needs: ['build_windows', 'build_macos', 'build_debian_buster', 'build_debian_bullseye', 'build_debian_bookworm', 'build_debian_sid', 'build_ubuntu_focal', 'build_ubuntu_jammy', 'build_ubuntu_mantic', 'build_raspios_bullseye_armhf', 'build_android']
needs: ['build_windows', 'build_macos_intel', 'build_macos_arm', 'build_debian_buster', 'build_debian_bullseye', 'build_debian_bookworm', 'build_debian_sid', 'build_ubuntu_focal', 'build_ubuntu_jammy', 'build_ubuntu_mantic', 'build_raspios_bullseye_armhf', 'build_android']
runs-on: ubuntu-latest
steps:
@ -359,6 +407,7 @@ jobs:
mkdir sdrpp_all &&
mv sdrpp_windows_x64/sdrpp_windows_x64.zip sdrpp_all/ &&
mv sdrpp_macos_intel/sdrpp_macos_intel.zip sdrpp_all/ &&
mv sdrpp_macos_arm/sdrpp_macos_arm.zip sdrpp_all/ &&
mv sdrpp_debian_buster_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_buster_amd64.deb &&
mv sdrpp_debian_bullseye_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_bullseye_amd64.deb &&
mv sdrpp_debian_bookworm_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_bookworm_amd64.deb &&

View File

@ -17,6 +17,7 @@ option(OPT_BUILD_FILE_SOURCE "Wav file source" ON)
option(OPT_BUILD_HACKRF_SOURCE "Build HackRF Source Module (Dependencies: libhackrf)" ON)
option(OPT_BUILD_HERMES_SOURCE "Build Hermes Source Module (no dependencies required)" ON)
option(OPT_BUILD_LIMESDR_SOURCE "Build LimeSDR Source Module (Dependencies: liblimesuite)" OFF)
option(OPT_BUILD_NETWORK_SOURCE "Build Network Source Module (no dependencies required)" ON)
option(OPT_BUILD_PERSEUS_SOURCE "Build Perseus Source Module (Dependencies: libperseus-sdr)" OFF)
option(OPT_BUILD_PLUTOSDR_SOURCE "Build PlutoSDR Source Module (Dependencies: libiio, libad9361)" ON)
option(OPT_BUILD_RFSPACE_SOURCE "Build RFspace Source Module (no dependencies required)" ON)
@ -24,7 +25,7 @@ option(OPT_BUILD_RTL_SDR_SOURCE "Build RTL-SDR Source Module (Dependencies: libr
option(OPT_BUILD_RTL_TCP_SOURCE "Build RTL-TCP Source Module (no dependencies required)" ON)
option(OPT_BUILD_SDRPP_SERVER_SOURCE "Build SDR++ Server Source Module (no dependencies required)" ON)
option(OPT_BUILD_SDRPLAY_SOURCE "Build SDRplay Source Module (Dependencies: libsdrplay)" OFF)
option(OPT_BUILD_SOAPY_SOURCE "Build SoapySDR Source Module (Dependencies: soapysdr)" ON)
option(OPT_BUILD_SOAPY_SOURCE "Build SoapySDR Source Module (Dependencies: soapysdr)" OFF)
option(OPT_BUILD_SPECTRAN_SOURCE "Build Spectran Source Module (Dependencies: Aaronia RTSA Suite)" OFF)
option(OPT_BUILD_SPECTRAN_HTTP_SOURCE "Build Spectran HTTP Source Module (no dependencies required)" ON)
option(OPT_BUILD_SPYSERVER_SOURCE "Build SpyServer Source Module (no dependencies required)" ON)
@ -43,14 +44,14 @@ option(OPT_BUILD_FALCON9_DECODER "Build the falcon9 live decoder (Dependencies:
option(OPT_BUILD_KG_SSTV_DECODER "Build the KG SSTV (KG-STV) decoder 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_PAGER_DECODER "Build the pager decoder module (no dependencies required)" OFF)
option(OPT_BUILD_PAGER_DECODER "Build the pager decoder 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)
# Misc
option(OPT_BUILD_DISCORD_PRESENCE "Build the Discord Rich Presence module" ON)
option(OPT_BUILD_FREQUENCY_MANAGER "Build the Frequency Manager module" ON)
option(OPT_BUILD_IQ_EXPORTER "Build the IQ Exporter module" OFF)
option(OPT_BUILD_IQ_EXPORTER "Build the IQ Exporter module" ON)
option(OPT_BUILD_RECORDER "Audio and baseband recorder" ON)
option(OPT_BUILD_RIGCTL_CLIENT "Rigctl client to make SDR++ act as a panadapter" ON)
option(OPT_BUILD_RIGCTL_SERVER "Rigctl backend for controlling SDR++ with software like gpredict" ON)
@ -144,6 +145,10 @@ if (OPT_BUILD_LIMESDR_SOURCE)
add_subdirectory("source_modules/limesdr_source")
endif (OPT_BUILD_LIMESDR_SOURCE)
if (OPT_BUILD_NETWORK_SOURCE)
add_subdirectory("source_modules/network_source")
endif (OPT_BUILD_NETWORK_SOURCE)
if (OPT_BUILD_PERSEUS_SOURCE)
add_subdirectory("source_modules/perseus_source")
endif (OPT_BUILD_PERSEUS_SOURCE)
@ -282,7 +287,12 @@ if (OPT_BUILD_SCHEDULER)
add_subdirectory("misc_modules/scheduler")
endif (OPT_BUILD_SCHEDULER)
add_executable(sdrpp "src/main.cpp" "win32/resources.rc")
if (MSVC)
add_executable(sdrpp "src/main.cpp" "win32/resources.rc")
else ()
add_executable(sdrpp "src/main.cpp")
endif ()
target_link_libraries(sdrpp PRIVATE sdrpp_core)
# Compiler arguments

View File

@ -193,8 +193,6 @@ int sdrpp_main(int argc, char* argv[]) {
defConfig["moduleInstances"]["SDRplay Source"]["enabled"] = true;
defConfig["moduleInstances"]["SDR++ Server Source"]["module"] = "sdrpp_server_source";
defConfig["moduleInstances"]["SDR++ Server Source"]["enabled"] = true;
defConfig["moduleInstances"]["SoapySDR Source"]["module"] = "soapy_source";
defConfig["moduleInstances"]["SoapySDR Source"]["enabled"] = true;
defConfig["moduleInstances"]["SpyServer Source"]["module"] = "spyserver_source";
defConfig["moduleInstances"]["SpyServer Source"]["enabled"] = true;

View File

@ -41,6 +41,7 @@ namespace sdrpp_credits {
"CaribouLabs",
"Ettus Research",
"Howard Su",
"MicroPhase",
"MyriadRF",
"Nuand",
"RFspace",
@ -54,6 +55,7 @@ namespace sdrpp_credits {
"Croccydile",
"Dale L Puckett (K0HYD)",
"Daniele D'Agnelli",
"David Taylor (GM8ARV)",
"D. Jones",
"Dexruus",
"EB3FRN",
@ -81,6 +83,7 @@ namespace sdrpp_credits {
"Syne Ardwin (WI9SYN)",
"W4IPA",
"William Arcand (W1WRA)",
"William Pitchford",
"Yves Rougy",
"Zipper"
};

View File

@ -41,7 +41,11 @@ namespace dsp::channel {
}
inline int process(int count, const complex_t* in, complex_t* out) {
#if VOLK_VERSION >= 030100
volk_32fc_s32fc_x2_rotator2_32fc((lv_32fc_t*)out, (lv_32fc_t*)in, &phaseDelta, &phase, count);
#else
volk_32fc_s32fc_x2_rotator_32fc((lv_32fc_t*)out, (lv_32fc_t*)in, phaseDelta, &phase, count);
#endif
return count;
}

View File

@ -12,6 +12,10 @@ namespace dsp::compression {
void init(stream<complex_t>* in, PCMType pcmType) {
_pcmType = pcmType;
// Set the output buffer size to the max size of a complex buffer + 8 bytes for the header
out.setBufferSize(STREAM_BUFFER_SIZE*sizeof(complex_t) + 8);
base_type::init(in);
}

View File

@ -41,10 +41,10 @@ namespace dsp::filter {
// Move existing data to make transition seemless
if (_taps.size < oldTC) {
memcpy(buffer, &buffer[oldTC - _taps.size], (_taps.size - 1) * sizeof(D));
memmove(buffer, &buffer[oldTC - _taps.size], (_taps.size - 1) * sizeof(D));
}
else if (_taps.size > oldTC) {
memcpy(&buffer[_taps.size - oldTC], buffer, (oldTC - 1) * sizeof(D));
memmove(&buffer[_taps.size - oldTC], buffer, (oldTC - 1) * sizeof(D));
buffer::clear<D>(buffer, _taps.size - oldTC);
}

View File

@ -436,6 +436,9 @@ void MainWindow::draw() {
showCredits = false;
}
// Reset waterfall lock
lockWaterfallControls = showCredits;
// Handle menu resize
ImVec2 winSize = ImGui::GetWindowSize();
ImVec2 mousePos = ImGui::GetMousePos();
@ -466,9 +469,10 @@ void MainWindow::draw() {
}
}
// Process menu keybinds
displaymenu::checkKeybinds();
// Left Column
lockWaterfallControls = false;
if (showMenu) {
ImGui::Columns(3, "WindowColumns", false);
ImGui::SetColumnWidth(0, menuWidth);
@ -577,6 +581,8 @@ void MainWindow::draw() {
// Handle scrollwheel
int wheel = ImGui::GetIO().MouseWheel;
if (wheel != 0 && (gui::waterfall.mouseInFFT || gui::waterfall.mouseInWaterfall)) {
double nfreq;
if (vfo != NULL) {
// Select factor depending on modifier keys
double interval;
if (ImGui::IsKeyDown(ImGuiKey_LeftShift)) {
@ -589,8 +595,6 @@ void MainWindow::draw() {
interval = vfo->snapInterval;
}
double nfreq;
if (vfo != NULL) {
nfreq = gui::waterfall.getCenterFrequency() + vfo->generalOffset + (interval * wheel);
nfreq = roundl(nfreq / interval) * interval;
}

View File

@ -127,17 +127,26 @@ namespace displaymenu {
uiScaleId = uiScales.valueId(style::uiScale);
}
void draw(void* ctx) {
float menuWidth = ImGui::GetContentRegionAvail().x;
bool homePressed = ImGui::IsKeyPressed(ImGuiKey_Home, false);
if (ImGui::Checkbox("Show Waterfall##_sdrpp", &showWaterfall) || homePressed) {
if (homePressed) { showWaterfall = !showWaterfall; }
void setWaterfallShown(bool shown) {
showWaterfall = shown;
showWaterfall ? gui::waterfall.showWaterfall() : gui::waterfall.hideWaterfall();
core::configManager.acquire();
core::configManager.conf["showWaterfall"] = showWaterfall;
core::configManager.release(true);
}
void checkKeybinds() {
if (ImGui::IsKeyPressed(ImGuiKey_Home, false)) {
setWaterfallShown(!showWaterfall);
}
}
void draw(void* ctx) {
float menuWidth = ImGui::GetContentRegionAvail().x;
if (ImGui::Checkbox("Show Waterfall##_sdrpp", &showWaterfall)) {
setWaterfallShown(showWaterfall);
}
if (ImGui::Checkbox("Full Waterfall Update##_sdrpp", &fullWaterfallUpdate)) {
gui::waterfall.setFullWaterfallUpdate(fullWaterfallUpdate);
core::configManager.acquire();

View File

@ -2,5 +2,6 @@
namespace displaymenu {
void init();
void checkKeybinds();
void draw(void* ctx);
}

View File

@ -39,7 +39,7 @@ namespace module_manager_menu {
ImVec2 btnSize = ImVec2(lheight, lheight - 1);
ImVec2 textOff = ImVec2(3.0f * style::uiScale, -5.0f * style::uiScale);
if (ImGui::BeginTable("Module Manager Table", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, ImVec2(0, 200))) {
if (ImGui::BeginTable("Module Manager Table", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, ImVec2(0, 200.0f * style::uiScale))) {
ImGui::TableSetupColumn("Name");
ImGui::TableSetupColumn("Type");
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, cellWidth);

View File

@ -230,7 +230,7 @@ namespace server {
// Compress data if needed and fill out header fields
if (compression) {
bb_pkt_hdr->type = PACKET_TYPE_BASEBAND_COMPRESSED;
bb_pkt_hdr->size = sizeof(PacketHeader) + (uint32_t)ZSTD_compressCCtx(cctx, &bbuf[sizeof(PacketHeader)], SERVER_MAX_PACKET_SIZE, data, count, 1);
bb_pkt_hdr->size = sizeof(PacketHeader) + (uint32_t)ZSTD_compressCCtx(cctx, &bbuf[sizeof(PacketHeader)], SERVER_MAX_PACKET_SIZE-sizeof(PacketHeader), data, count, 1);
}
else {
bb_pkt_hdr->type = PACKET_TYPE_BASEBAND;

View File

@ -84,7 +84,7 @@ void SourceManager::tune(double freq) {
if (selectedHandler == NULL) {
return;
}
// TODO: No need to always retune the hardware in panadpter mode
// TODO: No need to always retune the hardware in Panadapter mode
selectedHandler->tuneHandler(((tuneMode == TuningMode::NORMAL) ? freq : ifFreq) + tuneOffset, selectedHandler->ctx);
onRetune.emit(freq);
currentFreq = freq;
@ -100,7 +100,7 @@ void SourceManager::setTuningMode(TuningMode mode) {
tune(currentFreq);
}
void SourceManager::setPanadpterIF(double freq) {
void SourceManager::setPanadapterIF(double freq) {
ifFreq = freq;
tune(currentFreq);
}

View File

@ -35,7 +35,7 @@ public:
void tune(double freq);
void setTuningOffset(double offset);
void setTuningMode(TuningMode mode);
void setPanadpterIF(double freq);
void setPanadapterIF(double freq);
std::vector<std::string> getSourceNames();

View File

@ -139,18 +139,19 @@ class ATVDecoderModule : public ModuleManager::Instance {
_this->pll.process(720, _this->fir.out.writeBuf, _this->pll.out.writeBuf, ((_this->ypos%2)==1) ^ _this->evenFrame);
// Render line to the image without color
//int lypos = _this->ypos - 1;
//if (lypos < 0) { lypos = 624; }
//uint32_t* lastLine = &((uint32_t *)_this->img.buffer)[(lypos < 313) ? (lypos*720*2) : ((((lypos - 313)*2)+1)*720) ];
//uint32_t* currentLine = &((uint32_t *)_this->img.buffer)[(_this->ypos < 313) ? (_this->ypos*720*2) : ((((_this->ypos - 313)*2)+1)*720) ];
int lypos = _this->ypos - 1;
if (lypos < 0) { lypos = 624; }
uint32_t* lastLine = &((uint32_t *)_this->img.buffer)[(lypos < 313) ? (lypos*720*2) : ((((lypos - 313)*2)+1)*720) ];
uint32_t* currentLine = &((uint32_t *)_this->img.buffer)[(_this->ypos < 313) ? (_this->ypos*720*2) : ((((_this->ypos - 313)*2)+1)*720) ];
uint32_t* currentLine = &((uint32_t *)_this->img.buffer)[_this->ypos*720];
//uint32_t* currentLine = &((uint32_t *)_this->img.buffer)[_this->ypos*720];
for (int i = 0; i < count; i++) {
//float imval = std::clamp<float>((data[i] - _this->minLvl) * 255.0 / _this->spanLvl, 0, 255);
uint32_t re = std::clamp<float>((_this->pll.out.writeBuf[i].re - _this->minLvl) * 255.0 / _this->spanLvl, 0, 255);
uint32_t im = std::clamp<float>((_this->pll.out.writeBuf[i].im - _this->minLvl) * 255.0 / _this->spanLvl, 0, 255);
currentLine[i] = 0xFF000000 | (im << 8) | re;
int imval = std::clamp<float>((data[i] - _this->minLvl) * 255.0 / _this->spanLvl, 0, 255);
// uint32_t re = std::clamp<float>((_this->pll.out.writeBuf[i].re - _this->minLvl) * 255.0 / _this->spanLvl, 0, 255);
// uint32_t im = std::clamp<float>((_this->pll.out.writeBuf[i].im - _this->minLvl) * 255.0 / _this->spanLvl, 0, 255);
// currentLine[i] = 0xFF000000 | (im << 8) | re;
currentLine[i] = 0xFF000000 | (imval << 16) | (imval << 8) | imval;
}
// Vertical scan logic

View File

@ -36,7 +36,7 @@ public:
// Define protocols
protocols.define("POCSAG", PROTOCOL_POCSAG);
protocols.define("FLEX", PROTOCOL_FLEX);
//protocols.define("FLEX", PROTOCOL_FLEX);
// Initialize VFO with default values
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 12500, 24000, 12500, 12500, true);

View File

@ -8,16 +8,12 @@
#include "dsp.h"
#include "pocsag.h"
const char* msgTypes[] = {
"Numeric",
"Unknown (0b01)",
"Unknown (0b10)",
"Alphanumeric",
};
#define BAUDRATE 2400
#define SAMPLERATE (BAUDRATE*10)
class POCSAGDecoder : public Decoder {
public:
POCSAGDecoder(const std::string& name, VFOManager::VFO* vfo) : diag(0.6, 2400) {
POCSAGDecoder(const std::string& name, VFOManager::VFO* vfo) : diag(0.6, BAUDRATE) {
this->name = name;
this->vfo = vfo;
@ -28,9 +24,9 @@ public:
// 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);
vfo->setSampleRate(SAMPLERATE, 12500);
dsp.init(vfo->output, SAMPLERATE, BAUDRATE);
reshape.init(&dsp.soft, BAUDRATE, (BAUDRATE / 30.0) - BAUDRATE);
dataHandler.init(&dsp.out, _dataHandler, this);
diagHandler.init(&reshape.out, _diagHandler, this);
@ -61,7 +57,6 @@ public:
}
void start() {
flog::debug("POCSAG start");
dsp.start();
reshape.start();
dataHandler.start();
@ -69,7 +64,6 @@ public:
}
void stop() {
flog::debug("POCSAG stop");
dsp.stop();
reshape.stop();
dataHandler.stop();

View File

@ -19,18 +19,16 @@ public:
void init(dsp::stream<dsp::complex_t>* in, double samplerate, double baudrate) {
// Save settings
// TODO
_samplerate = samplerate;
// Configure blocks
demod.init(NULL, -4500.0, samplerate);
dcBlock.init(NULL, 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<float>(10, taps);
fir.init(NULL, shape);
recov.init(NULL, samplerate/baudrate, 1e5, 0.1, 0.05);
recov.init(NULL, samplerate/baudrate, 1e-4, 1.0, 0.05);
// Free useless buffers
dcBlock.out.free();
fir.out.free();
recov.out.free();
@ -40,13 +38,20 @@ public:
int process(int count, dsp::complex_t* in, float* softOut, uint8_t* out) {
count = demod.process(count, in, demod.out.readBuf);
count = dcBlock.process(count, demod.out.readBuf, demod.out.readBuf);
count = fir.process(count, demod.out.readBuf, demod.out.readBuf);
count = recov.process(count, demod.out.readBuf, softOut);
dsp::digital::BinarySlicer::process(count, softOut, out);
return count;
}
void setBaudrate(double baudrate) {
assert(base_type::_block_init);
std::lock_guard<std::recursive_mutex> lck(base_type::ctrlMtx);
base_type::tempStop();
base_type::tempStart();
}
int run() {
int count = base_type::_in->read();
if (count < 0) { return -1; }
@ -55,7 +60,7 @@ public:
base_type::_in->flush();
if (!base_type::out.swap(count)) { return -1; }
if (!soft.swap(count)) { return -1; }
if (count) { if (!soft.swap(count)) { return -1; } }
return count;
}
@ -63,9 +68,9 @@ public:
private:
dsp::demod::Quadrature demod;
dsp::correction::DCBlocker<float> dcBlock;
dsp::tap<float> shape;
dsp::filter::FIR<float, float> fir;
dsp::clock_recovery::MM<float> recov;
double _samplerate;
};

View File

@ -5,6 +5,7 @@
#define POCSAG_FRAME_SYNC_CODEWORD ((uint32_t)(0b01111100110100100001010111011000))
#define POCSAG_IDLE_CODEWORD_DATA ((uint32_t)(0b011110101100100111000))
#define POCSAG_BATCH_BIT_COUNT (POCSAG_BATCH_CODEWORD_COUNT*32)
#define POCSAG_DATA_BITS_PER_CW 20
#define POCSAG_GEN_POLY ((uint32_t)(0b11101101001))
@ -28,6 +29,11 @@ namespace pocsag {
'['
};
Decoder::Decoder() {
// Zero out batch
memset(batch, 0, sizeof(batch));
}
void Decoder::process(uint8_t* symbols, int count) {
for (int i = 0; i < count; i++) {
// Get symbol
@ -78,8 +84,26 @@ namespace pocsag {
void Decoder::flushMessage() {
if (!msg.empty()) {
// Send out message
onMessage(addr, msgType, msg);
// Reset state
msg.clear();
currChar = 0;
currOffset = 0;
}
}
void printbin(uint32_t cw) {
for (int i = 31; i >= 0; i--) {
printf("%c", ((cw >> i) & 1) ? '1':'0');
}
}
void bitswapChar(char in, char& out) {
out = 0;
for (int i = 0; i < 7; i++) {
out |= ((in >> (6-i)) & 1) << i;
}
}
@ -102,14 +126,14 @@ namespace pocsag {
if (type == CODEWORD_TYPE_IDLE) {
// If a non-empty message is available, send it out and clear
flushMessage();
flog::debug("[{}:{}]: IDLE", (i >> 1), i&1);
}
else if (type == CODEWORD_TYPE_ADDRESS) {
// If a non-empty message is available, send it out and clear
flushMessage();
// Decode message type
msgType = (MessageType)((cw >> 11) & 0b11);
msgType = MESSAGE_TYPE_ALPHANUMERIC;
// msgType = (MessageType)((cw >> 11) & 0b11);
// Decode address and append lower 8 bits from position
addr = ((cw >> 13) & 0b111111111111111111) << 3;
@ -129,11 +153,20 @@ namespace pocsag {
msg += NUMERIC_CHARSET[data & 0b1111];
}
else if (msgType == MESSAGE_TYPE_ALPHANUMERIC) {
// Unpack ascii bits 7 at a time (TODO: could be more efficient)
for (int i = 19; i >= 0; i--) {
// Append bit to char
currChar |= ((data >> i) & 1) << (currOffset++);
// When the char is full, append to message
if (currOffset >= 7) {
// TODO: maybe replace with std::isprint
if (currChar) { msg += currChar; }
currChar = 0;
currOffset = 0;
}
}
}
// Save last data
lastMsgData = data;
}
}
}

View File

@ -23,6 +23,8 @@ namespace pocsag {
class Decoder {
public:
Decoder();
void process(uint8_t* symbols, int count);
NewEvent<Address, MessageType, const std::string&> onMessage;
@ -43,6 +45,7 @@ namespace pocsag {
MessageType msgType;
std::string msg;
uint32_t lastMsgData;
char currChar = 0;
int currOffset = 0;
};
}

View File

@ -4,15 +4,15 @@ cd /root
# Install dependencies and tools
apt update
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libairspyhf-dev libairspy-dev \
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
libcodec2-dev autoconf libtool xxd
# Install SDRPlay libraries
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.12.1.run
7z x ./SDRplay_RSP_API-Linux-3.12.1.run
7z x ./SDRplay_RSP_API-Linux-3.12.1
cp x86_64/libsdrplay_api.so.3.12 /usr/lib/libsdrplay_api.so
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.14.0.run
7z x ./SDRplay_RSP_API-Linux-3.14.0.run
7z x ./SDRplay_RSP_API-Linux-3.14.0
cp x86_64/libsdrplay_api.so.3.14 /usr/lib/libsdrplay_api.so
cp inc/* /usr/include/
# Install libperseus

View File

@ -4,15 +4,15 @@ cd /root
# Install dependencies and tools
apt update
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libairspyhf-dev libairspy-dev \
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
libcodec2-dev autoconf libtool xxd
# Install SDRPlay libraries
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.12.1.run
7z x ./SDRplay_RSP_API-Linux-3.12.1.run
7z x ./SDRplay_RSP_API-Linux-3.12.1
cp x86_64/libsdrplay_api.so.3.12 /usr/lib/libsdrplay_api.so
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.14.0.run
7z x ./SDRplay_RSP_API-Linux-3.14.0.run
7z x ./SDRplay_RSP_API-Linux-3.14.0
cp x86_64/libsdrplay_api.so.3.14 /usr/lib/libsdrplay_api.so
cp inc/* /usr/include/
# Install libperseus

View File

@ -4,15 +4,15 @@ cd /root
# Install dependencies and tools
apt update
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk1-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk1-dev libzstd-dev libairspyhf-dev libairspy-dev \
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
libcodec2-dev autoconf libtool xxd
# Install SDRPlay libraries
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.12.1.run
7z x ./SDRplay_RSP_API-Linux-3.12.1.run
7z x ./SDRplay_RSP_API-Linux-3.12.1
cp x86_64/libsdrplay_api.so.3.12 /usr/lib/libsdrplay_api.so
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.14.0.run
7z x ./SDRplay_RSP_API-Linux-3.14.0.run
7z x ./SDRplay_RSP_API-Linux-3.14.0
cp x86_64/libsdrplay_api.so.3.14 /usr/lib/libsdrplay_api.so
cp inc/* /usr/include/
# Install libperseus

View File

@ -4,15 +4,15 @@ cd /root
# Install dependencies and tools
apt update
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk-dev libzstd-dev libairspyhf-dev libairspy-dev \
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
libcodec2-dev autoconf libtool xxd
# Install SDRPlay libraries
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.12.1.run
7z x ./SDRplay_RSP_API-Linux-3.12.1.run
7z x ./SDRplay_RSP_API-Linux-3.12.1
cp x86_64/libsdrplay_api.so.3.12 /usr/lib/libsdrplay_api.so
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.14.0.run
7z x ./SDRplay_RSP_API-Linux-3.14.0.run
7z x ./SDRplay_RSP_API-Linux-3.14.0
cp x86_64/libsdrplay_api.so.3.14 /usr/lib/libsdrplay_api.so
cp inc/* /usr/include/
# Install libperseus

View File

@ -10,15 +10,15 @@ echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://ap
apt update
# Install dependencies and tools
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk1-dev libzstd-dev libsoapysdr-dev libairspy-dev \
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk1-dev libzstd-dev libairspy-dev \
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
libcodec2-dev libudev-dev autoconf libtool xxd
# Install SDRPlay libraries
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.12.1.run
7z x ./SDRplay_RSP_API-Linux-3.12.1.run
7z x ./SDRplay_RSP_API-Linux-3.12.1
cp x86_64/libsdrplay_api.so.3.12 /usr/lib/libsdrplay_api.so
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.14.0.run
7z x ./SDRplay_RSP_API-Linux-3.14.0.run
7z x ./SDRplay_RSP_API-Linux-3.14.0
cp x86_64/libsdrplay_api.so.3.14 /usr/lib/libsdrplay_api.so
cp inc/* /usr/include/
# Install a more recent libusb version

View File

@ -4,15 +4,15 @@ cd /root
# Install dependencies and tools
apt update
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libairspyhf-dev libairspy-dev \
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
libcodec2-dev autoconf libtool xxd
# Install SDRPlay libraries
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.12.1.run
7z x ./SDRplay_RSP_API-Linux-3.12.1.run
7z x ./SDRplay_RSP_API-Linux-3.12.1
cp x86_64/libsdrplay_api.so.3.12 /usr/lib/libsdrplay_api.so
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.14.0.run
7z x ./SDRplay_RSP_API-Linux-3.14.0.run
7z x ./SDRplay_RSP_API-Linux-3.14.0
cp x86_64/libsdrplay_api.so.3.14 /usr/lib/libsdrplay_api.so
cp inc/* /usr/include/
# Install libperseus

View File

@ -4,15 +4,15 @@ cd /root
# Install dependencies and tools
apt update
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libairspyhf-dev libairspy-dev \
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
libcodec2-dev autoconf libtool xxd
# Install SDRPlay libraries
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.12.1.run
7z x ./SDRplay_RSP_API-Linux-3.12.1.run
7z x ./SDRplay_RSP_API-Linux-3.12.1
cp x86_64/libsdrplay_api.so.3.12 /usr/lib/libsdrplay_api.so
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.14.0.run
7z x ./SDRplay_RSP_API-Linux-3.14.0.run
7z x ./SDRplay_RSP_API-Linux-3.14.0
cp x86_64/libsdrplay_api.so.3.14 /usr/lib/libsdrplay_api.so
cp inc/* /usr/include/
# Install libperseus

View File

@ -4,15 +4,15 @@ cd /root
# Install dependencies and tools
apt update
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libairspy-dev \
apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk-dev libzstd-dev libairspyhf-dev libairspy-dev \
libiio-dev libad9361-dev librtaudio-dev libhackrf-dev librtlsdr-dev libbladerf-dev liblimesuite-dev p7zip-full wget portaudio19-dev \
libcodec2-dev autoconf libtool xxd
# Install SDRPlay libraries
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.12.1.run
7z x ./SDRplay_RSP_API-Linux-3.12.1.run
7z x ./SDRplay_RSP_API-Linux-3.12.1
cp x86_64/libsdrplay_api.so.3.12 /usr/lib/libsdrplay_api.so
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.14.0.run
7z x ./SDRplay_RSP_API-Linux-3.14.0.run
7z x ./SDRplay_RSP_API-Linux-3.14.0
cp x86_64/libsdrplay_api.so.3.14 /usr/lib/libsdrplay_api.so
cp inc/* /usr/include/
# Install libperseus

View File

@ -27,6 +27,7 @@ bundle_is_not_to_be_installed() {
if [ "$1" = "SystemConfiguration" ]; then echo 1; fi
if [ "$1" = "Security" ]; then echo 1; fi
if [ "$1" = "AppleFSCompression" ]; then echo 1; fi
if [ "$1" = "libsdrplay_api.so.3.14" ]; then echo 1; fi
}
# ========================= FOR INTERNAL USE ONLY =========================

View File

@ -45,7 +45,6 @@ bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/rtl_tcp_source/rtl_tcp_source.dylib
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/sdrplay_source/sdrplay_source.dylib
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/sdrpp_server_source/sdrpp_server_source.dylib
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/soapy_source/soapy_source.dylib
bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/spyserver_source/spyserver_source.dylib
# bundle_install_binary $BUNDLE $BUNDLE/Contents/Plugins $BUILD_DIR/source_modules/usrp_source/usrp_source.dylib

View File

@ -51,8 +51,6 @@ cp 'C:/Program Files/SDRplay/API/x64/sdrplay_api.dll' sdrpp_windows_x64/ -ErrorA
cp $build_dir/source_modules/sdrpp_server_source/Release/sdrpp_server_source.dll sdrpp_windows_x64/modules/
cp $build_dir/source_modules/soapy_source/Release/soapy_source.dll sdrpp_windows_x64/modules/
cp $build_dir/source_modules/spyserver_source/Release/spyserver_source.dll sdrpp_windows_x64/modules/
# cp $build_dir/source_modules/usrp_source/Release/usrp_source.dll sdrpp_windows_x64/modules/
@ -79,6 +77,8 @@ cp $build_dir/misc_modules/discord_integration/Release/discord_integration.dll s
cp $build_dir/misc_modules/frequency_manager/Release/frequency_manager.dll sdrpp_windows_x64/modules/
cp $build_dir/misc_modules/iq_exporter/Release/iq_exporter.dll sdrpp_windows_x64/modules/
cp $build_dir/misc_modules/recorder/Release/recorder.dll sdrpp_windows_x64/modules/
cp $build_dir/misc_modules/rigctl_client/Release/rigctl_client.dll sdrpp_windows_x64/modules/

View File

@ -485,7 +485,7 @@ private:
}
// Bookmark list
if (ImGui::BeginTable(("freq_manager_bkm_table" + _this->name).c_str(), 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, ImVec2(0, 200))) {
if (ImGui::BeginTable(("freq_manager_bkm_table" + _this->name).c_str(), 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, ImVec2(0, 200.0f * style::uiScale))) {
ImGui::TableSetupColumn("Name");
ImGui::TableSetupColumn("Bookmark");
ImGui::TableSetupScrollFreeze(2, 1);

View File

@ -408,9 +408,9 @@ private:
if (!_this->enabled) { ImGui::EndDisabled(); }
}
void setMode(Mode newMode, bool fromDisabled = false) {
void setMode(Mode newMode, bool forceSet = false) {
// If there is no mode to change, do nothing
if (!fromDisabled && mode == newMode) { return; }
if (!forceSet && mode == newMode) { return; }
// Stop the DSP
reshape.stop();
@ -421,14 +421,13 @@ private:
sigpath::vfoManager.deleteVFO(vfo);
vfo = NULL;
}
if (mode == MODE_BASEBAND && !fromDisabled) {
if (streamBound) {
sigpath::iqFrontEnd.unbindIQStream(&iqStream);
streamBound = false;
}
// If the mode was none, we're done
if (newMode == MODE_NONE) {
return;
}
if (newMode == MODE_NONE) { return; }
// Create VFO or bind IQ stream
if (newMode == MODE_VFO) {
@ -441,6 +440,7 @@ private:
else {
// Bind IQ stream
sigpath::iqFrontEnd.bindIQStream(&iqStream);
streamBound = true;
// Set its output as the input to the DSP
reshape.setInput(&iqStream);
@ -509,7 +509,7 @@ private:
size = sizeof(int16_t)*2;
break;
case SAMPLE_TYPE_INT32:
volk_32f_s32f_convert_32i((int32_t*)_this->buffer, (float*)data, (float)2147483647.0f, count*2);
volk_32f_s32f_convert_32i((int32_t*)_this->buffer, (float*)data, 2147483647.0f, count*2);
size = sizeof(int32_t)*2;
break;
case SAMPLE_TYPE_FLOAT32:
@ -555,6 +555,7 @@ private:
OptionList<int, int> packetSizes;
VFOManager::VFO* vfo = NULL;
bool streamBound = false;
dsp::stream<dsp::complex_t> iqStream;
dsp::buffer::Reshaper<dsp::complex_t> reshape;
dsp::sink::Handler<dsp::complex_t> handler;
@ -570,7 +571,7 @@ private:
MOD_EXPORT void _INIT_() {
json def = json({});
std::string root = (std::string)core::args["root"];
config.setPath(root + "/iq_exporter_config_config.json");
config.setPath(root + "/iq_exporter_config.json");
config.load(def);
config.enableAutoSave();
}

View File

@ -86,7 +86,7 @@ public:
}
// Switch source to panadapter mode
sigpath::sourceManager.setPanadpterIF(ifFreq);
sigpath::sourceManager.setPanadapterIF(ifFreq);
sigpath::sourceManager.setTuningMode(SourceManager::TuningMode::PANADAPTER);
sigpath::sourceManager.onRetune.bindHandler(&_retuneHandler);
@ -131,7 +131,7 @@ private:
ImGui::FillWidth();
if (ImGui::InputDouble(CONCAT("##_rigctl_if_freq_", _this->name), &_this->ifFreq, 100.0, 100000.0, "%.0f")) {
if (_this->running) {
sigpath::sourceManager.setPanadpterIF(_this->ifFreq);
sigpath::sourceManager.setPanadapterIF(_this->ifFreq);
}
config.acquire();
config.conf[_this->name]["ifFreq"] = _this->ifFreq;

View File

@ -334,7 +334,7 @@ private:
}
std::map<int, const char*> radioModeToString = {
{ RADIO_IFACE_MODE_NFM, "NFM" },
{ RADIO_IFACE_MODE_NFM, "FM" },
{ RADIO_IFACE_MODE_WFM, "WFM" },
{ RADIO_IFACE_MODE_AM, "AM" },
{ RADIO_IFACE_MODE_DSB, "DSB" },

View File

@ -89,7 +89,7 @@ private:
}
}
if (ImGui::BeginTable(("freq_manager_bkm_table" + _this->name).c_str(), 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, ImVec2(0, 200))) {
if (ImGui::BeginTable(("freq_manager_bkm_table" + _this->name).c_str(), 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, ImVec2(0, 200.0f * style::uiScale))) {
ImGui::TableSetupColumn("Name");
ImGui::TableSetupColumn("Countdown");
ImGui::TableSetupScrollFreeze(2, 1);

View File

@ -52,7 +52,7 @@ public:
}
}
if (ImGui::BeginTable("scheduler_task_triggers", 1, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, ImVec2(0, 100))) {
if (ImGui::BeginTable("scheduler_task_triggers", 1, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, ImVec2(0, 100.0f * style::uiScale))) {
ImGui::TableSetupColumn("Triggers");
ImGui::TableSetupScrollFreeze(1, 1);
ImGui::TableHeadersRow();
@ -65,7 +65,7 @@ public:
ImGui::EndTable();
}
if (ImGui::BeginTable("scheduler_task_actions", 1, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, ImVec2(0, 100))) {
if (ImGui::BeginTable("scheduler_task_actions", 1, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY, ImVec2(0, 100.0f * style::uiScale))) {
ImGui::TableSetupColumn("Actions");
ImGui::TableSetupScrollFreeze(1, 1);
ImGui::TableHeadersRow();

View File

@ -44,7 +44,7 @@ Download the latest release from [the Releases page](https://github.com/Alexandr
Then, run:
```sh
sudo apt install libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libsoapysdr-dev libairspyhf-dev libiio-dev libad9361-dev librtaudio-dev libhackrf-dev
sudo apt install libfftw3-dev libglfw3-dev libvolk2-dev libzstd-dev libairspyhf-dev libiio-dev libad9361-dev librtaudio-dev libhackrf-dev
sudo dpkg -i sdrpp_debian_amd64.deb
```
@ -135,7 +135,6 @@ As mentioned previously you need to edit `root_dev/config.json` to add the modul
"./build/radio/Release/radio.dll",
"./build/recorder/Release/recorder.dll",
"./build/rtl_tcp_source/Release/rtl_tcp_source.dll",
"./build/soapy_source/Release/soapy_source.dll",
"./build/audio_sink/Release/audio_sink.dll"
]
...
@ -166,7 +165,6 @@ The modules built will be some of the following (Repeat the instructions above f
* `build/recorder/Release/`
* `build/rtl_tcp_source/Release/`
* `build/spyserver_source/Release/`
* `build/soapy_source/Release/`
* `build/airspyhf_source/Release/`
* `build/plutosdr_source/Release/`
* `build/audio_sink/Release/`
@ -176,13 +174,9 @@ The modules built will be some of the following (Repeat the instructions above f
## Select which modules you wish to build
Depending on which module you want to build, you will need to install some additional dependencies.
Here are listed every module that requires addition dependencies. If a module enabled by default and you do not wish to install a particular dependency (or can't, eg. the BladeRF module on Debian Buster),
you can disable it using the module parameter listed in the table below
Please refer to the module list table further down in this readme for the names, dependencies and build options of each module.
* soapy_source: SoapySDR + drivers for each SDRs (see SoapySDR docs)
* airspyhf_source: libairspyhf
* plutosdr_source: libiio, libad9361
* audio_sink: librtaudio-dev
The build options are then passed to the cmake command as such `cmake .. -DOPTION_NAME_HERE=ON -DANOTHER_OPTION_HERE=OFF` etc...
## Install dependencies
@ -231,7 +225,6 @@ Then, you will need to edit the `root_dev/config.json` file to point to the modu
"./build/radio/radio.so",
"./build/recorder/recorder.so",
"./build/rtl_tcp_source/rtl_tcp_source.so",
"./build/soapy_source/soapy_source.so",
"./build/audio_sink/audio_sink.so"
]
...
@ -329,11 +322,13 @@ Modules in beta are still included in releases for the most part but not enabled
|----------------------|------------|-------------------|--------------------------------|:---------------:|:-----------------------:|:---------------------------:|
| airspy_source | Working | libairspy | OPT_BUILD_AIRSPY_SOURCE | ✅ | ✅ | ✅ |
| airspyhf_source | Working | libairspyhf | OPT_BUILD_AIRSPYHF_SOURCE | ✅ | ✅ | ✅ |
| audio_source | Working | rtaudio | OPT_BUILD_AUDIO_SOURCE | ✅ | ✅ | ✅ |
| bladerf_source | Working | libbladeRF | OPT_BUILD_BLADERF_SOURCE | ⛔ | ✅ (not Debian Buster) | ✅ |
| file_source | Working | - | OPT_BUILD_FILE_SOURCE | ✅ | ✅ | ✅ |
| hackrf_source | Working | libhackrf | OPT_BUILD_HACKRF_SOURCE | ✅ | ✅ | ✅ |
| hermes_source | Beta | - | OPT_BUILD_HERMES_SOURCE | ✅ | ✅ | ✅ |
| limesdr_source | Working | liblimesuite | OPT_BUILD_LIMESDR_SOURCE | ⛔ | ✅ | ✅ |
| network_source | Unfinished | - | OPT_BUILD_NETWORK_SOURCE | ✅ | ✅ | ⛔ |
| perseus_source | Beta | libperseus-sdr | OPT_BUILD_PERSEUS_SOURCE | ⛔ | ✅ | ✅ |
| plutosdr_source | Working | libiio, libad9361 | OPT_BUILD_PLUTOSDR_SOURCE | ✅ | ✅ | ✅ |
| rfspace_source | Working | - | OPT_BUILD_RFSPACE_SOURCE | ✅ | ✅ | ✅ |
@ -341,9 +336,9 @@ Modules in beta are still included in releases for the most part but not enabled
| rtl_tcp_source | Working | - | OPT_BUILD_RTL_TCP_SOURCE | ✅ | ✅ | ✅ |
| sdrplay_source | Working | SDRplay API | OPT_BUILD_SDRPLAY_SOURCE | ⛔ | ✅ | ✅ |
| sdrpp_server_source | Working | - | OPT_BUILD_SDRPP_SERVER_SOURCE | ✅ | ✅ | ✅ |
| soapy_source | Working | soapysdr | OPT_BUILD_SOAPY_SOURCE | ✅ | ✅ | ✅ |
| soapy_source | Deprecated | soapysdr | OPT_BUILD_SOAPY_SOURCE | ⛔ | ⛔ | ⛔ |
| spectran_source | Unfinished | RTSA Suite | OPT_BUILD_SPECTRAN_SOURCE | ⛔ | ⛔ | ⛔ |
| spectran_http_source | Unfinished | - | OPT_BUILD_SPECTRAN_HTTP_SOURCE | ✅ | ✅ | ⛔ |
| spectran_http_source | Beta | - | OPT_BUILD_SPECTRAN_HTTP_SOURCE | ✅ | ✅ | ⛔ |
| spyserver_source | Working | - | OPT_BUILD_SPYSERVER_SOURCE | ✅ | ✅ | ✅ |
| usrp_source | Beta | libuhd | OPT_BUILD_USRP_SOURCE | ⛔ | ⛔ | ⛔ |
@ -362,10 +357,9 @@ Modules in beta are still included in releases for the most part but not enabled
| Name | Stage | Dependencies | Option | Built by default| Built in Release | Enabled in SDR++ by default |
|---------------------|------------|--------------|-------------------------------|:---------------:|:----------------:|:---------------------------:|
| atv_decoder | Unfinished | - | OPT_BUILD_ATV_DECODER | ⛔ | ⛔ | ⛔ |
| dmr_decoder | Unfinished | - | OPT_BUILD_DMR_DECODER | ⛔ | ⛔ | ⛔ |
| falcon9_decoder | Unfinished | ffplay | OPT_BUILD_FALCON9_DECODER | ⛔ | ⛔ | ⛔ |
| kgsstv_decoder | Unfinished | - | OPT_BUILD_KGSSTV_DECODER | ⛔ | ⛔ | ⛔ |
| m17_decoder | Beta | - | OPT_BUILD_M17_DECODER | ⛔ | ✅ | ⛔ |
| m17_decoder | Working | - | OPT_BUILD_M17_DECODER | ⛔ | ✅ | ⛔ |
| meteor_demodulator | Working | - | OPT_BUILD_METEOR_DEMODULATOR | ✅ | ✅ | ⛔ |
| pager_decoder | Unfinished | - | OPT_BUILD_PAGER_DECODER | ⛔ | ⛔ | ⛔ |
| radio | Working | - | OPT_BUILD_RADIO | ✅ | ✅ | ✅ |
@ -377,7 +371,7 @@ Modules in beta are still included in releases for the most part but not enabled
|---------------------|------------|--------------|-----------------------------|:----------------:|:----------------:|:---------------------------:|
| discord_integration | Working | - | OPT_BUILD_DISCORD_PRESENCE | ✅ | ✅ | ⛔ |
| frequency_manager | Working | - | OPT_BUILD_FREQUENCY_MANAGER | ✅ | ✅ | ✅ |
| iq_exporter | Unfinished | - | OPT_BUILD_IQ_EXPORTER | ⛔ | ⛔ | ⛔ |
| iq_exporter | Working | - | OPT_BUILD_IQ_EXPORTER | ✅ | ✅ | ⛔ |
| recorder | Working | - | OPT_BUILD_RECORDER | ✅ | ✅ | ✅ |
| rigctl_client | Unfinished | - | OPT_BUILD_RIGCTL_CLIENT | ✅ | ✅ | ⛔ |
| rigctl_server | Working | - | OPT_BUILD_RIGCTL_SERVER | ✅ | ✅ | ✅ |
@ -433,6 +427,7 @@ I will soon publish a contributing.md listing the code style to use.
* Croccydile
* Dale L Puckett (K0HYD)
* [Daniele D'Agnelli](https://linkedin.com/in/dagnelli)
* [David Taylor (GM8ARV)](https://twitter.com/gm8arv)
* D. Jones
* Dexruus
* [EB3FRN](https://www.eb3frn.net/)
@ -460,6 +455,7 @@ I will soon publish a contributing.md listing the code style to use.
* Syne Ardwin (WI9SYN)
* [W4IPA](https://twitter.com/W4IPAstroke5)
* William Arcand (W1WRA)
* William Pitchford
* [Yves Rougy](https://www.twitch.tv/yorzian)
* [Zipper](https://github.com/reppiZ)

View File

@ -2,74 +2,290 @@
"name": "Germany",
"country_name": "Germany",
"country_code": "DE",
"author_name": "Manawyrm",
"author_name": "Manawyrm, LEDFlighter",
"author_url": "https://tbspace.de",
"bands": [
{
"name": "LW",
"name": "LW-Amateur",
"type": "amateur",
"start": 135700,
"end": 137800
},
{
"name": "630m",
"name": "LW-Broadcast",
"type": "broadcast",
"start": 148500,
"end": 283500
},
{
"name": "630m-Amateur",
"type": "amateur",
"start": 472000,
"end": 479000
},
{
"name": "160m",
"name": "MW-Broadcast",
"type": "broadcast",
"start": 526500,
"end": 1606500
},
{
"name": "160m-Amateur",
"type": "amateur",
"start": 1810000,
"end": 2000000
},
{
"name": "80m",
"name": "Maritime",
"type": "marine",
"start": 2045000,
"end": 2300000
},
{
"name": "120m-Broadcast",
"type": "broadcast",
"start": 2300000,
"end": 2495000
},
{
"name": "Aeronautical HF",
"type": "aviation",
"start": 2850000,
"end": 3155000
},
{
"name": "90m-Broadcast",
"type": "broadcast",
"start": 3200000,
"end": 3400000
},
{
"name": "Aeronautical HF",
"type": "aviation",
"start": 3400000,
"end": 3500000
},
{
"name": "80m-Amateur",
"type": "amateur",
"start": 3500000,
"end": 3800000
},
{
"name": "60m",
"name": "75m-Broadcast",
"type": "broadcast",
"start": 3900000,
"end": 4000000
},
{
"name": "Maritime",
"type": "marine",
"start": 4063000,
"end": 4438000
},
{
"name": "Aeronautical HF",
"type": "aviation",
"start": 4650000,
"end": 4750000
},
{
"name": "60m-Broadcast",
"type": "broadcast",
"start": 4750000,
"end": 5060000
},
{
"name": "60m-Amateur",
"type": "amateur",
"start": 5351500,
"end": 5366500
},
{
"name": "40m",
"name": "Aeronautical HF",
"type": "aviation",
"start": 5480000,
"end": 5730000
},
{
"name": "49m-Broadcast",
"type": "broadcast",
"start": 5900000,
"end": 6200000
},
{
"name": "Maritime",
"type": "marine",
"start": 6200000,
"end": 6525000
},
{
"name": "Aeronautical HF",
"type": "aviation",
"start": 6525000,
"end": 6765000
},
{
"name": "40m-Amateur",
"type": "amateur",
"start": 7000000,
"end": 7200000
},
{
"name": "30m",
"name": "41m-Broadcast",
"type": "broadcast",
"start": 7200000,
"end": 7450000
},
{
"name": "Maritime",
"type": "marine",
"start": 8195000,
"end": 8815000
},
{
"name": "31m-Broadcast",
"type": "broadcast",
"start": 9400000,
"end": 9900000
},
{
"name": "Aeronautical HF",
"type": "aviation",
"start": 8815000,
"end": 9040000
},
{
"name": "Aeronautical HF",
"type": "aviation",
"start": 10005000,
"end": 10100000
},
{
"name": "30m-Amateur",
"type": "amateur",
"start": 10100000,
"end": 10150000
},
{
"name": "20m",
"name": "Aeronautical HF",
"type": "aviation",
"start": 11175000,
"end": 11400000
},
{
"name": "25m-Broadcast",
"type": "broadcast",
"start": 11600000,
"end": 12100000
},
{
"name": "Maritime",
"type": "marine",
"start": 12230000,
"end": 13200000
},
{
"name": "Aeronautical HF",
"type": "aviation",
"start": 13200000,
"end": 13360000
},
{
"name": "22m-Broadcast",
"type": "broadcast",
"start": 13570000,
"end": 13870000
},
{
"name": "20m-Amateur",
"type": "amateur",
"start": 14000000,
"end": 14350000
},
{
"name": "17m",
"name": "Aeronautical HF",
"type": "aviation",
"start": 15010000,
"end": 15100000
},
{
"name": "Maritime",
"type": "marine",
"start": 16360000,
"end": 17410000
},
{
"name": "19m-Broadcast",
"type": "broadcast",
"start": 15100000,
"end": 15800000
},
{
"name": "16m-Broadcast",
"type": "broadcast",
"start": 17480000,
"end": 17900000
},
{
"name": "17m-Amateur",
"type": "amateur",
"start": 18068000,
"end": 18168000
},
{
"name": "15m",
"name": "Maritime - ship tx",
"type": "marine",
"start": 18780000,
"end": 18900000
},
{
"name": "15m-Broadcast",
"type": "broadcast",
"start": 18900000,
"end": 19020000
},
{
"name": "Maritime - coast tx",
"type": "marine",
"start": 19680000,
"end": 19990000
},
{
"name": "15m-Amateur",
"type": "amateur",
"start": 21000000,
"end": 21450000
},
{
"name": "12m",
"name": "13m-Broadcast",
"type": "broadcast",
"start": 21450000,
"end": 21850000
},
{
"name": "Aeronautical HF",
"type": "aviation",
"start": 21870000,
"end": 22000000
},
{
"name": "Aeronautical HF",
"type": "aviation",
"start": 23200000,
"end": 23350000
},
{
"name": "12m-Amateur",
"type": "amateur",
"start": 24890000,
"end": 24990000
},
{
"name": "11m-Broadcast",
"type": "broadcast",
"start": 25670000,
"end": 26100000
},
{
"name": "CB",
@ -78,31 +294,55 @@
"end": 27405000
},
{
"name": "10m",
"name": "10m-Amateur",
"type": "amateur",
"start": 28000000,
"end": 29700000
},
{
"name": "6m",
"name": "6m-Amateur",
"type": "amateur",
"start": 50030000,
"end": 51000000
},
{
"name": "4m",
"name": "4m-Amateur",
"type": "amateur",
"start": 70150000,
"end": 70200000
},
{
"name": "FM",
"name": "FM-Broadcast",
"type": "broadcast",
"start": 87500000,
"end": 108000000
},
{
"name": "2m",
"name": "Air Band VOR/ILS",
"type": "aviation",
"start": 108000000,
"end": 118000000
},
{
"name": "Air Band Voice",
"type": "aviation",
"start": 118000000,
"end": 136700000
},
{
"name": "Air Band CPDLC/Datalink",
"type": "aviation",
"start": 136700000,
"end": 137000000
},
{
"name": "Earth orbiting Satellites",
"type": "satellite",
"start": 137000000,
"end": 138000000
},
{
"name": "2m-Amateur",
"type": "amateur",
"start": 144000000,
"end": 146000000
@ -114,7 +354,49 @@
"end": 149115625
},
{
"name": "70cm",
"name": "Marine",
"type": "marine",
"start": 156000000,
"end": 162025000
},
{
"name": "Pager BOS",
"type": "other",
"start": 163000000,
"end": 174000000
},
{
"name": "DAB+ (digital broadcast)",
"type": "broadcast",
"start": 174000000,
"end": 225000000
},
{
"name": "Air Band Military",
"type": "military",
"start": 225000000,
"end": 380000000
},
{
"name": "TETRA BOS",
"type": "other",
"start": 388000000,
"end": 397000000
},
{
"name": "Weathersondes",
"type": "other",
"start": 401000000,
"end": 410000000
},
{
"name": "TETRA Civil",
"type": "other",
"start": 423000000,
"end": 430000000
},
{
"name": "70cm-Amateur",
"type": "amateur",
"start": 430000000,
"end": 440000000
@ -126,16 +408,58 @@
"end": 446196875
},
{
"name": "23cm",
"name": "Pager Civil",
"type": "other",
"start": 446500000,
"end": 470000000
},
{
"name": "DVB-T2 (TV)",
"type": "broadcast",
"start": 470000000,
"end": 690000000
},
{
"name": "868 MHz ISM-Devices",
"type": "other",
"start": 866500000,
"end": 871000000
},
{
"name": "23cm-Amateur",
"type": "amateur",
"start": 1240000000,
"end": 1300000000
},
{
"name": "13cm",
"name": "L-Band",
"type": "other",
"start": 1300000000,
"end": 2000000000
},
{
"name": "13cm-Amateur",
"type": "amateur",
"start": 2320000000,
"end": 2450000000
},
{
"name": "9cm-Amateur",
"type": "amateur",
"start": 3400000000,
"end": 3475000000
},
{
"name": "6cm-Amateur",
"type": "amateur",
"start": 5650000000,
"end": 5850000000
},
{
"name": "3cm-Amateur",
"type": "amateur",
"start": 10000000000,
"end": 10500000000
}
]
}

View File

@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.13)
project(network_source)
file(GLOB SRC "src/*.cpp")
include(${SDRPP_MODULE_CMAKE})

View File

@ -0,0 +1,366 @@
#include <utils/net.h>
#include <utils/flog.h>
#include <module.h>
#include <gui/gui.h>
#include <signal_path/signal_path.h>
#include <core.h>
#include <gui/style.h>
#include <config.h>
#include <gui/smgui.h>
#include <gui/widgets/stepped_slider.h>
#include <utils/optionlist.h>
#define CONCAT(a, b) ((std::string(a) + b).c_str())
SDRPP_MOD_INFO{
/* Name: */ "network_source",
/* Description: */ "UDP/TCP Source Module",
/* Author: */ "Ryzerth",
/* Version: */ 0, 1, 0,
/* Max instances */ 1
};
ConfigManager config;
enum Protocol {
PROTOCOL_TCP_SERVER,
PROTOCOL_TCP_CLIENT,
PROTOCOL_UDP
};
enum SampleType {
SAMPLE_TYPE_INT8,
SAMPLE_TYPE_INT16,
SAMPLE_TYPE_INT32,
SAMPLE_TYPE_FLOAT32
};
const size_t SAMPLE_TYPE_SIZE[] {
sizeof(int8_t)*2,
sizeof(int16_t)*2,
sizeof(int32_t)*2,
sizeof(float)*2,
};
class NetworkSourceModule : public ModuleManager::Instance {
public:
NetworkSourceModule(std::string name) {
this->name = name;
samplerate = 1000000.0;
handler.ctx = this;
handler.selectHandler = menuSelected;
handler.deselectHandler = menuDeselected;
handler.menuHandler = menuHandler;
handler.startHandler = start;
handler.stopHandler = stop;
handler.tuneHandler = tune;
handler.stream = &stream;
// Define samplerates
for (int i = 3000; i <= 192000; i <<= 1) {
samplerates.define(i, getSrScaled(i), i);
}
for (int i = 250000; i < 1000000; i += 250000) {
samplerates.define(i, getSrScaled(i), i);
}
for (int i = 1000000; i < 10000000; i += 500000) {
samplerates.define(i, getSrScaled(i), i);
}
for (int i = 10000000; i <= 100000000; i += 5000000) {
samplerates.define(i, getSrScaled(i), i);
}
// Define protocols
// protocols.define("TCP (Server)", PROTOCOL_TCP_SERVER);
protocols.define("TCP (Client)", PROTOCOL_TCP_CLIENT);
protocols.define("UDP", PROTOCOL_UDP);
// Define sample types
sampleTypes.define("Int8", SAMPLE_TYPE_INT8);
sampleTypes.define("Int16", SAMPLE_TYPE_INT16);
sampleTypes.define("Int32", SAMPLE_TYPE_INT32);
sampleTypes.define("Float32", SAMPLE_TYPE_FLOAT32);
// Load config
config.acquire();
if (config.conf[name].contains("samplerate")) {
int sr = config.conf[name]["samplerate"];
if (samplerates.keyExists(sr)) { samplerate = samplerates.value(samplerates.keyId(sr)); }
}
if (config.conf[name].contains("protocol")) {
std::string protoStr = config.conf[name]["protocol"];
if (protocols.keyExists(protoStr)) { proto = protocols.value(protocols.keyId(protoStr)); }
}
if (config.conf[name].contains("sampleType")) {
std::string sampTypeStr = config.conf[name]["sampleType"];
if (sampleTypes.keyExists(sampTypeStr)) { sampType = sampleTypes.value(sampleTypes.keyId(sampTypeStr)); }
}
if (config.conf[name].contains("host")) {
std::string hostStr = config.conf[name]["host"];
strcpy(hostname, hostStr.c_str());
}
if (config.conf[name].contains("port")) {
port = config.conf[name]["port"];
port = std::clamp<int>(port, 1, 65535);
}
config.release();
// Set menu IDs
srId = samplerates.valueId(samplerate);
protoId = protocols.valueId(proto);
sampTypeId = sampleTypes.valueId(sampType);
sigpath::sourceManager.registerSource("Network", &handler);
}
~NetworkSourceModule() {
stop(this);
sigpath::sourceManager.unregisterSource("Network");
}
void postInit() {}
void enable() {
enabled = true;
}
void disable() {
enabled = false;
}
bool isEnabled() {
return enabled;
}
private:
std::string getSrScaled(double sr) {
char buf[1024];
if (sr >= 1000000.0) {
sprintf(buf, "%.1lf MS/s", sr / 1000000.0);
}
else if (sr >= 1000.0) {
sprintf(buf, "%.1lf KS/s", sr / 1000.0);
}
else {
sprintf(buf, "%.1lf S/s", sr);
}
return std::string(buf);
}
static void menuSelected(void* ctx) {
NetworkSourceModule* _this = (NetworkSourceModule*)ctx;
core::setInputSampleRate(_this->samplerate);
flog::info("NetworkSourceModule '{0}': Menu Select!", _this->name);
}
static void menuDeselected(void* ctx) {
NetworkSourceModule* _this = (NetworkSourceModule*)ctx;
flog::info("NetworkSourceModule '{0}': Menu Deselect!", _this->name);
}
static void start(void* ctx) {
NetworkSourceModule* _this = (NetworkSourceModule*)ctx;
if (_this->running) { return; }
// Depends on protocol
try {
if (_this->proto == PROTOCOL_TCP_SERVER) {
// Create TCP listener
// TODO
// Start listen worker
// TODO
}
else if (_this->proto == PROTOCOL_TCP_CLIENT) {
// Connect to TCP server
_this->sock = net::connect(_this->hostname, _this->port);
}
else if (_this->proto == PROTOCOL_UDP) {
// Open UDP socket
_this->sock = net::openudp("0.0.0.0", _this->port, _this->hostname, _this->port, true);
}
}
catch (const std::exception& e) {
flog::error("Could not start Network Source: {}", e.what());
return;
}
// Start receive worker
_this->workerThread = std::thread(&NetworkSourceModule::worker, _this);
_this->running = true;
flog::info("NetworkSourceModule '{0}': Start!", _this->name);
}
static void stop(void* ctx) {
NetworkSourceModule* _this = (NetworkSourceModule*)ctx;
if (!_this->running) { return; }
// Stop listen worker
// TODO
// Close connection
if (_this->sock) { _this->sock->close(); }
// Stop worker thread
_this->stream.stopWriter();
if (_this->workerThread.joinable()) { _this->workerThread.join(); }
_this->stream.clearWriteStop();
_this->running = false;
flog::info("NetworkSourceModule '{0}': Stop!", _this->name);
}
static void tune(double freq, void* ctx) {
NetworkSourceModule* _this = (NetworkSourceModule*)ctx;
if (_this->running) {
// Nothing for now
}
_this->freq = freq;
flog::info("NetworkSourceModule '{0}': Tune: {1}!", _this->name, freq);
}
static void menuHandler(void* ctx) {
NetworkSourceModule* _this = (NetworkSourceModule*)ctx;
if (_this->running) { SmGui::BeginDisabled(); }
// Hostname and port field
if (ImGui::InputText(("##iq_exporter_host_" + _this->name).c_str(), _this->hostname, sizeof(_this->hostname))) {
config.acquire();
config.conf[_this->name]["host"] = _this->hostname;
config.release(true);
}
ImGui::SameLine();
ImGui::FillWidth();
if (ImGui::InputInt(("##iq_exporter_port_" + _this->name).c_str(), &_this->port, 0, 0)) {
_this->port = std::clamp<int>(_this->port, 1, 65535);
config.acquire();
config.conf[_this->name]["port"] = _this->port;
config.release(true);
}
// Samplerate selector
ImGui::LeftLabel("Samplerate");
ImGui::FillWidth();
if (ImGui::Combo(("##iq_exporter_sr_" + _this->name).c_str(), &_this->srId, _this->samplerates.txt)) {
_this->samplerate = _this->samplerates.value(_this->srId);
core::setInputSampleRate(_this->samplerate);
config.acquire();
config.conf[_this->name]["samplerate"] = _this->samplerates.key(_this->srId);
config.release(true);
}
// Mode protocol selector
ImGui::LeftLabel("Protocol");
ImGui::FillWidth();
if (ImGui::Combo(("##iq_exporter_proto_" + _this->name).c_str(), &_this->protoId, _this->protocols.txt)) {
_this->proto = _this->protocols.value(_this->protoId);
config.acquire();
config.conf[_this->name]["protocol"] = _this->protocols.key(_this->protoId);
config.release(true);
}
// Sample type selector
ImGui::LeftLabel("Sample type");
ImGui::FillWidth();
if (ImGui::Combo(("##iq_exporter_samp_" + _this->name).c_str(), &_this->sampTypeId, _this->sampleTypes.txt)) {
_this->sampType = _this->sampleTypes.value(_this->sampTypeId);
config.acquire();
config.conf[_this->name]["sampleType"] = _this->sampleTypes.key(_this->sampTypeId);
config.release(true);
}
if (_this->running) { SmGui::EndDisabled(); }
}
void worker() {
// Compute sizes
int blockSize = samplerate / 200;
int sampleSize = SAMPLE_TYPE_SIZE[sampType];
int frameSize = blockSize*sampleSize;
// Allocate receive buffer
uint8_t* buffer = dsp::buffer::alloc<uint8_t>(frameSize);
while (true) {
// Read samples from socket
int bytes = sock->recv(buffer, frameSize, true);
if (bytes <= 0) { break; }
// Convert to CF32 (note: problem if partial sample)
int count = bytes / sampleSize;
switch (sampType) {
case SAMPLE_TYPE_INT8:
volk_8i_s32f_convert_32f((float*)stream.writeBuf, (int8_t*)buffer, 128.0f, count*2);
break;
case SAMPLE_TYPE_INT16:
volk_16i_s32f_convert_32f((float*)stream.writeBuf, (int16_t*)buffer, 32768.0f, count*2);
break;
case SAMPLE_TYPE_INT32:
volk_32i_s32f_convert_32f((float*)stream.writeBuf, (int32_t*)buffer, 2147483647.0f, count*2);
break;
case SAMPLE_TYPE_FLOAT32:
memcpy(stream.writeBuf, buffer, bytes);
break;
default:
break;
}
// Send out converted samples
if (!stream.swap(count)) { break; }
}
// Free receive buffer
dsp::buffer::free(buffer);
}
std::string name;
bool enabled = true;
dsp::stream<dsp::complex_t> stream;
SourceManager::SourceHandler handler;
bool running = false;
double freq;
int samplerate = 1000000;
int srId;
Protocol proto = PROTOCOL_UDP;
int protoId;
SampleType sampType = SAMPLE_TYPE_INT16;
int sampTypeId;
char hostname[1024] = "localhost";
int port = 1234;
OptionList<int, int> samplerates;
OptionList<std::string, Protocol> protocols;
OptionList<std::string, SampleType> sampleTypes;
std::thread workerThread;
std::thread listenWorkerThread;
std::mutex sockMtx;
std::shared_ptr<net::Socket> sock;
std::shared_ptr<net::Listener> listener;
};
MOD_EXPORT void _INIT_() {
json def = json({});
config.setPath(core::args["root"].s() + "/network_source_config.json");
config.load(def);
config.enableAutoSave();
}
MOD_EXPORT ModuleManager::Instance* _CREATE_INSTANCE_(std::string name) {
return new NetworkSourceModule(name);
}
MOD_EXPORT void _DELETE_INSTANCE_(ModuleManager::Instance* instance) {
delete (NetworkSourceModule*)instance;
}
MOD_EXPORT void _END_() {
config.disableAutoSave();
config.save();
}

View File

@ -30,7 +30,7 @@ namespace server {
dctx = ZSTD_createDCtx();
// Initialize DSP
decompIn.setBufferSize((sizeof(dsp::complex_t) * STREAM_BUFFER_SIZE) + 8);
decompIn.setBufferSize(STREAM_BUFFER_SIZE*sizeof(dsp::complex_t) + 8);
decompIn.clearWriteStop();
decomp.init(&decompIn);
link.init(&decomp.out, output);
@ -42,8 +42,20 @@ namespace server {
// Ask for a UI
int res = getUI();
if (res == -1) { throw std::runtime_error("Timed out"); }
else if (res == -2) { throw std::runtime_error("Server busy"); }
if (res < 0) {
// Close client
close();
// Throw error
switch (res) {
case CONN_ERR_TIMEOUT:
throw std::runtime_error("Timed out");
case CONN_ERR_BUSY:
throw std::runtime_error("Server busy");
default:
throw std::runtime_error("Unknown error");
}
}
}
Client::~Client() {
@ -209,7 +221,7 @@ namespace server {
if (!decompIn.swap(r_pkt_hdr->size - sizeof(PacketHeader))) { break; }
}
else if (r_pkt_hdr->type == PACKET_TYPE_BASEBAND_COMPRESSED) {
size_t outCount = ZSTD_decompressDCtx(dctx, decompIn.writeBuf, STREAM_BUFFER_SIZE, r_pkt_data, r_pkt_hdr->size - sizeof(PacketHeader));
size_t outCount = ZSTD_decompressDCtx(dctx, decompIn.writeBuf, STREAM_BUFFER_SIZE*sizeof(dsp::complex_t)+8, r_pkt_data, r_pkt_hdr->size - sizeof(PacketHeader));
if (outCount) {
if (!decompIn.swap(outCount)) { break; }
};
@ -234,7 +246,7 @@ namespace server {
else {
if (!serverBusy) { flog::error("Timeout out after asking for UI"); };
waiter->handled();
return serverBusy ? -2 : -1;
return serverBusy ? CONN_ERR_BUSY : CONN_ERR_TIMEOUT;
}
waiter->handled();
return 0;

View File

@ -71,6 +71,11 @@ namespace server {
std::mutex handledMtx;
};
enum ConnectionError {
CONN_ERR_TIMEOUT = -1,
CONN_ERR_BUSY = -2
};
class Client {
public:
Client(std::shared_ptr<net::Socket> sock, dsp::stream<dsp::complex_t>* out);

View File

@ -81,8 +81,15 @@ public:
private:
void refresh() {
devList = SoapySDR::Device::enumerate();
txtDevList = "";
try {
devList = SoapySDR::Device::enumerate();
}
catch (const std::exception& e) {
flog::error("Could not list devices: {}", e.what());
return;
}
int i = 0;
for (auto& dev : devList) {
txtDevList += dev["label"] != "" ? dev["label"] : dev["driver"];
@ -153,7 +160,14 @@ private:
return;
}
SoapySDR::Device* dev = SoapySDR::Device::make(devArgs);
SoapySDR::Device* dev = NULL;
try {
dev = SoapySDR::Device::make(devArgs);
}
catch (const std::exception& e) {
flog::error("Could not open device: {}", e.what());
return;
}
antennaList = dev->listAntennas(SOAPY_SDR_RX, channelId);
txtAntennaList = "";
@ -307,7 +321,13 @@ private:
return;
}
try {
_this->dev = SoapySDR::Device::make(_this->devArgs);
}
catch (const std::exception& e) {
flog::error("Failed to open device: {}", e.what());
return;
}
_this->dev->setSampleRate(SOAPY_SDR_RX, _this->channelId, _this->sampleRate);

View File

@ -144,9 +144,7 @@ private:
_this->tryConnect();
}
else if (connected && SmGui::Button("Disconnect##spectran_http_source")) {
_this->client->onCenterFrequencyChanged.unbind(_this->onFreqChangedId);
_this->client->onCenterFrequencyChanged.unbind(_this->onSamplerateChangedId);
_this->client->close();
_this->disconnect();
}
if (_this->running) { style::endDisabled(); }
@ -173,6 +171,12 @@ private:
}
}
void disconnect() {
client->onCenterFrequencyChanged.unbind(onFreqChangedId);
client->onSamplerateChanged.unbind(onSamplerateChangedId);
client->close();
}
void onFreqChanged(double newFreq) {
if (lastReportedFreq == newFreq) { return; }
lastReportedFreq = newFreq;

View File

@ -11,12 +11,15 @@ SpectranHTTPClient::SpectranHTTPClient(std::string host, int port, dsp::stream<d
sock = net::connect(host, port);
http = net::http::Client(sock);
// Make request
// Send sttream request
net::http::RequestHeader rqhdr(net::http::METHOD_GET, "/stream?format=float32", host);
http.sendRequestHeader(rqhdr);
// Receive for response
net::http::ResponseHeader rshdr;
http.recvResponseHeader(rshdr, 5000);
// Check the status
if (rshdr.getStatusCode() != net::http::STATUS_CODE_OK) {
flog::error("HTTP request did not return ok: {}", rshdr.getStatusString());
throw std::runtime_error("HTTP request did not return ok");
@ -48,20 +51,29 @@ void SpectranHTTPClient::setCenterFrequency(uint64_t freq) {
auto controlSock = net::connect(host, port);
auto controlHttp = net::http::Client(controlSock);
// Make request
net::http::RequestHeader rqhdr(net::http::METHOD_PUT, "/control", host);
// Encode request body
net::http::RequestHeader rqhdr(net::http::METHOD_PUT, "/remoteconfig", host);
char buf[1024];
sprintf(buf, "{\"frequencyCenter\":%" PRIu64 ",\"frequencySpan\":%" PRIu64 ",\"type\":\"capture\"}", freq, _samplerate);
sprintf(buf, "{\"receiverName\": \"Block_IQDemodulator_0\", \"simpleconfig\": {\"main\": {\"centerfreq\": %" PRIu64 ", \"samplerate\": %" PRIu64 ", \"spanfreq\": %" PRIu64 "}}}", freq, _samplerate, _samplerate);
std::string data = buf;
char lenBuf[16];
sprintf(lenBuf, "%" PRIu64, (uint64_t)data.size());
// Setup request headers
rqhdr.setField("Content-Length", lenBuf);
// Send request
controlHttp.sendRequestHeader(rqhdr);
controlSock->sendstr(data);
// Receive response
net::http::ResponseHeader rshdr;
controlHttp.recvResponseHeader(rshdr, 5000);
// Log error if there is one
if (rshdr.getStatusCode() < 200 || rshdr.getStatusCode() >= 300) {
flog::debug("Response: {}", rshdr.getStatusString());
}
}
void SpectranHTTPClient::worker() {
@ -101,11 +113,10 @@ void SpectranHTTPClient::worker() {
auto sampleFreqEnd = jsonData.find(',', sampleFreqBegin);
std::string sampleFreqStr = jsonData.substr(sampleFreqBegin + 18, sampleFreqEnd - sampleFreqBegin - 18);
sampleFreq = std::stoll(sampleFreqStr);
//flog::debug("{}", jsonData);
}
// Calculate and update center freq
int64_t samplerate = /* sampleFreqReceived ? sampleFreq : */(endFreq - startFreq);
int64_t samplerate = sampleFreqReceived ? sampleFreq : (endFreq - startFreq);
int64_t centerFreq = round(((double)endFreq + (double)startFreq) / 2.0);
if (centerFreq != _centerFreq) {
flog::debug("New center freq: {}", centerFreq);

View File

@ -78,6 +78,10 @@ public:
std::string serial = devAddr["serial"];
std::string model = devAddr.has_key("product") ? devAddr["product"] : devAddr["type"];
sprintf(buf, "USRP %s [%s]", model.c_str(), serial.c_str());
// Work-around for UHD sometimes reporting the same device twice
if (devices.keyExists(serial)) { continue; }
devices.define(serial, buf, devAddr);
}
}
@ -107,7 +111,7 @@ public:
channels.clear();
auto subdevs = dev->get_rx_subdev_spec();
for (int i = 0; i < subdevs.size(); i++) {
std::string slot = subdevs[i].db_name;
std::string slot = subdevs[i].db_name + ',' + subdevs[i].sd_name;
sprintf(buf, "%s [%s]", dev->get_rx_subdev_name(i).c_str(), slot.c_str());
channels.define(buf, buf, buf);
}