kopia lustrzana https://github.com/AlexandreRouma/SDRPlusPlus
Porównaj commity
27 Commity
eab4264604
...
11a7c382e8
Autor | SHA1 | Data |
---|---|---|
AlexandreRouma | 11a7c382e8 | |
AlexandreRouma | 54276177ae | |
AlexandreRouma | e6a02a3944 | |
AlexandreRouma | 00e6832055 | |
AlexandreRouma | bc8baca190 | |
AlexandreRouma | 08e75b6d14 | |
AlexandreRouma | e9ec79f6ef | |
AlexandreRouma | cd996292bc | |
AlexandreRouma | 06b7ad5c98 | |
AlexandreRouma | 38a95b4011 | |
AlexandreRouma | f6052d913a | |
AlexandreRouma | 2b00370cf3 | |
AlexandreRouma | 09f4071803 | |
AlexandreRouma | e61ef29e0f | |
AlexandreRouma | eb36f86d41 | |
AlexandreRouma | 29889a289f | |
AlexandreRouma | 859af77bd3 | |
Davide Rovelli | 0a3d1de02f | |
AlexandreRouma | db3fbd2975 | |
AlexandreRouma | f5adc7c587 | |
AlexandreRouma | 255988ee46 | |
AlexandreRouma | 68bf2fc16f | |
AlexandreRouma | 3aa167701e | |
AlexandreRouma | 97c1a132a5 | |
AlexandreRouma | 118e56897c | |
AlexandreRouma | af8c085d43 | |
Davide Rovelli | 708f74e179 |
|
@ -7,6 +7,8 @@ assignees: ''
|
|||
|
||||
---
|
||||
|
||||
# WARNING: Filling out the template below is NOT optional. Issues not filling out this template will be closed without review.
|
||||
|
||||
FIRST: Before reporting any bug, make sure that the bug you are reporting has not been reported before. Also, try to use the [nightly version](https://www.sdrpp.org/nightly) if possible in case I've already fixed the bug.
|
||||
|
||||
**Hardware**
|
||||
|
|
|
@ -18,7 +18,7 @@ jobs:
|
|||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Create Build Environment
|
||||
run: cmake -E make_directory ${{runner.workspace}}/build
|
||||
|
@ -79,7 +79,7 @@ jobs:
|
|||
run: '&($Env:GITHUB_WORKSPACE + "/make_windows_package.ps1") ./build ($Env:GITHUB_WORKSPACE + "/root")'
|
||||
|
||||
- name: Save Archive
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdrpp_windows_x64
|
||||
path: ${{runner.workspace}}/sdrpp_windows_x64.zip
|
||||
|
@ -88,7 +88,7 @@ jobs:
|
|||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Create Build Environment
|
||||
run: cmake -E make_directory ${{runner.workspace}}/build
|
||||
|
@ -103,7 +103,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/SDRplay_RSP_API-MacOSX-3.07.3.pkg && sudo installer -pkg SDRplay_RSP_API-MacOSX-3.07.3.pkg -target /
|
||||
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 ../../
|
||||
|
@ -133,7 +133,7 @@ jobs:
|
|||
run: cd $GITHUB_WORKSPACE && sh make_macos_bundle.sh ${{runner.workspace}}/build ./SDR++.app && zip -r ${{runner.workspace}}/sdrpp_macos_intel.zip SDR++.app
|
||||
|
||||
- name: Save Archive
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdrpp_macos_intel
|
||||
path: ${{runner.workspace}}/sdrpp_macos_intel.zip
|
||||
|
@ -142,7 +142,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Create Docker Image
|
||||
run: cd $GITHUB_WORKSPACE/docker_builds/debian_buster && docker build . --tag sdrpp_build
|
||||
|
@ -155,7 +155,7 @@ jobs:
|
|||
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
|
||||
|
||||
- name: Save Deb Archive
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdrpp_debian_buster_amd64
|
||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
||||
|
@ -164,7 +164,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Create Docker Image
|
||||
run: cd $GITHUB_WORKSPACE/docker_builds/debian_bullseye && docker build . --tag sdrpp_build
|
||||
|
@ -177,7 +177,7 @@ jobs:
|
|||
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
|
||||
|
||||
- name: Save Deb Archive
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdrpp_debian_bullseye_amd64
|
||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
||||
|
@ -186,7 +186,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Create Docker Image
|
||||
run: cd $GITHUB_WORKSPACE/docker_builds/debian_bookworm && docker build . --tag sdrpp_build
|
||||
|
@ -199,7 +199,7 @@ jobs:
|
|||
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
|
||||
|
||||
- name: Save Deb Archive
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdrpp_debian_bookworm_amd64
|
||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
||||
|
@ -208,7 +208,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Create Docker Image
|
||||
run: cd $GITHUB_WORKSPACE/docker_builds/debian_sid && docker build . --tag sdrpp_build
|
||||
|
@ -221,7 +221,7 @@ jobs:
|
|||
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
|
||||
|
||||
- name: Save Deb Archive
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdrpp_debian_sid_amd64
|
||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
||||
|
@ -230,7 +230,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Create Docker Image
|
||||
run: cd $GITHUB_WORKSPACE/docker_builds/ubuntu_focal && docker build . --tag sdrpp_build
|
||||
|
@ -243,7 +243,7 @@ jobs:
|
|||
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
|
||||
|
||||
- name: Save Deb Archive
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdrpp_ubuntu_focal_amd64
|
||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
||||
|
@ -252,7 +252,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Create Docker Image
|
||||
run: cd $GITHUB_WORKSPACE/docker_builds/ubuntu_jammy && docker build . --tag sdrpp_build
|
||||
|
@ -265,16 +265,38 @@ jobs:
|
|||
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
|
||||
|
||||
- name: Save Deb Archive
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdrpp_ubuntu_jammy_amd64
|
||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
||||
|
||||
build_ubuntu_mantic:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Create Docker Image
|
||||
run: cd $GITHUB_WORKSPACE/docker_builds/ubuntu_mantic && docker build . --tag sdrpp_build
|
||||
|
||||
- name: Run Container
|
||||
run: docker run --name build -v $GITHUB_WORKSPACE:/root/SDRPlusPlus --env BUILD_NO="-$GITHUB_RUN_NUMBER" sdrpp_build /root/do_build.sh
|
||||
|
||||
- name: Recover Deb Archive
|
||||
working-directory: ${{runner.workspace}}
|
||||
run: docker cp build:/root/SDRPlusPlus/sdrpp_debian_amd64.deb ./
|
||||
|
||||
- name: Save Deb Archive
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdrpp_ubuntu_mantic_amd64
|
||||
path: ${{runner.workspace}}/sdrpp_debian_amd64.deb
|
||||
|
||||
build_raspios_bullseye_armhf:
|
||||
runs-on: ARM
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Create Build Environment
|
||||
run: rm -rf ${{runner.workspace}}/build && cmake -E make_directory ${{runner.workspace}}/build
|
||||
|
@ -292,7 +314,7 @@ jobs:
|
|||
run: sh $GITHUB_WORKSPACE/make_debian_package.sh ./build 'libfftw3-dev, libglfw3-dev, libvolk2-dev, librtaudio-dev' && mv sdrpp_debian_amd64.deb sdrpp_debian_armhf.deb
|
||||
|
||||
- name: Save Deb Archive
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdrpp_raspios_bullseye_armhf
|
||||
path: ${{runner.workspace}}/sdrpp_debian_armhf.deb
|
||||
|
@ -301,7 +323,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Fetch container
|
||||
working-directory: ${{runner.workspace}}
|
||||
|
@ -319,18 +341,18 @@ jobs:
|
|||
run: docker cp build:/root/SDRPlusPlus/android/app/build/outputs/apk/debug/app-debug.apk ./ && mv app-debug.apk sdrpp.apk
|
||||
|
||||
- name: Save APK
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdrpp_android
|
||||
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_raspios_bullseye_armhf', 'build_android']
|
||||
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']
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Download All Builds
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
- name: Create Archive
|
||||
run: >
|
||||
|
@ -343,10 +365,11 @@ jobs:
|
|||
mv sdrpp_debian_sid_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_debian_sid_amd64.deb &&
|
||||
mv sdrpp_ubuntu_focal_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_focal_amd64.deb &&
|
||||
mv sdrpp_ubuntu_jammy_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_jammy_amd64.deb &&
|
||||
mv sdrpp_ubuntu_mantic_amd64/sdrpp_debian_amd64.deb sdrpp_all/sdrpp_ubuntu_mantic_amd64.deb &&
|
||||
mv sdrpp_raspios_bullseye_armhf/sdrpp_debian_armhf.deb sdrpp_all/sdrpp_raspios_bullseye_armhf.deb &&
|
||||
mv sdrpp_android/sdrpp.apk sdrpp_all/sdrpp.apk
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sdrpp_all
|
||||
path: sdrpp_all/
|
||||
|
@ -358,7 +381,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Download All Builds
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
- name: Update Nightly
|
||||
run: gh release upload nightly sdrpp_all/* -R ${{github.repository}} --clobber
|
||||
|
@ -367,7 +390,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install codespell
|
||||
run: sudo apt update -y && sudo apt install -y codespell
|
||||
|
@ -379,7 +402,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Run check_clang_format
|
||||
run: cd $GITHUB_WORKSPACE && chmod +x ./check_clang_format.sh && ./check_clang_format.sh || true
|
||||
|
|
|
@ -62,6 +62,33 @@ inline void printAndScale(double freq, char* buf) {
|
|||
}
|
||||
}
|
||||
|
||||
inline void doZoom(int offset, int width, int inSize, int outSize, float* in, float* out) {
|
||||
// NOTE: REMOVE THAT SHIT, IT'S JUST A HACKY FIX
|
||||
if (offset < 0) {
|
||||
offset = 0;
|
||||
}
|
||||
if (width > 524288) {
|
||||
width = 524288;
|
||||
}
|
||||
|
||||
float factor = (float)width / (float)outSize;
|
||||
float sFactor = ceilf(factor);
|
||||
float uFactor;
|
||||
float id = offset;
|
||||
float maxVal;
|
||||
int sId;
|
||||
for (int i = 0; i < outSize; i++) {
|
||||
maxVal = -INFINITY;
|
||||
sId = (int)id;
|
||||
uFactor = (sId + sFactor > inSize) ? sFactor - ((sId + sFactor) - inSize) : sFactor;
|
||||
for (int j = 0; j < uFactor; j++) {
|
||||
if (in[sId + j] > maxVal) { maxVal = in[sId + j]; }
|
||||
}
|
||||
out[i] = maxVal;
|
||||
id += factor;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ImGui {
|
||||
WaterFall::WaterFall() {
|
||||
fftMin = -70.0;
|
||||
|
@ -586,7 +613,7 @@ namespace ImGui {
|
|||
for (int i = 0; i < count; i++) {
|
||||
drawDataSize = (viewBandwidth / wholeBandwidth) * rawFFTSize;
|
||||
drawDataStart = (((double)rawFFTSize / 2.0) * (offsetRatio + 1)) - (drawDataSize / 2);
|
||||
doZoom(drawDataStart, drawDataSize, dataWidth, &rawFFTs[((i + currentFFTLine) % waterfallHeight) * rawFFTSize], tempData);
|
||||
doZoom(drawDataStart, drawDataSize, rawFFTSize, dataWidth, &rawFFTs[((i + currentFFTLine) % waterfallHeight) * rawFFTSize], tempData);
|
||||
for (int j = 0; j < dataWidth; j++) {
|
||||
pixel = (std::clamp<float>(tempData[j], waterfallMin, waterfallMax) - waterfallMin) / dataRange;
|
||||
waterfallFb[(i * dataWidth) + j] = waterfallPallet[(int)(pixel * (WATERFALL_RESOLUTION - 1))];
|
||||
|
@ -867,7 +894,7 @@ namespace ImGui {
|
|||
int drawDataStart = (((double)rawFFTSize / 2.0) * (offsetRatio + 1)) - (drawDataSize / 2);
|
||||
|
||||
if (waterfallVisible) {
|
||||
doZoom(drawDataStart, drawDataSize, dataWidth, &rawFFTs[currentFFTLine * rawFFTSize], latestFFT);
|
||||
doZoom(drawDataStart, drawDataSize, rawFFTSize, dataWidth, &rawFFTs[currentFFTLine * rawFFTSize], latestFFT);
|
||||
memmove(&waterfallFb[dataWidth], waterfallFb, dataWidth * (waterfallHeight - 1) * sizeof(uint32_t));
|
||||
float pixel;
|
||||
float dataRange = waterfallMax - waterfallMin;
|
||||
|
@ -879,7 +906,7 @@ namespace ImGui {
|
|||
waterfallUpdate = true;
|
||||
}
|
||||
else {
|
||||
doZoom(drawDataStart, drawDataSize, dataWidth, rawFFTs, latestFFT);
|
||||
doZoom(drawDataStart, drawDataSize, rawFFTSize, dataWidth, rawFFTs, latestFFT);
|
||||
fftLines = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -90,33 +90,6 @@ namespace ImGui {
|
|||
float* getFFTBuffer();
|
||||
void pushFFT();
|
||||
|
||||
inline void doZoom(int offset, int width, int outWidth, float* data, float* out) {
|
||||
// NOTE: REMOVE THAT SHIT, IT'S JUST A HACKY FIX
|
||||
if (offset < 0) {
|
||||
offset = 0;
|
||||
}
|
||||
if (width > 524288) {
|
||||
width = 524288;
|
||||
}
|
||||
|
||||
float factor = (float)width / (float)outWidth;
|
||||
float sFactor = ceilf(factor);
|
||||
float uFactor;
|
||||
float id = offset;
|
||||
float maxVal;
|
||||
int sId;
|
||||
for (int i = 0; i < outWidth; i++) {
|
||||
maxVal = -INFINITY;
|
||||
sId = (int)id;
|
||||
uFactor = (sId + sFactor > rawFFTSize) ? sFactor - ((sId + sFactor) - rawFFTSize) : sFactor;
|
||||
for (int j = 0; j < uFactor; j++) {
|
||||
if (data[sId + j] > maxVal) { maxVal = data[sId + j]; }
|
||||
}
|
||||
out[i] = maxVal;
|
||||
id += factor;
|
||||
}
|
||||
}
|
||||
|
||||
void updatePallette(float colors[][3], int colorCount);
|
||||
void updatePalletteFromArray(float* colors, int colorCount);
|
||||
|
||||
|
|
|
@ -86,14 +86,14 @@ namespace net {
|
|||
addr.sin_port = htons(port);
|
||||
}
|
||||
|
||||
std::string Address::getIPStr() {
|
||||
std::string Address::getIPStr() const {
|
||||
char buf[128];
|
||||
IP_t ip = getIP();
|
||||
sprintf(buf, "%d.%d.%d.%d", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF);
|
||||
return buf;
|
||||
}
|
||||
|
||||
IP_t Address::getIP() {
|
||||
IP_t Address::getIP() const {
|
||||
return htonl(addr.sin_addr.s_addr);
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ namespace net {
|
|||
addr.sin_addr.s_addr = htonl(ip);
|
||||
}
|
||||
|
||||
int Address::getPort() {
|
||||
int Address::getPort() const {
|
||||
return htons(addr.sin_port);
|
||||
}
|
||||
|
||||
|
@ -160,8 +160,8 @@ namespace net {
|
|||
|
||||
// Set timeout
|
||||
timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = timeout * 1000;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout - tv.tv_sec*1000) * 1000;
|
||||
|
||||
// Wait for data
|
||||
int err = select(sock+1, &set, NULL, &set, (timeout > 0) ? &tv : NULL);
|
||||
|
@ -225,8 +225,8 @@ namespace net {
|
|||
|
||||
// Define timeout
|
||||
timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = timeout * 1000;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout - tv.tv_sec*1000) * 1000;
|
||||
|
||||
// Wait for data or error
|
||||
if (timeout != NONBLOCKING) {
|
||||
|
@ -375,13 +375,25 @@ namespace net {
|
|||
return connect(Address(host, port));
|
||||
}
|
||||
|
||||
std::shared_ptr<Socket> openudp(const Address& raddr, const Address& laddr) {
|
||||
std::shared_ptr<Socket> openudp(const Address& raddr, const Address& laddr, bool allowBroadcast) {
|
||||
// Init library if needed
|
||||
init();
|
||||
|
||||
// Create socket
|
||||
SockHandle_t s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
// If the remote address is multicast, allow multicast connections
|
||||
#ifdef _WIN32
|
||||
const char enable = allowBroadcast;
|
||||
#else
|
||||
int enable = allowBroadcast;
|
||||
#endif
|
||||
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &enable, sizeof(int)) < 0) {
|
||||
closeSocket(s);
|
||||
throw std::runtime_error("Could not enable broadcast on socket");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Bind socket to local port
|
||||
if (bind(s, (sockaddr*)&laddr.addr, sizeof(sockaddr_in))) {
|
||||
closeSocket(s);
|
||||
|
@ -393,15 +405,15 @@ namespace net {
|
|||
return std::make_shared<Socket>(s, &raddr);
|
||||
}
|
||||
|
||||
std::shared_ptr<Socket> openudp(std::string rhost, int rport, const Address& laddr) {
|
||||
return openudp(Address(rhost, rport), laddr);
|
||||
std::shared_ptr<Socket> openudp(std::string rhost, int rport, const Address& laddr, bool allowBroadcast) {
|
||||
return openudp(Address(rhost, rport), laddr, allowBroadcast);
|
||||
}
|
||||
|
||||
std::shared_ptr<Socket> openudp(const Address& raddr, std::string lhost, int lport) {
|
||||
return openudp(raddr, Address(lhost, lport));
|
||||
std::shared_ptr<Socket> openudp(const Address& raddr, std::string lhost, int lport, bool allowBroadcast) {
|
||||
return openudp(raddr, Address(lhost, lport), allowBroadcast);
|
||||
}
|
||||
|
||||
std::shared_ptr<Socket> openudp(std::string rhost, int rport, std::string lhost, int lport) {
|
||||
return openudp(Address(rhost, rport), Address(lhost, lport));
|
||||
std::shared_ptr<Socket> openudp(std::string rhost, int rport, std::string lhost, int lport, bool allowBroadcast) {
|
||||
return openudp(Address(rhost, rport), Address(lhost, lport), allowBroadcast);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,13 +67,13 @@ namespace net {
|
|||
* Get the IP address.
|
||||
* @return IP address in standard string format.
|
||||
*/
|
||||
std::string getIPStr();
|
||||
std::string getIPStr() const;
|
||||
|
||||
/**
|
||||
* Get the IP address.
|
||||
* @return IP address in host byte order.
|
||||
*/
|
||||
IP_t getIP();
|
||||
IP_t getIP() const;
|
||||
|
||||
/**
|
||||
* Set the IP address.
|
||||
|
@ -85,7 +85,7 @@ namespace net {
|
|||
* Get the TCP/UDP port.
|
||||
* @return TCP/UDP port number.
|
||||
*/
|
||||
int getPort();
|
||||
int getPort() const;
|
||||
|
||||
/**
|
||||
* Set the TCP/UDP port.
|
||||
|
@ -246,37 +246,37 @@ namespace net {
|
|||
|
||||
/**
|
||||
* Create UDP socket.
|
||||
* @param raddr Remote address.
|
||||
* @param raddr Remote address. Set to a multicast address to allow multicast.
|
||||
* @param laddr Local address to bind the socket to.
|
||||
* @return Socket instance on success, Throws runtime_error otherwise.
|
||||
*/
|
||||
std::shared_ptr<Socket> openudp(const Address& raddr, const Address& laddr);
|
||||
std::shared_ptr<Socket> openudp(const Address& raddr, const Address& laddr, bool allowBroadcast = false);
|
||||
|
||||
/**
|
||||
* Create UDP socket.
|
||||
* @param rhost Remote hostname or IP address.
|
||||
* @param rhost Remote hostname or IP address. Set to a multicast address to allow multicast.
|
||||
* @param rport Remote port.
|
||||
* @param laddr Local address to bind the socket to.
|
||||
* @return Socket instance on success, Throws runtime_error otherwise.
|
||||
*/
|
||||
std::shared_ptr<Socket> openudp(std::string rhost, int rport, const Address& laddr);
|
||||
std::shared_ptr<Socket> openudp(std::string rhost, int rport, const Address& laddr, bool allowBroadcast = false);
|
||||
|
||||
/**
|
||||
* Create UDP socket.
|
||||
* @param raddr Remote address.
|
||||
* @param raddr Remote address. Set to a multicast or broadcast address to allow multicast.
|
||||
* @param lhost Local hostname or IP used to bind the socket (optional, "0.0.0.0" for Any).
|
||||
* @param lpost Local port used to bind the socket to (optional, 0 to allocate automatically).
|
||||
* @return Socket instance on success, Throws runtime_error otherwise.
|
||||
*/
|
||||
std::shared_ptr<Socket> openudp(const Address& raddr, std::string lhost = "0.0.0.0", int lport = 0);
|
||||
std::shared_ptr<Socket> openudp(const Address& raddr, std::string lhost = "0.0.0.0", int lport = 0, bool allowBroadcast = false);
|
||||
|
||||
/**
|
||||
* Create UDP socket.
|
||||
* @param rhost Remote hostname or IP address.
|
||||
* @param rhost Remote hostname or IP address. Set to a multicast or broadcast address to allow multicast.
|
||||
* @param rport Remote port.
|
||||
* @param lhost Local hostname or IP used to bind the socket (optional, "0.0.0.0" for Any).
|
||||
* @param lpost Local port used to bind the socket to (optional, 0 to allocate automatically).
|
||||
* @return Socket instance on success, Throws runtime_error otherwise.
|
||||
*/
|
||||
std::shared_ptr<Socket> openudp(std::string rhost, int rport, std::string lhost = "0.0.0.0", int lport = 0);
|
||||
std::shared_ptr<Socket> openudp(std::string rhost, int rport, std::string lhost = "0.0.0.0", int lport = 0, bool allowBroadcast = false);
|
||||
}
|
|
@ -9,10 +9,10 @@ apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev
|
|||
libcodec2-dev autoconf libtool xxd
|
||||
|
||||
# Install SDRPlay libraries
|
||||
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
|
||||
7z x ./SDRplay_RSP_API-Linux-3.07.1.run
|
||||
7z x ./SDRplay_RSP_API-Linux-3.07.1
|
||||
cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so
|
||||
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
|
||||
cp inc/* /usr/include/
|
||||
|
||||
# Install libperseus
|
||||
|
|
|
@ -9,10 +9,10 @@ apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev
|
|||
libcodec2-dev autoconf libtool xxd
|
||||
|
||||
# Install SDRPlay libraries
|
||||
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
|
||||
7z x ./SDRplay_RSP_API-Linux-3.07.1.run
|
||||
7z x ./SDRplay_RSP_API-Linux-3.07.1
|
||||
cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so
|
||||
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
|
||||
cp inc/* /usr/include/
|
||||
|
||||
# Install libperseus
|
||||
|
|
|
@ -9,10 +9,10 @@ apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk1-dev
|
|||
libcodec2-dev autoconf libtool xxd
|
||||
|
||||
# Install SDRPlay libraries
|
||||
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
|
||||
7z x ./SDRplay_RSP_API-Linux-3.07.1.run
|
||||
7z x ./SDRplay_RSP_API-Linux-3.07.1
|
||||
cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so
|
||||
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
|
||||
cp inc/* /usr/include/
|
||||
|
||||
# Install libperseus
|
||||
|
|
|
@ -9,10 +9,10 @@ apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk-dev l
|
|||
libcodec2-dev autoconf libtool xxd
|
||||
|
||||
# Install SDRPlay libraries
|
||||
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
|
||||
7z x ./SDRplay_RSP_API-Linux-3.07.1.run
|
||||
7z x ./SDRplay_RSP_API-Linux-3.07.1
|
||||
cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so
|
||||
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
|
||||
cp inc/* /usr/include/
|
||||
|
||||
# Install libperseus
|
||||
|
|
|
@ -15,10 +15,10 @@ apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk1-dev
|
|||
libcodec2-dev libudev-dev autoconf libtool xxd
|
||||
|
||||
# Install SDRPlay libraries
|
||||
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
|
||||
7z x ./SDRplay_RSP_API-Linux-3.07.1.run
|
||||
7z x ./SDRplay_RSP_API-Linux-3.07.1
|
||||
cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so
|
||||
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
|
||||
cp inc/* /usr/include/
|
||||
|
||||
# Install a more recent libusb version
|
||||
|
|
|
@ -9,10 +9,10 @@ apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev
|
|||
libcodec2-dev autoconf libtool xxd
|
||||
|
||||
# Install SDRPlay libraries
|
||||
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
|
||||
7z x ./SDRplay_RSP_API-Linux-3.07.1.run
|
||||
7z x ./SDRplay_RSP_API-Linux-3.07.1
|
||||
cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so
|
||||
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
|
||||
cp inc/* /usr/include/
|
||||
|
||||
# Install libperseus
|
||||
|
|
|
@ -9,10 +9,10 @@ apt install -y build-essential cmake git libfftw3-dev libglfw3-dev libvolk2-dev
|
|||
libcodec2-dev autoconf libtool xxd
|
||||
|
||||
# Install SDRPlay libraries
|
||||
wget https://www.sdrplay.com/software/SDRplay_RSP_API-Linux-3.07.1.run
|
||||
7z x ./SDRplay_RSP_API-Linux-3.07.1.run
|
||||
7z x ./SDRplay_RSP_API-Linux-3.07.1
|
||||
cp x86_64/libsdrplay_api.so.3.07 /usr/lib/libsdrplay_api.so
|
||||
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
|
||||
cp inc/* /usr/include/
|
||||
|
||||
# Install libperseus
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
FROM ubuntu:mantic
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
COPY do_build.sh /root
|
||||
RUN chmod +x /root/do_build.sh
|
|
@ -0,0 +1,35 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
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 \
|
||||
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
|
||||
cp inc/* /usr/include/
|
||||
|
||||
# Install libperseus
|
||||
git clone https://github.com/Microtelecom/libperseus-sdr
|
||||
cd libperseus-sdr
|
||||
autoreconf -i
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
ldconfig
|
||||
cd ..
|
||||
|
||||
cd SDRPlusPlus
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DOPT_BUILD_BLADERF_SOURCE=ON -DOPT_BUILD_LIMESDR_SOURCE=ON -DOPT_BUILD_SDRPLAY_SOURCE=ON -DOPT_BUILD_NEW_PORTAUDIO_SINK=ON -DOPT_BUILD_M17_DECODER=ON -DOPT_BUILD_PERSEUS_SOURCE=ON
|
||||
make VERBOSE=1 -j2
|
||||
|
||||
cd ..
|
||||
sh make_debian_package.sh ./build 'libfftw3-dev, libglfw3-dev, libvolk-dev, librtaudio-dev, libzstd-dev'
|
|
@ -15,7 +15,7 @@ SDR++ is a cross-platform and open source SDR software with the aim of being blo
|
|||
* Multi VFO
|
||||
* Wide hardware support (both through SoapySDR and dedicated modules)
|
||||
* SIMD accelerated DSP
|
||||
* Cross-platform (Windows, Linux, OSX and BSD)
|
||||
* Cross-platform (Windows, Linux, MacOS and BSD)
|
||||
* Full waterfall update when possible. Makes browsing signals easier and more pleasant
|
||||
* Modular design (easily write your own plugins)
|
||||
|
||||
|
|
|
@ -103,6 +103,24 @@
|
|||
},
|
||||
{
|
||||
"start": 283500,
|
||||
"end": 472000,
|
||||
"type": "aviation",
|
||||
"name": "Aeronautical Radionavigation / Maritime"
|
||||
},
|
||||
{
|
||||
"start": 472000,
|
||||
"end": 475000,
|
||||
"type": "amateur",
|
||||
"name": "635m Ham Band CW"
|
||||
},
|
||||
{
|
||||
"start": 475000,
|
||||
"end": 479000,
|
||||
"type": "amateur1",
|
||||
"name": "635m Ham Band CW, Digimodes"
|
||||
},
|
||||
{
|
||||
"start": 479000,
|
||||
"end": 526500,
|
||||
"type": "aviation",
|
||||
"name": "Aeronautical Radionavigation / Maritime"
|
||||
|
@ -284,7 +302,7 @@
|
|||
{
|
||||
"start": 3754500,
|
||||
"end": 3757500,
|
||||
"type": "amateur1",
|
||||
"type": "utility",
|
||||
"name": "The Pip (Night)"
|
||||
},
|
||||
{
|
||||
|
@ -729,7 +747,7 @@
|
|||
"start": 5330500,
|
||||
"end": 5333400,
|
||||
"type": "amateur",
|
||||
"name": "|60m Ham Band Ch. 1 (Not NL)"
|
||||
"name": "60m Ham Band Ch. 1 (Not NL)"
|
||||
},
|
||||
{
|
||||
"start": 5333400,
|
||||
|
@ -744,19 +762,31 @@
|
|||
"name": "Ch. 2 (60m) (Not NL)"
|
||||
},
|
||||
{
|
||||
"start": 5351500,
|
||||
"end": 5366500,
|
||||
"start": 5349400,
|
||||
"end": 5351500,
|
||||
"type": "amateur1",
|
||||
"name": "60m Ham Band NL"
|
||||
"name": "60m Ham Band (Not NL)"
|
||||
},
|
||||
{
|
||||
"start": 5357000,
|
||||
"end": 5359900,
|
||||
"start": 5351500,
|
||||
"end": 5354000,
|
||||
"type": "amateur",
|
||||
"name": "Ch. 3 (60m) (Not NL)"
|
||||
"name": "60m Ham Band CW"
|
||||
},
|
||||
{
|
||||
"start": 5359900,
|
||||
"start": 5354000,
|
||||
"end": 5366000,
|
||||
"type": "amateur1",
|
||||
"name": "60m HAM Alle modes (USB)"
|
||||
},
|
||||
{
|
||||
"start": 5366000,
|
||||
"end": 5366500,
|
||||
"type": "amateur",
|
||||
"name": "60m HAM Weak NB modes"
|
||||
},
|
||||
{
|
||||
"start": 5366500,
|
||||
"end": 5371500,
|
||||
"type": "amateur1",
|
||||
"name": "60m Ham Band (Not NL)"
|
||||
|
@ -777,7 +807,7 @@
|
|||
"start": 5403500,
|
||||
"end": 5406400,
|
||||
"type": "amateur",
|
||||
"name": "Ch. 5 60m Ham Band (Not NL)|"
|
||||
"name": "Ch. 5 60m Ham Band (Not NL)"
|
||||
},
|
||||
{
|
||||
"start": 5406400,
|
||||
|
@ -3047,17 +3077,11 @@
|
|||
"type": "utility",
|
||||
"name": "Radio Astronomy"
|
||||
},
|
||||
{
|
||||
"start": 2300000000,
|
||||
"end": 2310000000,
|
||||
"type": "amateur",
|
||||
"name": "|13cm Ham Band"
|
||||
},
|
||||
{
|
||||
"start": 2320000000,
|
||||
"end": 2332500000,
|
||||
"type": "satellite",
|
||||
"name": "Satellite Digital Audio Radio Service (SDARS)"
|
||||
"type": "amateur",
|
||||
"name": "|13cm Ham Band Satellite Digital Audio Radio Service (SDARS)"
|
||||
},
|
||||
{
|
||||
"start": 2332500000,
|
||||
|
@ -3067,21 +3091,9 @@
|
|||
},
|
||||
{
|
||||
"start": 2345000000,
|
||||
"end": 2360000000,
|
||||
"type": "aviation",
|
||||
"name": "Aviation Service and the Wireless Communications Service (WCS)"
|
||||
},
|
||||
{
|
||||
"start": 2360000000,
|
||||
"end": 2390000000,
|
||||
"type": "aviation",
|
||||
"name": "Aviation"
|
||||
},
|
||||
{
|
||||
"start": 2390000000,
|
||||
"end": 2393750000,
|
||||
"type": "amateur",
|
||||
"name": "13cm Ham Band (Upper)| Analog and Digital"
|
||||
"name": "13cm Ham Band Analog and Digital"
|
||||
},
|
||||
{
|
||||
"start": 2393750000,
|
||||
|
@ -3093,25 +3105,25 @@
|
|||
"start": 2394750000,
|
||||
"end": 2400000000,
|
||||
"type": "amateur",
|
||||
"name": "Analog and Digital 13 cm HAM Band|"
|
||||
"name": "Analog and Digital 13cm HAM Band"
|
||||
},
|
||||
{
|
||||
"start": 2400000000,
|
||||
"end": 2401000000,
|
||||
"type": "utility",
|
||||
"name": "Shared Satellite and 13cm ISM"
|
||||
"name": "Shared Satellite, 13cm ISM and Ham"
|
||||
},
|
||||
{
|
||||
"start": 2401000000,
|
||||
"end": 2410000000,
|
||||
"type": "utility",
|
||||
"name": "WiFi shared with Satellite and 13cm ISM"
|
||||
"name": "WiFi shared with Satellite, 13cm ISM and Ham"
|
||||
},
|
||||
{
|
||||
"start": 2410000000,
|
||||
"end": 2411900000,
|
||||
"type": "utility",
|
||||
"name": "WiFi shared with Broadband Modes and 13cm ISM"
|
||||
"name": "WiFi shared with Broadband Modes, 13cm ISM and Ham"
|
||||
},
|
||||
{
|
||||
"start": 2411900000,
|
||||
|
@ -3122,8 +3134,8 @@
|
|||
{
|
||||
"start": 2412100000,
|
||||
"end": 2450000000,
|
||||
"type": "utility",
|
||||
"name": "WiFi shared with Broadband Modes 13cm ISM |13cm Ham Band"
|
||||
"type": "amateur",
|
||||
"name": "WiFi shared with Broadband Modes 13cm ISM, 13cm Ham Band|"
|
||||
},
|
||||
{
|
||||
"start": 2450000000,
|
||||
|
@ -3172,6 +3184,366 @@
|
|||
"end": 2500000000,
|
||||
"type": "utility",
|
||||
"name": "ISM Band (13cm)"
|
||||
},
|
||||
{
|
||||
"name": "IMT",
|
||||
"type": "cellular",
|
||||
"start": 2500000000,
|
||||
"end": 2544500000
|
||||
},
|
||||
{
|
||||
"name": "Radioastronomy",
|
||||
"type": "utility",
|
||||
"start": 2690000000,
|
||||
"end": 2700000000
|
||||
},
|
||||
{
|
||||
"name": "Radar meteo",
|
||||
"type": "military",
|
||||
"start": 2700000000,
|
||||
"end": 2900000000
|
||||
},
|
||||
{
|
||||
"name": "Maritime Radar",
|
||||
"type": "marine",
|
||||
"start": 2900000000,
|
||||
"end": 3400000000
|
||||
},
|
||||
{
|
||||
"name": "Radio Ham 9 cm band",
|
||||
"type": "amateur",
|
||||
"start": 3400000000,
|
||||
"end": 3475000000
|
||||
},
|
||||
{
|
||||
"name": "Digital Networks",
|
||||
"type": "utility",
|
||||
"start": 3475000000,
|
||||
"end": 4200000000
|
||||
},
|
||||
{
|
||||
"name": "Altimeters",
|
||||
"type": "aviation",
|
||||
"start": 4200000000,
|
||||
"end": 4400000000
|
||||
},
|
||||
{
|
||||
"name": "Feeder link",
|
||||
"type": "satellite",
|
||||
"start": 5150000000,
|
||||
"end": 5250000000
|
||||
},
|
||||
{
|
||||
"name": "Digital networks and 802.11",
|
||||
"type": "utility",
|
||||
"start": 5250000000,
|
||||
"end": 5650000000
|
||||
},
|
||||
{
|
||||
"name": "Radio Ham 6 cm band",
|
||||
"type": "amateur",
|
||||
"start": 5650000000,
|
||||
"end": 5850000000
|
||||
},
|
||||
{
|
||||
"name": "Digital Networks and LPR",
|
||||
"type": "utility",
|
||||
"start": 5925000000,
|
||||
"end": 7750000000
|
||||
},
|
||||
{
|
||||
"name": "LPR",
|
||||
"type": "utility",
|
||||
"start": 7750000000,
|
||||
"end": 7975000000
|
||||
},
|
||||
{
|
||||
"name": "Remote sensing",
|
||||
"type": "utility",
|
||||
"start": 7975000000,
|
||||
"end": 8215000000
|
||||
},
|
||||
{
|
||||
"name": "TLPR and SRD",
|
||||
"type": "utility",
|
||||
"start": 8215000000,
|
||||
"end": 8650000000
|
||||
},
|
||||
{
|
||||
"name": "Radar Doppler",
|
||||
"type": "aviation",
|
||||
"start": 8650000000,
|
||||
"end": 8850000000
|
||||
},
|
||||
{
|
||||
"name": "Maritime Radar",
|
||||
"type": "marine",
|
||||
"start": 8850000000,
|
||||
"end": 9000000000
|
||||
},
|
||||
{
|
||||
"name": "Radar and transponder SART",
|
||||
"type": "marine",
|
||||
"start": 9000000000,
|
||||
"end": 9500000000
|
||||
},
|
||||
{
|
||||
"name": "TLPR and SRD",
|
||||
"type": "utility",
|
||||
"start": 9500000000,
|
||||
"end": 10000000000
|
||||
},
|
||||
{
|
||||
"name": "Radio Ham 3 cm band",
|
||||
"type": "amateur",
|
||||
"start": 10000000000,
|
||||
"end": 10500000000
|
||||
},
|
||||
{
|
||||
"name": "Point to point TV networks",
|
||||
"type": "utility",
|
||||
"start": 10500000000,
|
||||
"end": 10680000000
|
||||
},
|
||||
{
|
||||
"name": "Digital network (fixed)",
|
||||
"type": "utility",
|
||||
"start": 10680000000,
|
||||
"end": 11700000000
|
||||
},
|
||||
{
|
||||
"name": "TV satellite",
|
||||
"type": "satellite",
|
||||
"start": 11700000000,
|
||||
"end": 12500000000
|
||||
},
|
||||
{
|
||||
"name": "Digital network (fixed)",
|
||||
"type": "utility",
|
||||
"start": 12500000000,
|
||||
"end": 13250000000
|
||||
},
|
||||
{
|
||||
"name": "Satellite Uplink",
|
||||
"type": "satellite",
|
||||
"start": 14000000000,
|
||||
"end": 14500000000
|
||||
},
|
||||
{
|
||||
"name": "Digital network (fixed)",
|
||||
"type": "utility",
|
||||
"start": 14500000000,
|
||||
"end": 14620000000
|
||||
},
|
||||
{
|
||||
"name": "Digital network (fixed)",
|
||||
"type": "utility",
|
||||
"start": 15230000000,
|
||||
"end": 15350000000
|
||||
},
|
||||
{
|
||||
"name": "Digital network (poit to point)",
|
||||
"type": "utility",
|
||||
"start": 17100000000,
|
||||
"end": 19300000000
|
||||
},
|
||||
{
|
||||
"name": "Feeder link",
|
||||
"type": "satellite",
|
||||
"start": 19300000000,
|
||||
"end": 19700000000
|
||||
},
|
||||
{
|
||||
"name": "HEST, LEST, ESIM, ESOMP",
|
||||
"type": "satellite",
|
||||
"start": 19700000000,
|
||||
"end": 20200000000
|
||||
},
|
||||
{
|
||||
"name": "Digital network (fixed)",
|
||||
"type": "utility",
|
||||
"start": 22000000000,
|
||||
"end": 22330000000
|
||||
},
|
||||
{
|
||||
"name": "Digital network (fixed)",
|
||||
"type": "utility",
|
||||
"start": 22674750000,
|
||||
"end": 2283350000
|
||||
},
|
||||
{
|
||||
"name": "Digital network (fixed), SAP/SAB",
|
||||
"type": "utility",
|
||||
"start": 22926750000,
|
||||
"end": 23150000000
|
||||
},
|
||||
{
|
||||
"name": "Digital network (fixed)",
|
||||
"type": "utility",
|
||||
"start": 23150000000,
|
||||
"end": 23338000000
|
||||
},
|
||||
{
|
||||
"name": "ISM, SRD and LPR",
|
||||
"type": "utility",
|
||||
"start": 24000000000,
|
||||
"end": 24450000000
|
||||
},
|
||||
{
|
||||
"name": "Digital network (point to point, multipoint)",
|
||||
"type": "utility",
|
||||
"start": 24450000000,
|
||||
"end": 25109000000
|
||||
},
|
||||
{
|
||||
"name": "LPR, SRD and SRR",
|
||||
"type": "utility",
|
||||
"start": 25109000000,
|
||||
"end": 2544500000
|
||||
},
|
||||
{
|
||||
"name": "Network (point to point, multipoint)",
|
||||
"type": "utility",
|
||||
"start": 2544500000,
|
||||
"end": 2611700000
|
||||
},
|
||||
{
|
||||
"name": "LPR, SRD and SRR",
|
||||
"type": "utility",
|
||||
"start": 2611700000,
|
||||
"end": 2650000000
|
||||
},
|
||||
{
|
||||
"name": "Terrestrial electric utility",
|
||||
"type": "utility",
|
||||
"start": 26500000000,
|
||||
"end": 27500000000
|
||||
},
|
||||
{
|
||||
"name": "Network (point to point, multipoint)",
|
||||
"type": "utility",
|
||||
"start": 27500000000,
|
||||
"end": 29100000000
|
||||
},
|
||||
{
|
||||
"name": "Network (point to point, multipoint)",
|
||||
"type": "utility",
|
||||
"start": 29100000000,
|
||||
"end": 29500000000
|
||||
},
|
||||
{
|
||||
"name": "Network (point to point, multipoint)",
|
||||
"type": "utility",
|
||||
"start": 31000000000,
|
||||
"end": 31300000000
|
||||
},
|
||||
{
|
||||
"name": "Network (high density, fixed)",
|
||||
"type": "utility",
|
||||
"start": 31983000000,
|
||||
"end": 32599000000
|
||||
},
|
||||
{
|
||||
"name": "Network (high density, fixed)",
|
||||
"type": "utility",
|
||||
"start": 32795000000,
|
||||
"end": 33400000000
|
||||
},
|
||||
{
|
||||
"name": "Network (high density, fixed)",
|
||||
"type": "utility",
|
||||
"start": 37338000000,
|
||||
"end": 38300000000
|
||||
},
|
||||
{
|
||||
"name": "Network (high density, fixed)",
|
||||
"type": "utility",
|
||||
"start": 38590000000,
|
||||
"end": 39500000000
|
||||
},
|
||||
{
|
||||
"name": "FWS systems (fixed)",
|
||||
"type": "utility",
|
||||
"start": 40500000000,
|
||||
"end": 43500000000
|
||||
},
|
||||
{
|
||||
"name": "Radio Ham 6 mm band",
|
||||
"type": "amateur",
|
||||
"start": 47000000000,
|
||||
"end": 47200000000
|
||||
},
|
||||
{
|
||||
"name": "Network (high density, fixed)",
|
||||
"type": "utility",
|
||||
"start": 51400000000,
|
||||
"end": 52600000000
|
||||
},
|
||||
{
|
||||
"name": "Network (high density, fixed)",
|
||||
"type": "utility",
|
||||
"start": 55780000000,
|
||||
"end": 61000000000
|
||||
},
|
||||
{
|
||||
"name": "ISM",
|
||||
"type": "utility",
|
||||
"start": 61000000000,
|
||||
"end": 64000000000
|
||||
},
|
||||
{
|
||||
"name": "Network (high density, fixed)",
|
||||
"type": "utility",
|
||||
"start": 64000000000,
|
||||
"end": 66000000000
|
||||
},
|
||||
{
|
||||
"name": "Links (high density, fixed)",
|
||||
"type": "utility",
|
||||
"start": 71000000000,
|
||||
"end": 74000000000
|
||||
},
|
||||
{
|
||||
"name": "LPR, SRD, SRR, TLPR, vehichle radar",
|
||||
"type": "utility",
|
||||
"start": 74000000000,
|
||||
"end": 76500000000
|
||||
},
|
||||
{
|
||||
"name": "Radio Ham 4 mm band",
|
||||
"type": "amateur",
|
||||
"start": 76500000000,
|
||||
"end": 81500000000
|
||||
},
|
||||
{
|
||||
"name": "Links (high density, fixed)",
|
||||
"type": "utility",
|
||||
"start": 84000000000,
|
||||
"end": 86000000000
|
||||
},
|
||||
{
|
||||
"name": "ISM",
|
||||
"type": "utility",
|
||||
"start": 120200000000,
|
||||
"end": 122250000000
|
||||
},
|
||||
{
|
||||
"name": "Radio Ham 2.5 mm band",
|
||||
"type": "amateur",
|
||||
"start": 122250000000,
|
||||
"end": 123000000000
|
||||
},
|
||||
{
|
||||
"name": "Radio Ham 2 mm band",
|
||||
"type": "amateur",
|
||||
"start": 134000000000,
|
||||
"end": 141000000000
|
||||
},
|
||||
{
|
||||
"name": "Radio Ham 1 mm band",
|
||||
"type": "amateur",
|
||||
"start": 241000000000,
|
||||
"end": 250000000000
|
||||
}
|
||||
]
|
||||
}
|
|
@ -224,14 +224,6 @@ private:
|
|||
int count = _this->stereoPacker.out.read();
|
||||
if (count < 0) { return 0; }
|
||||
|
||||
// For debug purposes only...
|
||||
// if (nBufferFrames != count) { flog::warn("Buffer size mismatch, wanted {0}, was asked for {1}", count, nBufferFrames); }
|
||||
// for (int i = 0; i < count; i++) {
|
||||
// if (_this->stereoPacker.out.readBuf[i].l == NAN || _this->stereoPacker.out.readBuf[i].r == NAN) { flog::error("NAN in audio data"); }
|
||||
// if (_this->stereoPacker.out.readBuf[i].l == INFINITY || _this->stereoPacker.out.readBuf[i].r == INFINITY) { flog::error("INFINITY in audio data"); }
|
||||
// if (_this->stereoPacker.out.readBuf[i].l == -INFINITY || _this->stereoPacker.out.readBuf[i].r == -INFINITY) { flog::error("-INFINITY in audio data"); }
|
||||
// }
|
||||
|
||||
memcpy(outputBuffer, _this->stereoPacker.out.readBuf, nBufferFrames * sizeof(dsp::stereo_t));
|
||||
_this->stereoPacker.out.flush();
|
||||
return 0;
|
||||
|
|
|
@ -2,6 +2,13 @@
|
|||
#include <utils/flog.h>
|
||||
|
||||
namespace hermes {
|
||||
const int SAMPLERATE_LIST[] = {
|
||||
48000,
|
||||
96000,
|
||||
192000,
|
||||
384000
|
||||
};
|
||||
|
||||
Client::Client(std::shared_ptr<net::Socket> sock) {
|
||||
this->sock = sock;
|
||||
|
||||
|
@ -33,6 +40,7 @@ namespace hermes {
|
|||
|
||||
void Client::setSamplerate(HermesLiteSamplerate samplerate) {
|
||||
writeReg(0, (uint32_t)samplerate << 24);
|
||||
blockSize = SAMPLERATE_LIST[samplerate] / 200;
|
||||
}
|
||||
|
||||
void Client::setFrequency(double freq) {
|
||||
|
@ -157,12 +165,15 @@ namespace hermes {
|
|||
void Client::worker() {
|
||||
uint8_t rbuf[2048];
|
||||
MetisUSBPacket* pkt = (MetisUSBPacket*)rbuf;
|
||||
int sampleCount = 0;
|
||||
|
||||
while (true) {
|
||||
// Wait for a packet or exit if connection closed
|
||||
int len = sock->recv(rbuf, 2048);
|
||||
if (len <= 0) { break; }
|
||||
|
||||
// Ignore anything that's not a USB packet
|
||||
// TODO: Gotta check the endpoint
|
||||
if (htons(pkt->hdr.signature) != HERMES_METIS_SIGNATURE || pkt->hdr.type != METIS_PKT_USB) {
|
||||
continue;
|
||||
}
|
||||
|
@ -183,9 +194,10 @@ namespace hermes {
|
|||
flog::warn("Got response! Reg={0}, Seq={1}", reg, (uint32_t)htonl(pkt->seq));
|
||||
}
|
||||
|
||||
// Decode and send IQ to stream
|
||||
// Decode and save IQ to buffer
|
||||
uint8_t* iq = &frame[8];
|
||||
for (int i = 0; i < 63; i++) {
|
||||
dsp::complex_t* writeBuf = &out.writeBuf[sampleCount];
|
||||
for (int i = 0; i < HERMES_SAMPLES_PER_FRAME; i++) {
|
||||
// Convert to 32bit
|
||||
int32_t si = ((uint32_t)iq[(i*8) + 0] << 16) | ((uint32_t)iq[(i*8) + 1] << 8) | (uint32_t)iq[(i*8) + 2];
|
||||
int32_t sq = ((uint32_t)iq[(i*8) + 3] << 16) | ((uint32_t)iq[(i*8) + 4] << 8) | (uint32_t)iq[(i*8) + 5];
|
||||
|
@ -195,18 +207,23 @@ namespace hermes {
|
|||
sq = (sq << 8) >> 8;
|
||||
|
||||
// Convert to float (IQ swapped for some reason)
|
||||
out.writeBuf[i].im = (float)si / (float)0x1000000;
|
||||
out.writeBuf[i].re = (float)sq / (float)0x1000000;
|
||||
writeBuf[i].im = (float)si / (float)0x1000000;
|
||||
writeBuf[i].re = (float)sq / (float)0x1000000;
|
||||
}
|
||||
sampleCount += HERMES_SAMPLES_PER_FRAME;
|
||||
|
||||
// If enough samples are in the buffer, send to stream
|
||||
if (sampleCount >= blockSize) {
|
||||
out.swap(sampleCount);
|
||||
sampleCount = 0;
|
||||
}
|
||||
out.swap(63);
|
||||
// TODO: Buffer the data to avoid having a very high DSP frame rate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Info> discover() {
|
||||
// TODO: Maybe try to instead detect on each interface as a work around for 0.0.0.0 not receiving anything?
|
||||
auto sock = net::openudp("0.0.0.0", 1024);
|
||||
// Open a UDP broadcast socket (TODO: Figure out why 255.255.255.255 doesn't work on windows with local = 0.0.0.0)
|
||||
auto sock = net::openudp("255.255.255.255", 1024, "0.0.0.0", 0, true);
|
||||
|
||||
// Build discovery packet
|
||||
uint8_t discoveryPkt[64];
|
||||
|
@ -225,6 +242,7 @@ namespace hermes {
|
|||
}
|
||||
}
|
||||
|
||||
// Await all responses
|
||||
std::vector<Info> devices;
|
||||
while (true) {
|
||||
// Wait for a response
|
||||
|
@ -258,7 +276,9 @@ namespace hermes {
|
|||
|
||||
devices.push_back(info);
|
||||
}
|
||||
|
||||
|
||||
// Close broadcast socket
|
||||
sock->close();
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
|
|
@ -7,11 +7,12 @@
|
|||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#define HERMES_METIS_REPEAT 5
|
||||
#define HERMES_METIS_TIMEOUT 1000
|
||||
#define HERMES_METIS_SIGNATURE 0xEFFE
|
||||
#define HERMES_HPSDR_USB_SYNC 0x7F
|
||||
#define HERMES_I2C_DELAY 50
|
||||
#define HERMES_METIS_REPEAT 5
|
||||
#define HERMES_METIS_TIMEOUT 1000
|
||||
#define HERMES_METIS_SIGNATURE 0xEFFE
|
||||
#define HERMES_HPSDR_USB_SYNC 0x7F
|
||||
#define HERMES_I2C_DELAY 50
|
||||
#define HERMES_SAMPLES_PER_FRAME 63
|
||||
|
||||
namespace hermes {
|
||||
enum MetisPacketType {
|
||||
|
@ -140,7 +141,7 @@ namespace hermes {
|
|||
|
||||
dsp::stream<dsp::complex_t> out;
|
||||
|
||||
//private:
|
||||
private:
|
||||
void sendMetisUSB(uint8_t endpoint, void* frame0, void* frame1 = NULL);
|
||||
void sendMetisControl(MetisControl ctrl);
|
||||
|
||||
|
@ -149,12 +150,12 @@ namespace hermes {
|
|||
|
||||
void writeI2C(I2CPort port, uint8_t addr, uint8_t reg, uint8_t data);
|
||||
|
||||
|
||||
|
||||
void worker();
|
||||
|
||||
double freq = 0;
|
||||
|
||||
int blockSize = 63;
|
||||
|
||||
std::thread workerThread;
|
||||
std::shared_ptr<net::Socket> sock;
|
||||
uint32_t usbSeq = 0;
|
||||
|
|
|
@ -17,7 +17,7 @@ SDRPP_MOD_INFO{
|
|||
/* Name: */ "hermes_source",
|
||||
/* Description: */ "Hermes Lite 2 source module for SDR++",
|
||||
/* Author: */ "Ryzerth",
|
||||
/* Version: */ 0, 1, 0,
|
||||
/* Version: */ 0, 1, 1,
|
||||
/* Max instances */ 1
|
||||
};
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <gui/smgui.h>
|
||||
#include <iio.h>
|
||||
#include <ad9361.h>
|
||||
|
||||
#include <utils/optionlist.h>
|
||||
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
|
||||
|
@ -15,16 +15,10 @@ SDRPP_MOD_INFO{
|
|||
/* Name: */ "plutosdr_source",
|
||||
/* Description: */ "PlutoSDR source module for SDR++",
|
||||
/* Author: */ "Ryzerth",
|
||||
/* Version: */ 0, 1, 0,
|
||||
/* Version: */ 0, 2, 0,
|
||||
/* Max instances */ 1
|
||||
};
|
||||
|
||||
const char* gainModes[] = {
|
||||
"manual", "fast_attack", "slow_attack", "hybrid"
|
||||
};
|
||||
|
||||
const char* gainModesTxt = "Manual\0Fast Attack\0Slow Attack\0Hybrid\0";
|
||||
|
||||
ConfigManager config;
|
||||
|
||||
class PlutoSDRSourceModule : public ModuleManager::Instance {
|
||||
|
@ -32,34 +26,63 @@ public:
|
|||
PlutoSDRSourceModule(std::string name) {
|
||||
this->name = name;
|
||||
|
||||
// Load configuration
|
||||
config.acquire();
|
||||
std::string _ip = config.conf["IP"];
|
||||
strcpy(&ip[3], _ip.c_str());
|
||||
sampleRate = config.conf["sampleRate"];
|
||||
gainMode = config.conf["gainMode"];
|
||||
gain = config.conf["gain"];
|
||||
if (config.conf.contains("IP")) {
|
||||
std::string _ip = config.conf["IP"];
|
||||
strcpy(&ip[3], _ip.c_str());
|
||||
}
|
||||
if (config.conf.contains("sampleRate")) {
|
||||
sampleRate = config.conf["sampleRate"];
|
||||
}
|
||||
if (config.conf.contains("bandwidth")) {
|
||||
bandwidth = config.conf["bandwidth"];
|
||||
}
|
||||
if (config.conf.contains("gainMode")) {
|
||||
gainMode = config.conf["gainMode"];
|
||||
}
|
||||
if (config.conf.contains("gain")) {
|
||||
gain = config.conf["gain"];
|
||||
}
|
||||
config.release();
|
||||
|
||||
// Generate the samplerate list and find srId
|
||||
bool found = false;
|
||||
int id = 0;
|
||||
for (double sr = 1000000; sr <= 20000000; sr += 500000) {
|
||||
sampleRates.push_back(sr);
|
||||
sampleRatesTxt += getBandwdithScaled(sr);
|
||||
sampleRatesTxt += '\0';
|
||||
|
||||
if (sr == sampleRate) {
|
||||
found = true;
|
||||
srId = id;
|
||||
}
|
||||
|
||||
id++;
|
||||
// Define valid samplerates
|
||||
for (int sr = 1000000; sr <= 61440000; sr += 500000) {
|
||||
samplerates.define(sr, getBandwdithScaled(sr), sr);
|
||||
}
|
||||
if (!found) {
|
||||
samplerates.define(61440000, getBandwdithScaled(61440000.0), 61440000.0);
|
||||
|
||||
// Set samplerate ID
|
||||
if (samplerates.keyExists(sampleRate)) {
|
||||
srId = samplerates.keyId(sampleRate);
|
||||
}
|
||||
else {
|
||||
srId = 0;
|
||||
sampleRate = sampleRates[0];
|
||||
sampleRate = samplerates.value(srId);
|
||||
}
|
||||
|
||||
// Define valid bandwidths
|
||||
bandwidths.define(0, "Auto", 0);
|
||||
for (int bw = 1000000.0; bw <= 52000000; bw += 500000) {
|
||||
bandwidths.define(bw, getBandwdithScaled(bw), bw);
|
||||
}
|
||||
|
||||
// Set bandwidth ID
|
||||
if (bandwidths.keyExists(bandwidth)) {
|
||||
bwId = bandwidths.keyId(bandwidth);
|
||||
}
|
||||
else {
|
||||
bwId = 0;
|
||||
bandwidth = bandwidths.value(bwId);
|
||||
}
|
||||
|
||||
// Define gain modes
|
||||
gainModes.define(0, "Manual", "manual");
|
||||
gainModes.define(1, "Fast Attack", "fast_attack");
|
||||
gainModes.define(2, "Slow Attack", "slow_attack");
|
||||
gainModes.define(3, "Hybrid", "hybrid");
|
||||
|
||||
// Register source
|
||||
handler.ctx = this;
|
||||
handler.selectHandler = menuSelected;
|
||||
handler.deselectHandler = menuDeselected;
|
||||
|
@ -120,12 +143,14 @@ private:
|
|||
PlutoSDRSourceModule* _this = (PlutoSDRSourceModule*)ctx;
|
||||
if (_this->running) { return; }
|
||||
|
||||
// TODO: INIT CONTEXT HERE
|
||||
// Open context
|
||||
_this->ctx = iio_create_context_from_uri(_this->ip);
|
||||
if (_this->ctx == NULL) {
|
||||
flog::error("Could not open pluto");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get phy and device handle
|
||||
_this->phy = iio_context_find_device(_this->ctx, "ad9361-phy");
|
||||
if (_this->phy == NULL) {
|
||||
flog::error("Could not connect to pluto phy");
|
||||
|
@ -139,17 +164,27 @@ private:
|
|||
return;
|
||||
}
|
||||
|
||||
// Configure pluto
|
||||
iio_channel_attr_write_bool(iio_device_find_channel(_this->phy, "altvoltage1", true), "powerdown", true);
|
||||
iio_channel_attr_write_bool(iio_device_find_channel(_this->phy, "altvoltage0", true), "powerdown", false);
|
||||
// Get RX channels
|
||||
_this->rxChan = iio_device_find_channel(_this->phy, "voltage0", false);
|
||||
_this->rxLO = iio_device_find_channel(_this->phy, "altvoltage0", true);
|
||||
|
||||
iio_channel_attr_write(iio_device_find_channel(_this->phy, "voltage0", false), "rf_port_select", "A_BALANCED");
|
||||
iio_channel_attr_write_longlong(iio_device_find_channel(_this->phy, "altvoltage0", true), "frequency", round(_this->freq)); // Freq
|
||||
iio_channel_attr_write_longlong(iio_device_find_channel(_this->phy, "voltage0", false), "sampling_frequency", round(_this->sampleRate)); // Sample rate
|
||||
iio_channel_attr_write(iio_device_find_channel(_this->phy, "voltage0", false), "gain_control_mode", gainModes[_this->gainMode]); // manual gain
|
||||
iio_channel_attr_write_longlong(iio_device_find_channel(_this->phy, "voltage0", false), "hardwaregain", round(_this->gain)); // gain
|
||||
// Enable RX LO and disable TX
|
||||
iio_channel_attr_write_bool(iio_device_find_channel(_this->phy, "altvoltage1", true), "powerdown", true);
|
||||
iio_channel_attr_write_bool(_this->rxLO, "powerdown", false);
|
||||
|
||||
// Configure RX channel
|
||||
iio_channel_attr_write(_this->rxChan, "rf_port_select", "A_BALANCED");
|
||||
iio_channel_attr_write_longlong(_this->rxLO, "frequency", round(_this->freq)); // Freq
|
||||
iio_channel_attr_write_bool(_this->rxChan, "filter_fir_en", true); // Digital filter
|
||||
iio_channel_attr_write_longlong(_this->rxChan, "sampling_frequency", round(_this->sampleRate)); // Sample rate
|
||||
iio_channel_attr_write_longlong(_this->rxChan, "hardwaregain", round(_this->gain)); // Gain
|
||||
iio_channel_attr_write(_this->rxChan, "gain_control_mode", _this->gainModes.value(_this->gainMode).c_str()); // Gain mode
|
||||
_this->setBandwidth(_this->bandwidth);
|
||||
|
||||
// Configure the ADC filters
|
||||
ad9361_set_bb_rate(_this->phy, round(_this->sampleRate));
|
||||
|
||||
// Start worker thread
|
||||
_this->running = true;
|
||||
_this->workerThread = std::thread(worker, _this);
|
||||
flog::info("PlutoSDRSourceModule '{0}': Start!", _this->name);
|
||||
|
@ -158,12 +193,14 @@ private:
|
|||
static void stop(void* ctx) {
|
||||
PlutoSDRSourceModule* _this = (PlutoSDRSourceModule*)ctx;
|
||||
if (!_this->running) { return; }
|
||||
|
||||
// Stop worker thread
|
||||
_this->running = false;
|
||||
_this->stream.stopWriter();
|
||||
_this->workerThread.join();
|
||||
_this->stream.clearWriteStop();
|
||||
|
||||
// DESTROY CONTEXT HERE
|
||||
// Close device
|
||||
if (_this->ctx != NULL) {
|
||||
iio_context_destroy(_this->ctx);
|
||||
_this->ctx = NULL;
|
||||
|
@ -176,7 +213,7 @@ private:
|
|||
PlutoSDRSourceModule* _this = (PlutoSDRSourceModule*)ctx;
|
||||
_this->freq = freq;
|
||||
if (_this->running) {
|
||||
// SET PLUTO FREQ HERE
|
||||
// Tune device
|
||||
iio_channel_attr_write_longlong(iio_device_find_channel(_this->phy, "altvoltage0", true), "frequency", round(freq));
|
||||
}
|
||||
flog::info("PlutoSDRSourceModule '{0}': Tune: {1}!", _this->name, freq);
|
||||
|
@ -196,8 +233,8 @@ private:
|
|||
|
||||
SmGui::LeftLabel("Samplerate");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo(CONCAT("##_pluto_sr_", _this->name), &_this->srId, _this->sampleRatesTxt.c_str())) {
|
||||
_this->sampleRate = _this->sampleRates[_this->srId];
|
||||
if (SmGui::Combo(CONCAT("##_pluto_sr_", _this->name), &_this->srId, _this->samplerates.txt)) {
|
||||
_this->sampleRate = _this->samplerates.value(_this->srId);
|
||||
core::setInputSampleRate(_this->sampleRate);
|
||||
config.acquire();
|
||||
config.conf["sampleRate"] = _this->sampleRate;
|
||||
|
@ -205,12 +242,24 @@ private:
|
|||
}
|
||||
if (_this->running) { SmGui::EndDisabled(); }
|
||||
|
||||
SmGui::LeftLabel("Bandwidth");
|
||||
SmGui::FillWidth();
|
||||
if (SmGui::Combo(CONCAT("##_pluto_bw_", _this->name), &_this->bwId, _this->bandwidths.txt)) {
|
||||
_this->bandwidth = _this->bandwidths.value(_this->bwId);
|
||||
if (_this->running) {
|
||||
_this->setBandwidth(_this->bandwidth);
|
||||
}
|
||||
config.acquire();
|
||||
config.conf["bandwidth"] = _this->bandwidth;
|
||||
config.release(true);
|
||||
}
|
||||
|
||||
SmGui::LeftLabel("Gain Mode");
|
||||
SmGui::FillWidth();
|
||||
SmGui::ForceSync();
|
||||
if (SmGui::Combo(CONCAT("##_gainmode_select_", _this->name), &_this->gainMode, gainModesTxt)) {
|
||||
if (SmGui::Combo(CONCAT("##_gainmode_select_", _this->name), &_this->gainMode, _this->gainModes.txt)) {
|
||||
if (_this->running) {
|
||||
iio_channel_attr_write(iio_device_find_channel(_this->phy, "voltage0", false), "gain_control_mode", gainModes[_this->gainMode]);
|
||||
iio_channel_attr_write(_this->rxChan, "gain_control_mode", _this->gainModes.value(_this->gainMode).c_str());
|
||||
}
|
||||
config.acquire();
|
||||
config.conf["gainMode"] = _this->gainMode;
|
||||
|
@ -222,7 +271,7 @@ private:
|
|||
SmGui::FillWidth();
|
||||
if (SmGui::SliderFloat(CONCAT("##_gain_select_", _this->name), &_this->gain, 0, 76)) {
|
||||
if (_this->running) {
|
||||
iio_channel_attr_write_longlong(iio_device_find_channel(_this->phy, "voltage0", false), "hardwaregain", round(_this->gain));
|
||||
iio_channel_attr_write_longlong(_this->rxChan, "hardwaregain", round(_this->gain));
|
||||
}
|
||||
config.acquire();
|
||||
config.conf["gain"] = _this->gain;
|
||||
|
@ -231,72 +280,86 @@ private:
|
|||
if (_this->gainMode) { SmGui::EndDisabled(); }
|
||||
}
|
||||
|
||||
void setBandwidth(int bw) {
|
||||
if (bw > 0) {
|
||||
iio_channel_attr_write_longlong(rxChan, "rf_bandwidth", bw);
|
||||
}
|
||||
else {
|
||||
iio_channel_attr_write_longlong(rxChan, "rf_bandwidth", std::min<int>(sampleRate, 52000000));
|
||||
}
|
||||
}
|
||||
|
||||
static void worker(void* ctx) {
|
||||
PlutoSDRSourceModule* _this = (PlutoSDRSourceModule*)ctx;
|
||||
int blockSize = _this->sampleRate / 200.0f;
|
||||
|
||||
struct iio_channel *rx0_i, *rx0_q;
|
||||
struct iio_buffer* rxbuf;
|
||||
|
||||
rx0_i = iio_device_find_channel(_this->dev, "voltage0", 0);
|
||||
rx0_q = iio_device_find_channel(_this->dev, "voltage1", 0);
|
||||
// Acquire channels
|
||||
iio_channel* rx0_i = iio_device_find_channel(_this->dev, "voltage0", 0);
|
||||
iio_channel* rx0_q = iio_device_find_channel(_this->dev, "voltage1", 0);
|
||||
|
||||
// Start streaming
|
||||
iio_channel_enable(rx0_i);
|
||||
iio_channel_enable(rx0_q);
|
||||
|
||||
rxbuf = iio_device_create_buffer(_this->dev, blockSize, false);
|
||||
// Allocate buffer
|
||||
iio_buffer* rxbuf = iio_device_create_buffer(_this->dev, blockSize, false);
|
||||
if (!rxbuf) {
|
||||
flog::error("Could not create RX buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
// Receive loop
|
||||
while (true) {
|
||||
// Read samples here
|
||||
// TODO: RECEIVE HERE
|
||||
// Read samples
|
||||
iio_buffer_refill(rxbuf);
|
||||
|
||||
// Get buffer pointer
|
||||
int16_t* buf = (int16_t*)iio_buffer_first(rxbuf, rx0_i);
|
||||
|
||||
for (int i = 0; i < blockSize; i++) {
|
||||
_this->stream.writeBuf[i].re = (float)buf[i * 2] / 32768.0f;
|
||||
_this->stream.writeBuf[i].im = (float)buf[(i * 2) + 1] / 32768.0f;
|
||||
}
|
||||
|
||||
// Convert samples to CF32
|
||||
volk_16i_s32f_convert_32f((float*)_this->stream.writeBuf, buf, 32768.0f, blockSize * 2);
|
||||
|
||||
// Send out the samples
|
||||
if (!_this->stream.swap(blockSize)) { break; };
|
||||
}
|
||||
|
||||
// Stop streaming
|
||||
iio_channel_disable(rx0_i);
|
||||
iio_channel_disable(rx0_q);
|
||||
|
||||
// Free buffer
|
||||
iio_buffer_destroy(rxbuf);
|
||||
}
|
||||
|
||||
std::string name;
|
||||
bool enabled = true;
|
||||
dsp::stream<dsp::complex_t> stream;
|
||||
float sampleRate;
|
||||
SourceManager::SourceHandler handler;
|
||||
std::thread workerThread;
|
||||
struct iio_context* ctx = NULL;
|
||||
struct iio_device* phy = NULL;
|
||||
struct iio_device* dev = NULL;
|
||||
iio_context* ctx = NULL;
|
||||
iio_device* phy = NULL;
|
||||
iio_device* dev = NULL;
|
||||
iio_channel* rxLO = NULL;
|
||||
iio_channel* rxChan = NULL;
|
||||
bool running = false;
|
||||
bool ipMode = true;
|
||||
|
||||
double freq;
|
||||
char ip[1024] = "ip:192.168.2.1";
|
||||
float sampleRate = 4000000;
|
||||
int bandwidth = 0;
|
||||
int gainMode = 0;
|
||||
float gain = 0;
|
||||
int srId = 0;
|
||||
|
||||
std::vector<double> sampleRates;
|
||||
std::string sampleRatesTxt;
|
||||
int srId = 0;
|
||||
int bwId = 0;
|
||||
|
||||
OptionList<int, double> samplerates;
|
||||
OptionList<int, double> bandwidths;
|
||||
OptionList<int, std::string> gainModes;
|
||||
};
|
||||
|
||||
MOD_EXPORT void _INIT_() {
|
||||
json defConf;
|
||||
defConf["IP"] = "192.168.2.1";
|
||||
defConf["sampleRate"] = 4000000.0f;
|
||||
defConf["gainMode"] = 0;
|
||||
defConf["gain"] = 0.0f;
|
||||
json defConf = {};
|
||||
config.setPath(core::args["root"].s() + "/plutosdr_source_config.json");
|
||||
config.load(defConf);
|
||||
config.enableAutoSave();
|
||||
|
|
|
@ -17,7 +17,7 @@ SDRPP_MOD_INFO{
|
|||
/* Name: */ "rfspace_source",
|
||||
/* Description: */ "RFspace source module for SDR++",
|
||||
/* Author: */ "Ryzerth",
|
||||
/* Version: */ 0, 1, 0,
|
||||
/* Version: */ 0, 1, 1,
|
||||
/* Max instances */ 1
|
||||
};
|
||||
|
||||
|
@ -231,7 +231,7 @@ private:
|
|||
}
|
||||
|
||||
// Create samplerate list
|
||||
auto srs = client->getValidSampleRates();
|
||||
auto srs = client->getSamplerates();
|
||||
sampleRates.clear();
|
||||
for (auto& sr : srs) {
|
||||
sampleRates.define(sr, getBandwdithScaled(sr), sr);
|
||||
|
@ -317,7 +317,7 @@ private:
|
|||
dsp::stream<dsp::complex_t> stream;
|
||||
SourceManager::SourceHandler handler;
|
||||
|
||||
rfspace::RFspaceClient client;
|
||||
std::shared_ptr<rfspace::Client> client;
|
||||
};
|
||||
|
||||
MOD_EXPORT void _INIT_() {
|
||||
|
|
|
@ -6,15 +6,13 @@
|
|||
using namespace std::chrono_literals;
|
||||
|
||||
namespace rfspace {
|
||||
RFspaceClientClass::RFspaceClientClass(net::Conn conn, net::Conn udpConn, dsp::stream<dsp::complex_t>* out) {
|
||||
client = std::move(conn);
|
||||
udpClient = std::move(udpConn);
|
||||
Client::Client(std::shared_ptr<net::Socket> tcp, std::shared_ptr<net::Socket> udp, dsp::stream<dsp::complex_t>* out) {
|
||||
this->tcp = tcp;
|
||||
this->udp = udp;
|
||||
output = out;
|
||||
|
||||
// Allocate buffers
|
||||
rbuffer = new uint8_t[RFSPACE_MAX_SIZE];
|
||||
sbuffer = new uint8_t[RFSPACE_MAX_SIZE];
|
||||
ubuffer = new uint8_t[RFSPACE_MAX_SIZE];
|
||||
|
||||
// Clear write stop of stream just in case
|
||||
output->clearWriteStop();
|
||||
|
@ -22,9 +20,9 @@ namespace rfspace {
|
|||
// Send UDP packet so that a router opens the port
|
||||
sendDummyUDP();
|
||||
|
||||
// Start readers
|
||||
client->readAsync(sizeof(tcpHeader), (uint8_t*)&tcpHeader, tcpHandler, this);
|
||||
udpClient->readAsync(RFSPACE_MAX_SIZE, ubuffer, udpHandler, this);
|
||||
// Start workers
|
||||
tcpWorkerThread = std::thread(&Client::tcpWorker, this);
|
||||
udpWorkerThread = std::thread(&Client::udpWorker, this);
|
||||
|
||||
// Get device ID and wait for response
|
||||
getControlItem(RFSPACE_CTRL_ITEM_PROD_ID, NULL, 0);
|
||||
|
@ -43,22 +41,20 @@ namespace rfspace {
|
|||
setPort(RFSPACE_RF_PORT_1);
|
||||
|
||||
// Start heartbeat
|
||||
heartBeatThread = std::thread(&RFspaceClientClass::heartBeatWorker, this);
|
||||
heartBeatThread = std::thread(&Client::heartBeatWorker, this);
|
||||
}
|
||||
|
||||
RFspaceClientClass::~RFspaceClientClass() {
|
||||
Client::~Client() {
|
||||
close();
|
||||
delete[] rbuffer;
|
||||
delete[] sbuffer;
|
||||
delete[] ubuffer;
|
||||
}
|
||||
|
||||
void RFspaceClientClass::sendDummyUDP() {
|
||||
void Client::sendDummyUDP() {
|
||||
uint8_t dummy = 0x5A;
|
||||
udpClient->write(1, &dummy);
|
||||
udp->send(&dummy, 1);
|
||||
}
|
||||
|
||||
int RFspaceClientClass::getControlItem(ControlItem item, void* param, int len) {
|
||||
int Client::getControlItem(ControlItem item, void* param, int len) {
|
||||
// Build packet
|
||||
uint16_t* header = (uint16_t*)&sbuffer[0];
|
||||
uint16_t* item_val = (uint16_t*)&sbuffer[2];
|
||||
|
@ -66,12 +62,12 @@ namespace rfspace {
|
|||
*item_val = item;
|
||||
|
||||
// Send packet
|
||||
client->write(4, sbuffer);
|
||||
tcp->send(sbuffer, 4);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void RFspaceClientClass::setControlItem(ControlItem item, void* param, int len) {
|
||||
void Client::setControlItem(ControlItem item, void* param, int len) {
|
||||
// Build packet
|
||||
uint16_t* header = (uint16_t*)&sbuffer[0];
|
||||
uint16_t* item_val = (uint16_t*)&sbuffer[2];
|
||||
|
@ -80,10 +76,10 @@ namespace rfspace {
|
|||
memcpy(&sbuffer[4], param, len);
|
||||
|
||||
// Send packet
|
||||
client->write(len + 4, sbuffer);
|
||||
tcp->send(sbuffer, len + 4);
|
||||
}
|
||||
|
||||
void RFspaceClientClass::setControlItemWithChanID(ControlItem item, uint8_t chanId, void* param, int len) {
|
||||
void Client::setControlItemWithChanID(ControlItem item, uint8_t chanId, void* param, int len) {
|
||||
// Build packet
|
||||
uint16_t* header = (uint16_t*)&sbuffer[0];
|
||||
uint16_t* item_val = (uint16_t*)&sbuffer[2];
|
||||
|
@ -94,10 +90,10 @@ namespace rfspace {
|
|||
memcpy(&sbuffer[5], param, len);
|
||||
|
||||
// Send packet
|
||||
client->write(len + 5, sbuffer);
|
||||
tcp->send(sbuffer, len + 5);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> RFspaceClientClass::getValidSampleRates() {
|
||||
std::vector<uint32_t> Client::getSamplerates() {
|
||||
std::vector<uint32_t> sr;
|
||||
|
||||
switch (deviceId) {
|
||||
|
@ -119,92 +115,145 @@ namespace rfspace {
|
|||
return sr;
|
||||
}
|
||||
|
||||
void RFspaceClientClass::setFrequency(uint64_t freq) {
|
||||
void Client::setFrequency(uint64_t freq) {
|
||||
setControlItemWithChanID(RFSPACE_CTRL_ITEM_NCO_FREQUENCY, 0, &freq, 5);
|
||||
}
|
||||
|
||||
void RFspaceClientClass::setPort(RFPort port) {
|
||||
void Client::setPort(RFPort port) {
|
||||
uint8_t value = port;
|
||||
setControlItemWithChanID(RFSPACE_CTRL_ITEM_RF_PORT, 0, &value, sizeof(value));
|
||||
}
|
||||
|
||||
void RFspaceClientClass::setGain(int8_t gain) {
|
||||
void Client::setGain(int8_t gain) {
|
||||
setControlItemWithChanID(RFSPACE_CTRL_ITEM_RF_GAIN, 0, &gain, sizeof(gain));
|
||||
}
|
||||
|
||||
void RFspaceClientClass::setSampleRate(uint32_t sampleRate) {
|
||||
void Client::setSampleRate(uint32_t sampleRate) {
|
||||
// Acquire the buffer variables
|
||||
std::lock_guard<std::mutex> lck(bufferMtx);
|
||||
|
||||
// Update block size
|
||||
blockSize = sampleRate / 200;
|
||||
|
||||
// Send samplerate to device
|
||||
setControlItemWithChanID(RFSPACE_CTRL_ITEM_IQ_SAMP_RATE, 0, &sampleRate, sizeof(sampleRate));
|
||||
}
|
||||
|
||||
void RFspaceClientClass::start(SampleFormat sampleFormat, SampleDepth sampleDepth) {
|
||||
void Client::start(SampleFormat sampleFormat, SampleDepth sampleDepth) {
|
||||
// Acquire the buffer variables
|
||||
std::lock_guard<std::mutex> lck(bufferMtx);
|
||||
|
||||
// Reset buffer
|
||||
inBuffer = 0;
|
||||
|
||||
// Start device
|
||||
uint8_t args[4] = { (uint8_t)sampleFormat, (uint8_t)RFSPACE_STATE_RUN, (uint8_t)sampleDepth, 0 };
|
||||
setControlItem(RFSPACE_CTRL_ITEM_STATE, args, sizeof(args));
|
||||
}
|
||||
|
||||
void RFspaceClientClass::stop() {
|
||||
void Client::stop() {
|
||||
uint8_t args[4] = { 0, RFSPACE_STATE_IDLE, 0, 0 };
|
||||
setControlItem(RFSPACE_CTRL_ITEM_STATE, args, sizeof(args));
|
||||
}
|
||||
|
||||
void RFspaceClientClass::close() {
|
||||
void Client::close() {
|
||||
// Stop UDP worker
|
||||
output->stopWriter();
|
||||
udp->close();
|
||||
if (udpWorkerThread.joinable()) { udpWorkerThread.join(); }
|
||||
output->clearWriteStop();
|
||||
|
||||
// Stop heartbeat worker
|
||||
stopHeartBeat = true;
|
||||
heartBeatCnd.notify_all();
|
||||
if (heartBeatThread.joinable()) { heartBeatThread.join(); }
|
||||
client->close();
|
||||
udpClient->close();
|
||||
output->clearWriteStop();
|
||||
|
||||
// Stop TCP worker
|
||||
tcp->close();
|
||||
if (tcpWorkerThread.joinable()) { tcpWorkerThread.join(); }
|
||||
}
|
||||
|
||||
bool RFspaceClientClass::isOpen() {
|
||||
return client->isOpen();
|
||||
bool Client::isOpen() {
|
||||
return tcp->isOpen() || udp->isOpen();
|
||||
}
|
||||
|
||||
void RFspaceClientClass::tcpHandler(int count, uint8_t* buf, void* ctx) {
|
||||
RFspaceClientClass* _this = (RFspaceClientClass*)ctx;
|
||||
uint8_t type = _this->tcpHeader >> 13;
|
||||
uint16_t size = _this->tcpHeader & 0b1111111111111;
|
||||
void Client::tcpWorker() {
|
||||
// Allocate receive buffer
|
||||
uint8_t* buffer = new uint8_t[RFSPACE_MAX_SIZE];
|
||||
|
||||
// Read the rest of the data
|
||||
if (size > 2) {
|
||||
_this->client->read(size - 2, &_this->rbuffer[2]);
|
||||
}
|
||||
// Receive loop
|
||||
while (true) {
|
||||
// Receive header
|
||||
uint16_t header;
|
||||
if (tcp->recv((uint8_t*)&header, sizeof(uint16_t), true) <= 0) { break; }
|
||||
|
||||
// flog::warn("TCP received: {0} {1}", type, size);
|
||||
// Decode header
|
||||
uint8_t type = header >> 13;
|
||||
uint16_t size = header & 0b1111111111111;
|
||||
|
||||
// Check for a device ID
|
||||
uint16_t* controlItem = (uint16_t*)&_this->rbuffer[2];
|
||||
if (type == RFSPACE_MSG_TYPE_T2H_SET_CTRL_ITEM_RESP && *controlItem == RFSPACE_CTRL_ITEM_PROD_ID) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(_this->devIdMtx);
|
||||
_this->deviceId = (DeviceID)*(uint32_t*)&_this->rbuffer[4];
|
||||
_this->devIdAvailable = true;
|
||||
// Receive data
|
||||
if (tcp->recv(buffer, size - 2, true, RFSPACE_TIMEOUT_MS) <= 0) { break; }
|
||||
|
||||
// Check for a device ID
|
||||
uint16_t* controlItem = (uint16_t*)&buffer[0];
|
||||
if (type == RFSPACE_MSG_TYPE_T2H_SET_CTRL_ITEM_RESP && *controlItem == RFSPACE_CTRL_ITEM_PROD_ID) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(devIdMtx);
|
||||
deviceId = (DeviceID)*(uint32_t*)&buffer[2];
|
||||
devIdAvailable = true;
|
||||
}
|
||||
devIdCnd.notify_all();
|
||||
}
|
||||
_this->devIdCnd.notify_all();
|
||||
}
|
||||
|
||||
// Restart an async read
|
||||
_this->client->readAsync(sizeof(_this->tcpHeader), (uint8_t*)&_this->tcpHeader, tcpHandler, _this);
|
||||
// Free receive buffer
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
void RFspaceClientClass::udpHandler(int count, uint8_t* buf, void* ctx) {
|
||||
RFspaceClientClass* _this = (RFspaceClientClass*)ctx;
|
||||
uint16_t hdr = (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
|
||||
uint8_t type = hdr >> 13;
|
||||
uint16_t size = hdr & 0b1111111111111;
|
||||
void Client::udpWorker() {
|
||||
// Allocate receive buffer
|
||||
uint8_t* buffer = new uint8_t[RFSPACE_MAX_SIZE];
|
||||
uint16_t* header = (uint16_t*)&buffer[0];
|
||||
|
||||
if (type == RFSPACE_MSG_TYPE_T2H_DATA_ITEM_0) {
|
||||
int16_t* samples = (int16_t*)&buf[4];
|
||||
int sampCount = (size - 4) / (2 * sizeof(int16_t));
|
||||
volk_16i_s32f_convert_32f((float*)_this->output->writeBuf, samples, 32768.0f, sampCount * 2);
|
||||
_this->output->swap(sampCount);
|
||||
// Receive loop
|
||||
while (true) {
|
||||
// Receive datagram
|
||||
int rsize = udp->recv(buffer, RFSPACE_MAX_SIZE);
|
||||
if (rsize <= 0) { break; }
|
||||
|
||||
// Decode header
|
||||
uint8_t type = (*header) >> 13;
|
||||
uint16_t size = (*header) & 0b1111111111111;
|
||||
|
||||
if (rsize != size) {
|
||||
flog::error("Datagram size mismatch: {} vs {}", rsize, size);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for a sample packet
|
||||
if (type == RFSPACE_MSG_TYPE_T2H_DATA_ITEM_0) {
|
||||
// Acquire the buffer variables
|
||||
std::lock_guard<std::mutex> lck(bufferMtx);
|
||||
|
||||
// Convert samples to complex float
|
||||
int16_t* samples = (int16_t*)&buffer[4];
|
||||
int sampCount = (size - 4) / (2 * sizeof(int16_t));
|
||||
volk_16i_s32f_convert_32f((float*)&output->writeBuf[inBuffer], samples, 32768.0f, sampCount * 2);
|
||||
inBuffer += sampCount;
|
||||
|
||||
// Send out samples if enough are buffered
|
||||
if (inBuffer >= blockSize) {
|
||||
if (!output->swap(inBuffer)) { break; };
|
||||
inBuffer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Restart an async read
|
||||
_this->udpClient->readAsync(RFSPACE_MAX_SIZE, _this->ubuffer, udpHandler, _this);
|
||||
// Free receive buffer
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
void RFspaceClientClass::heartBeatWorker() {
|
||||
void Client::heartBeatWorker() {
|
||||
uint8_t dummy[4];
|
||||
while (true) {
|
||||
getControlItem(RFSPACE_CTRL_ITEM_STATE, dummy, sizeof(dummy));
|
||||
|
@ -216,11 +265,9 @@ namespace rfspace {
|
|||
}
|
||||
}
|
||||
|
||||
RFspaceClient connect(std::string host, uint16_t port, dsp::stream<dsp::complex_t>* out) {
|
||||
net::Conn conn = net::connect(host, port);
|
||||
if (!conn) { return NULL; }
|
||||
net::Conn udpConn = net::openUDP("0.0.0.0", port, host, port, true);
|
||||
if (!udpConn) { return NULL; }
|
||||
return RFspaceClient(new RFspaceClientClass(std::move(conn), std::move(udpConn), out));
|
||||
std::shared_ptr<Client> connect(std::string host, uint16_t port, dsp::stream<dsp::complex_t>* out) {
|
||||
auto tcp = net::connect(host, port);
|
||||
auto udp = net::openudp(host, port, "0.0.0.0", port);
|
||||
return std::make_shared<Client>(tcp, udp, out);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#pragma once
|
||||
#include <utils/networking.h>
|
||||
#include <utils/net.h>
|
||||
#include <dsp/stream.h>
|
||||
#include <dsp/types.h>
|
||||
#include <atomic>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
|
||||
#define RFSPACE_MAX_SIZE 8192
|
||||
#define RFSPACE_HEARTBEAT_INTERVAL_MS 1000
|
||||
|
@ -96,10 +97,10 @@ namespace rfspace {
|
|||
RFSPACE_CTRL_ITEM_ERROR_LOG = 0x0410
|
||||
};
|
||||
|
||||
class RFspaceClientClass {
|
||||
class Client {
|
||||
public:
|
||||
RFspaceClientClass(net::Conn conn, net::Conn udpConn, dsp::stream<dsp::complex_t>* out);
|
||||
~RFspaceClientClass();
|
||||
Client(std::shared_ptr<net::Socket> tcp, std::shared_ptr<net::Socket> udp, dsp::stream<dsp::complex_t>* out);
|
||||
~Client();
|
||||
|
||||
void sendDummyUDP();
|
||||
|
||||
|
@ -107,7 +108,7 @@ namespace rfspace {
|
|||
void setControlItem(ControlItem item, void* param, int len);
|
||||
void setControlItemWithChanID(ControlItem item, uint8_t chanId, void* param, int len);
|
||||
|
||||
std::vector<uint32_t> getValidSampleRates();
|
||||
std::vector<uint32_t> getSamplerates();
|
||||
|
||||
void setFrequency(uint64_t freq);
|
||||
void setPort(RFPort port);
|
||||
|
@ -123,21 +124,22 @@ namespace rfspace {
|
|||
DeviceID deviceId;
|
||||
|
||||
private:
|
||||
static void tcpHandler(int count, uint8_t* buf, void* ctx);
|
||||
static void udpHandler(int count, uint8_t* buf, void* ctx);
|
||||
void tcpWorker();
|
||||
void udpWorker();
|
||||
void heartBeatWorker();
|
||||
|
||||
net::Conn client;
|
||||
net::Conn udpClient;
|
||||
std::shared_ptr<net::Socket> tcp;
|
||||
std::shared_ptr<net::Socket> udp;
|
||||
|
||||
dsp::stream<dsp::complex_t>* output;
|
||||
|
||||
uint16_t tcpHeader;
|
||||
uint16_t udpHeader;
|
||||
|
||||
uint8_t* rbuffer = NULL;
|
||||
uint8_t* sbuffer = NULL;
|
||||
uint8_t* ubuffer = NULL;
|
||||
|
||||
std::thread tcpWorkerThread;
|
||||
std::thread udpWorkerThread;
|
||||
|
||||
std::thread heartBeatThread;
|
||||
std::mutex heartBeatMtx;
|
||||
|
@ -147,10 +149,12 @@ namespace rfspace {
|
|||
bool devIdAvailable = false;
|
||||
std::condition_variable devIdCnd;
|
||||
std::mutex devIdMtx;
|
||||
|
||||
std::mutex bufferMtx;
|
||||
int blockSize = 256;
|
||||
int inBuffer = 0;
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<RFspaceClientClass> RFspaceClient;
|
||||
|
||||
RFspaceClient connect(std::string host, uint16_t port, dsp::stream<dsp::complex_t>* out);
|
||||
std::shared_ptr<Client> connect(std::string host, uint16_t port, dsp::stream<dsp::complex_t>* out);
|
||||
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue