kopia lustrzana https://github.com/AlexandreRouma/SDRPlusPlus
Porównaj commity
9 Commity
c0a84f8703
...
2b752bb267
Autor | SHA1 | Data |
---|---|---|
AlexandreRouma | 2b752bb267 | |
AlexandreRouma | 5204cfec56 | |
AlexandreRouma | c616892eda | |
AlexandreRouma | 5f23c1f312 | |
AlexandreRouma | 5e0c4449f8 | |
AlexandreRouma | cd3e2b6c05 | |
AlexandreRouma | ba5380f9bb | |
AlexandreRouma | daf0f8c159 | |
AlexandreRouma | 63aa45de9e |
|
@ -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
|
||||
|
@ -138,6 +138,60 @@ 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: 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
|
||||
|
||||
- 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.12.1.pkg && sudo installer -pkg SDRplayAPI-macos-installer-universal-3.12.1.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_SOAPY_SOURCE=OFF -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_AUDIO_SINK=OFF -DOPT_BUILD_PORTAUDIO_SINK=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=OFF -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 +401,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 +413,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 &&
|
||||
|
|
|
@ -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)
|
||||
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
class POCSAGDecoder : public Decoder {
|
||||
public:
|
||||
POCSAGDecoder(const std::string& name, VFOManager::VFO* vfo) : diag(0.6, BAUDRATE) {
|
||||
POCSAGDecoder(const std::string& name, VFOManager::VFO* vfo) : diag(0.6, 544) {
|
||||
this->name = name;
|
||||
this->vfo = vfo;
|
||||
|
||||
|
@ -26,7 +26,7 @@ public:
|
|||
vfo->setBandwidthLimits(12500, 12500, true);
|
||||
vfo->setSampleRate(SAMPLERATE, 12500);
|
||||
dsp.init(vfo->output, SAMPLERATE, BAUDRATE);
|
||||
reshape.init(&dsp.soft, BAUDRATE, (BAUDRATE / 30.0) - BAUDRATE);
|
||||
reshape.init(&dsp.soft, 544, 0);
|
||||
dataHandler.init(&dsp.out, _dataHandler, this);
|
||||
diagHandler.init(&reshape.out, _diagHandler, this);
|
||||
|
||||
|
|
|
@ -11,6 +11,89 @@
|
|||
#include <dsp/digital/binary_slicer.h>
|
||||
#include <dsp/routing/doubler.h>
|
||||
|
||||
#include "packet_clock_sync.h"
|
||||
|
||||
inline float PATTERN_DSDSDZED[] = {
|
||||
-1.00000000e+00, -8.00000000e-01, -6.00000000e-01, -4.00000000e-01,
|
||||
-2.00000000e-01, -2.77555756e-17, 2.00000000e-01, 4.00000000e-01,
|
||||
6.00000000e-01, 8.00000000e-01, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 8.00000000e-01,
|
||||
6.00000000e-01, 4.00000000e-01, 2.00000000e-01, 2.77555756e-17,
|
||||
-2.00000000e-01, -4.00000000e-01, -6.00000000e-01, -8.00000000e-01,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -8.00000000e-01,
|
||||
-6.00000000e-01, -4.00000000e-01, -2.00000000e-01, -2.77555756e-17,
|
||||
2.00000000e-01, 4.00000000e-01, 6.00000000e-01, 8.00000000e-01,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 8.00000000e-01,
|
||||
6.00000000e-01, 4.00000000e-01, 2.00000000e-01, 2.77555756e-17,
|
||||
-2.00000000e-01, -4.00000000e-01, -6.00000000e-01, -8.00000000e-01,
|
||||
-1.00000000e+00, -8.00000000e-01, -6.00000000e-01, -4.00000000e-01,
|
||||
-2.00000000e-01, -2.77555756e-17, 2.00000000e-01, 4.00000000e-01,
|
||||
6.00000000e-01, 8.00000000e-01, 1.00000000e+00, 8.00000000e-01,
|
||||
6.00000000e-01, 4.00000000e-01, 2.00000000e-01, 2.77555756e-17,
|
||||
-2.00000000e-01, -4.00000000e-01, -6.00000000e-01, -8.00000000e-01,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -8.00000000e-01,
|
||||
-6.00000000e-01, -4.00000000e-01, -2.00000000e-01, -2.77555756e-17,
|
||||
2.00000000e-01, 4.00000000e-01, 6.00000000e-01, 8.00000000e-01,
|
||||
1.00000000e+00, 8.00000000e-01, 6.00000000e-01, 4.00000000e-01,
|
||||
2.00000000e-01, 2.77555756e-17, -2.00000000e-01, -4.00000000e-01,
|
||||
-6.00000000e-01, -8.00000000e-01, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -8.00000000e-01, -6.00000000e-01, -4.00000000e-01,
|
||||
-2.00000000e-01, -2.77555756e-17, 2.00000000e-01, 4.00000000e-01,
|
||||
6.00000000e-01, 8.00000000e-01, 1.00000000e+00, 8.00000000e-01,
|
||||
6.00000000e-01, 4.00000000e-01, 2.00000000e-01, 2.77555756e-17,
|
||||
-2.00000000e-01, -4.00000000e-01, -6.00000000e-01, -8.00000000e-01,
|
||||
-1.00000000e+00, -8.00000000e-01, -6.00000000e-01, -4.00000000e-01,
|
||||
-2.00000000e-01, -2.77555756e-17, 2.00000000e-01, 4.00000000e-01,
|
||||
6.00000000e-01, 8.00000000e-01, 1.00000000e+00, 8.00000000e-01,
|
||||
6.00000000e-01, 4.00000000e-01, 2.00000000e-01, 2.77555756e-17,
|
||||
-2.00000000e-01, -4.00000000e-01, -6.00000000e-01, -8.00000000e-01,
|
||||
-1.00000000e+00, -8.00000000e-01, -6.00000000e-01, -4.00000000e-01,
|
||||
-2.00000000e-01, -2.77555756e-17, 2.00000000e-01, 4.00000000e-01,
|
||||
6.00000000e-01, 8.00000000e-01, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 8.00000000e-01,
|
||||
6.00000000e-01, 4.00000000e-01, 2.00000000e-01, 2.77555756e-17,
|
||||
-2.00000000e-01, -4.00000000e-01, -6.00000000e-01, -8.00000000e-01,
|
||||
-1.00000000e+00, -8.00000000e-01, -6.00000000e-01, -4.00000000e-01,
|
||||
-2.00000000e-01, -2.77555756e-17, 2.00000000e-01, 4.00000000e-01,
|
||||
6.00000000e-01, 8.00000000e-01, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
||||
1.00000000e+00, 8.00000000e-01, 6.00000000e-01, 4.00000000e-01,
|
||||
2.00000000e-01, 2.77555756e-17, -2.00000000e-01, -4.00000000e-01,
|
||||
-6.00000000e-01, -8.00000000e-01, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
||||
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00
|
||||
};
|
||||
|
||||
class POCSAGDSP : public dsp::Processor<dsp::complex_t, uint8_t> {
|
||||
using base_type = dsp::Processor<dsp::complex_t, uint8_t>;
|
||||
public:
|
||||
|
@ -27,7 +110,9 @@ public:
|
|||
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, 1e-4, 1.0, 0.05);
|
||||
//recov.init(NULL, samplerate/baudrate, 1e-4, 1.0, 0.05);
|
||||
|
||||
cs.init(NULL, PATTERN_DSDSDZED, sizeof(PATTERN_DSDSDZED)/sizeof(float), 544, 10);
|
||||
|
||||
// Free useless buffers
|
||||
// dcBlock.out.free();
|
||||
|
@ -42,8 +127,11 @@ public:
|
|||
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);
|
||||
//count = recov.process(count, demod.out.readBuf, softOut);
|
||||
|
||||
count = cs.process(count, demod.out.readBuf, softOut);
|
||||
|
||||
//dsp::digital::BinarySlicer::process(count, softOut, out);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -58,8 +146,10 @@ public:
|
|||
count = process(count, base_type::_in->readBuf, soft.writeBuf, base_type::out.writeBuf);
|
||||
|
||||
base_type::_in->flush();
|
||||
if (!base_type::out.swap(count)) { return -1; }
|
||||
if (!soft.swap(count)) { return -1; }
|
||||
//if (!base_type::out.swap(count)) { return -1; }
|
||||
|
||||
if (count) { if (!soft.swap(count)) { return -1; } }
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -72,4 +162,6 @@ private:
|
|||
dsp::filter::FIR<float, float> fir;
|
||||
dsp::clock_recovery::MM<float> recov;
|
||||
|
||||
dsp::PacketClockSync cs;
|
||||
|
||||
};
|
|
@ -0,0 +1,221 @@
|
|||
#pragma once
|
||||
#include <dsp/stream.h>
|
||||
#include <dsp/buffer/reshaper.h>
|
||||
#include <dsp/multirate/rational_resampler.h>
|
||||
#include <dsp/sink/handler_sink.h>
|
||||
#include <dsp/demod/quadrature.h>
|
||||
#include <dsp/clock_recovery/mm.h>
|
||||
#include <dsp/taps/root_raised_cosine.h>
|
||||
#include <dsp/correction/dc_blocker.h>
|
||||
#include <dsp/loop/fast_agc.h>
|
||||
#include <dsp/digital/binary_slicer.h>
|
||||
#include <dsp/routing/doubler.h>
|
||||
#include <utils/flog.h>
|
||||
#include <fftw3.h>
|
||||
#include <dsp/math/conjugate.h>
|
||||
#include <dsp/math/normalize_phase.h>
|
||||
|
||||
namespace dsp {
|
||||
class PacketClockSync : public dsp::Processor<float, float> {
|
||||
using base_type = dsp::Processor<float, float>;
|
||||
public:
|
||||
PacketClockSync() {}
|
||||
PacketClockSync(dsp::stream<float>* in, float* pattern, int patternLen, int frameLen, float sampsPerSym, float threshold = 0.4f) { init(in, pattern, patternLen, frameLen, sampsPerSym, threshold); }
|
||||
|
||||
// TODO: Free in destroyer
|
||||
|
||||
void init(dsp::stream<float>* in, float* pattern, int patternLen, int frameLen, float sampsPerSym, float threshold = 0.4f) {
|
||||
// Compute the required FFT size and associated delay length
|
||||
fftSize = 512;// TODO: Find smallest power of 2 that fits patternLen
|
||||
delayLen = fftSize - 1;
|
||||
|
||||
// Allocate buffers
|
||||
buffer = dsp::buffer::alloc<float>(STREAM_BUFFER_SIZE+delayLen);
|
||||
bufferStart = &buffer[delayLen];
|
||||
this->pattern = dsp::buffer::alloc<float>(patternLen);
|
||||
patternFFT = dsp::buffer::alloc<complex_t>(fftSize);
|
||||
patternFFTAmps = dsp::buffer::alloc<float>(fftSize);
|
||||
fftIn = fftwf_alloc_real(fftSize);
|
||||
fftOut = (complex_t*)fftwf_alloc_complex(fftSize);
|
||||
|
||||
// Copy parameters
|
||||
memcpy(this->pattern, pattern, patternLen*sizeof(float));
|
||||
this->sampsPerSym = sampsPerSym;
|
||||
this->threshold = threshold;
|
||||
this->patternLen = patternLen;
|
||||
this->frameLen = frameLen;
|
||||
|
||||
// Plan FFT
|
||||
plan = fftwf_plan_dft_r2c_1d(fftSize, fftIn, (fftwf_complex*)fftOut, FFTW_ESTIMATE);
|
||||
|
||||
// Pre-compute pattern conjugated FFT
|
||||
// TODO: Offset the pattern to avoid it being cut off (EXTREMELY IMPORTANT)
|
||||
memcpy(fftIn, pattern, patternLen*sizeof(float));
|
||||
memset(&fftIn[patternLen], 0, (fftSize-patternLen)*sizeof(float));
|
||||
fftwf_execute(plan);
|
||||
volk_32fc_conjugate_32fc((lv_32fc_t*)patternFFT, (lv_32fc_t*)fftOut, fftSize);
|
||||
|
||||
// Compute amplitudes of the pattern FFT
|
||||
volk_32fc_magnitude_32f(patternFFTAmps, (lv_32fc_t*)patternFFT, fftSize);
|
||||
|
||||
// Normalize the amplitudes
|
||||
float maxAmp = 0.0f;
|
||||
for (int i = 0; i < fftSize/2; i++) {
|
||||
if (patternFFTAmps[i] > maxAmp) { maxAmp = patternFFTAmps[i]; }
|
||||
}
|
||||
volk_32f_s32f_multiply_32f(patternFFTAmps, patternFFTAmps, 1.0f/maxAmp, fftSize);
|
||||
|
||||
// Initialize the phase control loop
|
||||
float omegaRelLimit = 0.05;
|
||||
pcl.init(1, 10e-4, 0.0, 0.0, 1.0, sampsPerSym, sampsPerSym * (1.0 - omegaRelLimit), sampsPerSym * (1.0 + omegaRelLimit));
|
||||
generateInterpTaps();
|
||||
|
||||
// Init base
|
||||
base_type::init(in);
|
||||
}
|
||||
|
||||
int process(int count, float* in, float* out) {
|
||||
// Copy to buffer
|
||||
memcpy(bufferStart, in, count * sizeof(float));
|
||||
|
||||
int outCount = 0;
|
||||
|
||||
for (int i = 0; i < count;) {
|
||||
// Run clock recovery if needed
|
||||
while (toRead) {
|
||||
// Interpolate symbol
|
||||
float symbol;
|
||||
int phase = std::clamp<int>(floorf(pcl.phase * (float)interpPhaseCount), 0, interpPhaseCount - 1);
|
||||
volk_32f_x2_dot_prod_32f(&symbol, &buffer[offsetInt], interpBank.phases[phase], interpTapCount);
|
||||
out[outCount++] = symbol;
|
||||
|
||||
// Compute symbol phase error
|
||||
float error = (math::step(lastSymbol) * symbol) - (lastSymbol * math::step(symbol));
|
||||
lastSymbol = symbol;
|
||||
|
||||
// Clamp symbol phase error
|
||||
if (error > 1.0f) { error = 1.0f; }
|
||||
if (error < -1.0f) { error = -1.0f; }
|
||||
|
||||
// Advance symbol offset and phase
|
||||
pcl.advance(error);
|
||||
float delta = floorf(pcl.phase);
|
||||
offsetInt += delta;
|
||||
i = offsetInt;
|
||||
pcl.phase -= delta;
|
||||
|
||||
// Decrement read counter
|
||||
toRead--;
|
||||
|
||||
if (offsetInt >= count) {
|
||||
offsetInt -= count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Measure correlation to the sync pattern
|
||||
float corr;
|
||||
volk_32f_x2_dot_prod_32f(&corr, &buffer[i], pattern, patternLen);
|
||||
|
||||
// If not correlated enough, go to next sample. Otherwise continue with fine detection
|
||||
if (corr/(float)patternLen < threshold) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Copy samples into FFT input (only the part where we think the pattern is located)
|
||||
// TODO: Instead, check the interval onto which correlation occurs to determine where the pattern is located (IMPORTANT)
|
||||
memcpy(fftIn, &buffer[i], patternLen*sizeof(float));
|
||||
|
||||
// Compute FFT
|
||||
fftwf_execute(plan);
|
||||
|
||||
// Multiply with the conjugated pattern FFT to get the phase offset at each frequency
|
||||
volk_32fc_x2_multiply_32fc((lv_32fc_t*)fftOut, (lv_32fc_t*)fftOut, (lv_32fc_t*)patternFFT, fftSize);
|
||||
|
||||
// Compute the average phase delay rate
|
||||
float last = 0;
|
||||
float rateIntegral = 0;
|
||||
for (int j = 1; j < fftSize/2; j++) {
|
||||
// Compute instantanous rate
|
||||
float currentPhase = fftOut[j].phase();
|
||||
float instantRate = dsp::math::normalizePhase(currentPhase - last);
|
||||
last = currentPhase;
|
||||
|
||||
// Compute current rate guess
|
||||
float rateGuess = rateIntegral / (float)j;
|
||||
|
||||
// Update the rate integral as a weighted average of the current guess and measured rate depending on pattern amplitude
|
||||
rateIntegral += patternFFTAmps[j]*instantRate + (1.0f-patternFFTAmps[j])*rateGuess;
|
||||
}
|
||||
float avgRate = 1.14f*rateIntegral/(float)(fftSize/2);
|
||||
|
||||
// Compute the total offset
|
||||
float offset = (float)i - avgRate*(float)fftSize/(2.0f*FL_M_PI);
|
||||
flog::debug("Detected: {} -> {}", i, offset);
|
||||
|
||||
// Initialize clock recovery
|
||||
offsetInt = floorf(offset) - 3; // TODO: Will be negative sometimes, has to be taken into account
|
||||
pcl.phase = offset - (float)floorf(offset);
|
||||
pcl.freq = sampsPerSym;
|
||||
|
||||
// Start reading symbols
|
||||
toRead = frameLen;
|
||||
}
|
||||
|
||||
// Move unused data
|
||||
memmove(buffer, &buffer[count], delayLen * sizeof(float));
|
||||
|
||||
return outCount;
|
||||
}
|
||||
|
||||
int run() {
|
||||
int count = base_type::_in->read();
|
||||
if (count < 0) { return -1; }
|
||||
|
||||
count = process(count, base_type::_in->readBuf, base_type::out.writeBuf);
|
||||
|
||||
base_type::_in->flush();
|
||||
if (count) {
|
||||
if (!base_type::out.swap(count)) { return -1; }
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private:
|
||||
void generateInterpTaps() {
|
||||
double bw = 0.5 / (double)interpPhaseCount;
|
||||
dsp::tap<float> lp = dsp::taps::windowedSinc<float>(interpPhaseCount * interpTapCount, dsp::math::hzToRads(bw, 1.0), dsp::window::nuttall, interpPhaseCount);
|
||||
interpBank = dsp::multirate::buildPolyphaseBank<float>(interpPhaseCount, lp);
|
||||
taps::free(lp);
|
||||
}
|
||||
|
||||
int delayLen;
|
||||
float* buffer = NULL;
|
||||
float* bufferStart = NULL;
|
||||
float* pattern = NULL;
|
||||
int patternLen;
|
||||
bool locked;
|
||||
int fftSize;
|
||||
int frameLen;
|
||||
float threshold;
|
||||
|
||||
float* fftIn = NULL;
|
||||
complex_t* fftOut = NULL;
|
||||
fftwf_plan plan;
|
||||
|
||||
complex_t* patternFFT;
|
||||
float* patternFFTAmps;
|
||||
|
||||
float sampsPerSym;
|
||||
int toRead = 0;
|
||||
|
||||
loop::PhaseControlLoop<float, false> pcl;
|
||||
dsp::multirate::PolyphaseBank<float> interpBank;
|
||||
int interpTapCount = 8;
|
||||
int interpPhaseCount = 128;
|
||||
float lastSymbol = 0.0f;
|
||||
int offsetInt;
|
||||
};
|
||||
}
|
|
@ -334,6 +334,7 @@ Modules in beta are still included in releases for the most part but not enabled
|
|||
| 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 | ✅ | ✅ | ✅ |
|
||||
|
@ -432,6 +433,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/)
|
||||
|
@ -459,6 +461,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)
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
cmake_minimum_required(VERSION 3.13)
|
||||
project(network_source)
|
||||
|
||||
file(GLOB SRC "src/*.cpp")
|
||||
|
||||
include(${SDRPP_MODULE_CMAKE})
|
|
@ -0,0 +1,334 @@
|
|||
#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
|
||||
};
|
||||
|
||||
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; }
|
||||
|
||||
// TODO
|
||||
|
||||
_this->running = true;
|
||||
flog::info("NetworkSourceModule '{0}': Start!", _this->name);
|
||||
}
|
||||
|
||||
static void stop(void* ctx) {
|
||||
NetworkSourceModule* _this = (NetworkSourceModule*)ctx;
|
||||
if (!_this->running) { return; }
|
||||
|
||||
// TODO
|
||||
|
||||
_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() {
|
||||
int frameSize = samplerate / 200;
|
||||
switch (sampType) {
|
||||
case SAMPLE_TYPE_INT8:
|
||||
frameSize *= 2*sizeof(int8_t);;
|
||||
break;
|
||||
case SAMPLE_TYPE_INT16:
|
||||
frameSize *= 2*sizeof(int16_t);
|
||||
break;
|
||||
case SAMPLE_TYPE_INT32:
|
||||
frameSize *= 2*sizeof(int32_t);
|
||||
break;
|
||||
case SAMPLE_TYPE_FLOAT32:
|
||||
frameSize *= sizeof(dsp::complex_t);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
uint8_t* buffer = dsp::buffer::alloc<uint8_t>(STREAM_BUFFER_SIZE*sizeof(uint32_t));
|
||||
|
||||
while (true) {
|
||||
// Read samples from socket
|
||||
int bytes = sock->recv(buffer, frameSize, true);
|
||||
|
||||
// Convert to CF32
|
||||
int count;
|
||||
switch (sampType) {
|
||||
case SAMPLE_TYPE_INT8:
|
||||
frameSize *= 2*sizeof(int8_t);;
|
||||
break;
|
||||
case SAMPLE_TYPE_INT16:
|
||||
frameSize *= 2*sizeof(int16_t);
|
||||
break;
|
||||
case SAMPLE_TYPE_INT32:
|
||||
frameSize *= 2*sizeof(int32_t);
|
||||
break;
|
||||
case SAMPLE_TYPE_FLOAT32:
|
||||
//memcpy(stream.writeBuf, buffer, )
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Send out converted samples
|
||||
//if (!stream.swap(bufferSize))
|
||||
}
|
||||
|
||||
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_TCP_SERVER;
|
||||
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 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();
|
||||
}
|
Ładowanie…
Reference in New Issue