Porównaj commity

...

27 Commity

Autor SHA1 Wiadomość Data
AlexandreRouma 11a7c382e8 update more github action versions 2024-01-28 17:28:07 +01:00
AlexandreRouma 54276177ae update github action version 2024-01-28 17:25:27 +01:00
AlexandreRouma e6a02a3944 fix bad plutosdr bandwidth selection at very high samplerates 2024-01-27 22:52:11 +01:00
AlexandreRouma 00e6832055 add plutosdr bandwidth selection for #563 2024-01-27 22:49:39 +01:00
AlexandreRouma bc8baca190 clean up plutosdr source code 2024-01-27 21:35:13 +01:00
AlexandreRouma 08e75b6d14 fix gain mode selection not always applying 2024-01-27 21:30:06 +01:00
AlexandreRouma e9ec79f6ef modernise gain mode selection for plutosdr 2024-01-27 21:29:44 +01:00
AlexandreRouma cd996292bc revamp plutosdr samplerate selection code 2024-01-27 21:12:26 +01:00
AlexandreRouma 06b7ad5c98 remove old useless debug code from audio sink 2024-01-27 16:34:54 +01:00
AlexandreRouma 38a95b4011 update SDRplay API in MacOS CI 2024-01-26 19:31:32 +01:00
AlexandreRouma f6052d913a bump version of updated modules 2024-01-26 19:00:36 +01:00
AlexandreRouma 2b00370cf3 Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2024-01-26 18:47:18 +01:00
AlexandreRouma 09f4071803 Switch SDRplay API in Linux nightly builds to version 3.12 2024-01-26 18:47:13 +01:00
AlexandreRouma e61ef29e0f
Merge pull request #1292 from daviderud/aligned_master
additions and corrections to NL band plan
2024-01-26 17:56:54 +01:00
AlexandreRouma eb36f86d41 added missing include 2024-01-26 17:21:51 +01:00
AlexandreRouma 29889a289f Merge branch 'master' of https://github.com/AlexandreRouma/SDRPlusPlus 2024-01-26 16:57:19 +01:00
AlexandreRouma 859af77bd3 revamp RFspace source to use new networking library and fix buffering 2024-01-26 16:57:11 +01:00
Davide Rovelli 0a3d1de02f removed tabs and unnecessary pipes 2024-01-26 07:43:01 +01:00
AlexandreRouma db3fbd2975
update issue template to reflect that fact that filling it out is not optional 2024-01-26 01:40:17 +01:00
AlexandreRouma f5adc7c587 fix hermes lite buffering 2024-01-25 23:28:03 +01:00
AlexandreRouma 255988ee46 fix hermes lite enumeration issues and fix copy paste fail in network library 2024-01-25 22:27:59 +01:00
AlexandreRouma 68bf2fc16f fix bad network lib broadcast implementation 2024-01-25 21:34:13 +01:00
AlexandreRouma 3aa167701e fix networking library to allow multicast 2024-01-25 20:27:04 +01:00
AlexandreRouma 97c1a132a5 move zoom waterfall's zoom function in the cpp file to avoid annoying recomps 2024-01-25 19:48:04 +01:00
AlexandreRouma 118e56897c Add ubuntu mantic CI build 2024-01-25 15:41:23 +01:00
AlexandreRouma af8c085d43 switch osx to macos 2024-01-24 18:14:29 +01:00
Davide Rovelli 708f74e179
additions and corrections 2024-01-24 06:14:00 +01:00
25 zmienionych plików z 910 dodań i 335 usunięć

Wyświetl plik

@ -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**

Wyświetl plik

@ -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

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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);

Wyświetl plik

@ -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);
}
}

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -0,0 +1,4 @@
FROM ubuntu:mantic
ENV DEBIAN_FRONTEND=noninteractive
COPY do_build.sh /root
RUN chmod +x /root/do_build.sh

Wyświetl plik

@ -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'

Wyświetl plik

@ -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)

Wyświetl plik

@ -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
}
]
}

Wyświetl plik

@ -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;

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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;

Wyświetl plik

@ -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
};

Wyświetl plik

@ -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();

Wyświetl plik

@ -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_() {

Wyświetl plik

@ -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);
}
}

Wyświetl plik

@ -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);
}