Merge branch 'master' of https://github.com/f4exb/sdrangel into osx

This commit is contained in:
ZigaS 2018-11-30 23:54:02 +01:00
commit 6ec5d62205
1530 changed files with 142443 additions and 42799 deletions

42
.gitignore vendored
View File

@ -1,20 +1,22 @@
CMakeLists.txt.user*
build*
qtbuild/*
sdriq/*
presets/*
LOCAL/*
sdrangelove.supp
.cproject
.project
.pydevproject
.settings/
*.cs
*.pro.user
.idea/*
debian/sdrangel/*
debian/sdrangel.substvars
debian/files
debian/sdrangel.debhelper.log
debian/debhelper-build-stamp
obj-x86_64-linux-gnu/*
CMakeLists.txt.user*
build*
qtbuild/*
sdriq/*
presets/*
LOCAL/*
sdrangelove.supp
.cproject
.project
.pydevproject
.vscode/
.settings/
*.cs
*.pro.user
.idea/*
rescuesdriq/rescuesdriq
debian/sdrangel/*
debian/sdrangel.substvars
debian/files
debian/sdrangel.debhelper.log
debian/debhelper-build-stamp
obj-x86_64-linux-gnu/*

View File

@ -13,7 +13,7 @@ set(CMAKE_SKIP_BUILD_RPATH FALSE)
# when building, don't use the install RPATH already
# (but later on when installing)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
@ -30,6 +30,7 @@ option(DEBUG_OUTPUT "Print debug messages" OFF)
option(SANITIZE_ADDRESS "Activate memory address sanitization" OFF)
option(HOST_RPI "Compiling on RPi" OFF)
option(RX_SAMPLE_24BIT "Internal 24 bit Rx DSP" OFF)
option(NO_DSP_SIMD "Do not use SIMD instructions for DSP even if available" OFF)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
@ -55,12 +56,11 @@ set(CMAKE_AUTOMOC ON)
find_package(Qt5Core 5.0 REQUIRED)
find_package(Qt5Widgets 5.0 REQUIRED)
find_package(Qt5Multimedia 5.0 REQUIRED)
#find_package(QT5OpenGL 5.0 REQUIRED)
find_package(Qt5OpenGL 5.0 REQUIRED)
find_package(OpenGL REQUIRED)
find_package(PkgConfig)
find_package(Boost REQUIRED)
find_package(FFTW3F)
find_package(JRTPLib)
if (NOT BUILD_DEBIAN)
find_package(LibDSDcc)
@ -106,7 +106,7 @@ if (${ARCHITECTURE} MATCHES "x86_64|AMD64|x86")
EXECUTE_PROCESS( COMMAND grep flags /proc/cpuinfo OUTPUT_VARIABLE CPU_FLAGS )
# if (${CPU_FLAGS} MATCHES "avx2")
# set(HAS_AVX2 ON CACHE BOOL "Architecture has AVX2 SIMD enabled")
# if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX)
# if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
# set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mavx2" )
# set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -mavx2" )
# message(STATUS "Use AVX2 SIMD instructions")
@ -117,7 +117,7 @@ if (${ARCHITECTURE} MATCHES "x86_64|AMD64|x86")
# endif()
if (${CPU_FLAGS} MATCHES "sse4_1")
set(HAS_SSE4_1 ON CACHE BOOL "Architecture has SSE 4.1 SIMD enabled")
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX)
if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -msse4.1" )
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -msse4.1" )
message(STATUS "Use SSE 4.1 SIMD instructions")
@ -134,7 +134,7 @@ if (${ARCHITECTURE} MATCHES "x86_64|AMD64|x86")
endif()
if (${CPU_FLAGS} MATCHES "ssse3")
set(HAS_SSSE3 ON CACHE BOOL "Architecture has SSSE3 SIMD enabled")
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX)
if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mssse3" )
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -mssse3" )
message(STATUS "Use SSSE3 SIMD instructions")
@ -151,7 +151,7 @@ if (${ARCHITECTURE} MATCHES "x86_64|AMD64|x86")
endif()
if (${CPU_FLAGS} MATCHES "sse2")
set(HAS_SSE2 ON CACHE BOOL "Architecture has SSE2 SIMD enabled")
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX)
if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -msse2" )
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -msse2" )
message(STATUS "Use SSE2 SIMD instructions")
@ -170,7 +170,7 @@ elseif (${ARCHITECTURE} MATCHES "armv7l")
EXECUTE_PROCESS( COMMAND grep Features /proc/cpuinfo OUTPUT_VARIABLE CPU_FLAGS )
if (${CPU_FLAGS} MATCHES "neon")
set(HAS_NEON ON CACHE BOOL "Architecture has NEON SIMD enabled")
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX)
if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mfpu=neon" )
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -mfpu=neon" )
message(STATUS "Use NEON SIMD instructions")
@ -181,7 +181,7 @@ elseif (${ARCHITECTURE} MATCHES "armv7l")
endif()
elseif (${ARCHITECTURE} MATCHES "aarch64")
set(HAS_NEON ON CACHE BOOL FORCE "Architecture has NEON SIMD enabled")
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX)
if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
message(STATUS "Aarch64 always has NEON SIMD instructions")
add_definitions(-DUSE_NEON)
endif()
@ -204,13 +204,29 @@ if (SANITIZE_ADDRESS)
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} -fsanitize=address")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -fmax-errors=10 -ffast-math -ftree-vectorize ${EXTRA_FLAGS}")
if (NO_DSP_SIMD)
message(STATUS "Not compiling with SIMD instructions for DSP even if available")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNO_DSP_SIMD")
else()
message(STATUS "Compiling with SIMD instructions for DSP if available")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wvla -Woverloaded-virtual -ffast-math -ftree-vectorize ${EXTRA_FLAGS}")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if (BUILD_DEBIAN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmax-errors=1")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmax-errors=10")
endif()
endif()
##############################################################################
# base libraries
add_subdirectory(sdrbase)
add_subdirectory(sdrgui)
add_subdirectory(sdrsrv)
add_subdirectory(sdrbench)
add_subdirectory(httpserver)
add_subdirectory(logging)
add_subdirectory(qrtplib)
@ -218,6 +234,7 @@ add_subdirectory(swagger)
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_SOURCE_DIR}/exports
${CMAKE_SOURCE_DIR}/sdrbase
${CMAKE_SOURCE_DIR}/sdrgui
${CMAKE_SOURCE_DIR}/logging
@ -239,7 +256,7 @@ set(sdrangel_SOURCES
)
if(WIN32)
SET(sdrangel_SOURCES ${sdrangel_SOURCES} sdrbase/resources/sdrangel.rc)
SET(sdrangel_SOURCES ${sdrangel_SOURCES} sdrgui/resources/sdrangel.rc)
endif(WIN32)
add_executable(sdrangel
@ -263,7 +280,7 @@ if(WIN32)
set_target_properties(sdrangel PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")
endif(WIN32)
qt5_use_modules(sdrangel Widgets Multimedia)
target_link_libraries(sdrangel Qt5::Widgets Qt5::Multimedia)
##############################################################################
# main server application
@ -287,7 +304,31 @@ target_link_libraries(sdrangelsrv
${QT_LIBRARIES}
)
qt5_use_modules(sdrangelsrv Multimedia)
target_link_libraries(sdrangelsrv Qt5::Multimedia)
##############################################################################
# main benchmark application
set(sdrangelbench_SOURCES
appbench/main.cpp
)
add_executable(sdrangelbench
${sdrangelbench_SOURCES}
)
target_include_directories(sdrangelbench
PUBLIC ${CMAKE_SOURCE_DIR}/sdrbench
)
target_link_libraries(sdrangelbench
sdrbench
logging
${QT_LIBRARIES}
)
target_compile_features(sdrangelbench PRIVATE cxx_generalized_initializers) # cmake >= 3.1.0
target_link_libraries(sdrangelbench Qt5::Multimedia)
##############################################################################
@ -321,6 +362,7 @@ endif(LIBUSB_FOUND AND UNIX)
#install targets
install(TARGETS sdrangel DESTINATION bin)
install(TARGETS sdrangelsrv DESTINATION bin)
install(TARGETS sdrangelbench DESTINATION bin)
#install(TARGETS sdrbase DESTINATION lib)
#install files and directories

169
Readme.md
View File

@ -1,10 +1,16 @@
![SDR Angel banner](doc/img/sdrangel_banner.png)
**SDRangel** is an Open Source Qt5 / OpenGL 3.0+ (Linux) SDR and signal analyzer frontend to various hardware.
**SDRangel** is an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
**Check the discussion group** [here](https://groups.io/g/sdrangel)
**⚠ Warning**: Windows distribution is provided as a by product of the Qt toolchain. The platform of choice to run SDRangel is definitely Linux. You are encouraged to use the group to seek help from other Windows users but the author cannot give help or any support for problems related to running the software on Windows. Issues specific to Windows problems opened on Github will be closed systematically. Windows distribution may be discontinued in the future.
⚠ SDRangel is intended for the power user. We expect you to already have some experience with SDR applications and digital signal processing in general. SDRangel might be a bit overwhelming for you however you are encouraged to use the discussion group above to look for help. You can also find more information in the [Wiki](https://github.com/f4exb/sdrangel/wiki).
<h1>Hardware requirements</h1>
SDRangel is a near real time application that is demanding on CPU power and clock speeds for low latency. Recent (2015 or later) Core i7 class CPU is recommended preferably with 4 HT CPU cores (8 logical CPUs or more) with nominal clock over 2 GHz and at least 8 GB RAM. Modern Intel processors will include a GPU suitable for proper OpenGL support. On the other hand SDRangel is not as demanding as recent computer games for graphics and CPU integrated graphics are perfectly fine. USB-3 ports are also preferable for high speed, low latency USB communication. It may run on beefy SBCs and was tested successfully on a Udoo Ultra.
The server variant does not need a graphical display and therefore OpenGL support. It can run on smaller devices check the Wiki for hardware requirements and a list of successful cases.
<h1>Source code</h1>
@ -12,7 +18,7 @@
- master: the production branch
- dev: the development branch
- legacy: the modified code from the parent application [hexameron rtl-sdrangelove](https://github.com/hexameron/rtl-sdrangelove) before a major redeisign of the code was carried out and sync was lost.
- legacy: the modified code from the parent application [hexameron rtl-sdrangelove](https://github.com/hexameron/rtl-sdrangelove) before a major redesign of the code was carried out and sync was lost.
<h2>Untested plugins</h2>
@ -21,31 +27,37 @@ These plugins come from the parent code base and have been maintained so that th
channelrx:
- demodlora
- tcpsrc (although it has evolved please use the udpsrc plugin instead)
<h2>Deprecated plugins</h2>
These plugins are still present at least in the code but have been superceded:
- chanalyzer: the Channel Analyzer channel plugin is superceded by the "new generation" Channel Analyzer NG (chanalyzerng)
<h1>Specific features</h1>
<h2>Multiple device support</h2>
From version 2 SDRangel can integrate more than one hardware device running concurrently.
Since version 2 SDRangel can integrate more than one hardware device running concurrently.
<h2>Transmission support</h2>
From version 3 transmission or signal generation is supported for BladeRF, HackRF (since version 3.1), LimeSDR (since version 3.4) and PlutoSDR (since version 3.7.8) using a sample sink plugin. These plugins are:
Since version 3 transmission or signal generation is supported for BladeRF, HackRF (since version 3.1), LimeSDR (since version 3.4) and PlutoSDR (since version 3.7.8) using a sample sink plugin. These plugins are:
- [BladeRF output plugin](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesink/bladerfoutput) limited support in Windows
- [BladeRF1 output plugin](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesink/bladerf1output)
- [BladeRF2 output plugin](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesink/bladerf2output)
- [HackRF output plugin](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesink/hackrfoutput)
- [LimeSDR output plugin](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesink/limesdroutput)
- [PlutoSDR output plugin](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesink/plutosdroutput)
- [File output or file sink plugin](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesink/filesink)
- [Remote device via Network with SDRdaemon](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesink/sdrdaemonsink) Linux only
<h2>REST API</h2>
Since version 4 a REST API is available to interact with the SDRangel application. More details are provided in the server instance documentation in the `sdrsrv` folder.
<h2>Server instance</h2>
Since version 4 the `sdrangelsrv` binary launches a server mode SDRangel instance that runs wihout the GUI. More information is provided in the Readme file of the `sdrsrv` folder.
<h2>Detached RF head server (SDRdaemon)</h2>
Since version 4.1 the previously separated project SDRdaemon has been modified and included in SDRangel. The `sdrangelsrv` headless variant can be used for this purpose using the Daemon source or sink channels.
<h1>Notes on pulseaudio setup</h1>
The audio devices with Qt are supported through pulseaudio and unless you are using a single sound chip (or card) with a single output port or you are an expert with pulseaudio config files you may get into trouble when trying to route the audio to a different output port. These notes are a follow-up of issue #31 with my own experiments with HDMI audio output on the Udoo x86 board. So using this example of HDMI output you can do the following:
@ -58,7 +70,7 @@ The audio devices with Qt are supported through pulseaudio and unless you are us
- Select HDMI from the profiles list in the 'Configuration' tab
- Then in the 'Output devices' tab the HDMI / display port is selected as it is normally the only one. Just double check this
- In SDRangel's Preferences/Audio menu make sure something like `alsa_output.pci-0000_00_1b.0.hdmi-stereo` is selected. The default might also work after the pulseaudio configuration you just made.
In case you cannot see anything related to HDMI or your desired audio device in pavucontrol just restart pulseaudio with `pulseaudio -k` (`-k` kills the previous instance before restarting) and do the above steps again.
<h1>Supported hardware</h1>
@ -87,14 +99,30 @@ It is recommended to add `-DRX_SAMPLE_24BIT=ON` on the cmake command line to act
&#9758; From version 3.12.0 the Linux binaries are built with the 24 bit Rx option.
<h2>BladeRF</h2>
<h2>BladeRF classic (v.1)</h2>
[BladeRF](https://www.nuand.com/) is supported through the libbladerf library that should be installed in your system for proper build of the software and operation support. Add `libbladerf-dev` to the list of dependencies to install.
[BladeRF1](https://www.nuand.com/bladerf-1) is supported through the libbladeRF library that should be installed in your system for proper build of the software and operation support. Add `libbladerf-dev` to the list of dependencies to install. Note that libbladeRF v2 is used since version 4.2.0 (git tag 2018.08).
If you use your own location for libbladeRF install directory you need to specify library and include locations. Example with `/opt/install/libbladerf` with the following defines on `cmake` command line:
If you compile and use your own location for libbladeRF install directory you need to specify library and include locations. Example with `/opt/install/libbladerf` with the following defines on `cmake` command line:
`-DLIBBLADERF_LIBRARIES=/opt/install/libbladeRF/lib/libbladeRF.so -DLIBBLADERF_INCLUDE_DIR=/opt/install/libbladeRF/include`
&#9758; Please note that if you use your own library the FPGA image `hostedx40.rbf` or `hostedx115.rbf` shoud be placed in e.g. `/opt/install/libbladeRF/share/Nuand/bladeRF` unless you have flashed the FPGA image inside the BladeRF.
The plugins used to support BladeRF classic are specific to this version of the BladeRF:
- [BladeRF1 input](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesource/bladerf1input)
- [BladeRF1 output](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesink/bladerf1output)
<h2>BladeRF micro (v.2)</h2>
From version 4.2.0.
[BladeRF 2 micro](https://www.nuand.com/bladerf-2-0-micro/) is also supported using libbladeRF library that should be installed and configured in the same way as for BladeRF1.
The plugins used to support BladeRF 2 micro are specific to this version of the BladeRF:
- [BladeRF2 input](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesource/bladerf2input)
- [BladeRF2 output](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesink/bladerf2output)
<h2>FunCube Dongle</h2>
Linux only.
@ -119,11 +147,9 @@ HackRF is better used with a sampling rate of 4.8 MS/s and above. The 2.4 and 3.
[LimeSDR](https://myriadrf.org/projects/limesdr/) and its smaller clone LimeSDR Mini are supported using LimeSuite library (see next).
<p><b>&#9888; The plugins should work normally when running as single instances. Support of many Rx and/or Tx instances running concurrently is considered experimental. At least you should always have one of the streams running.</b></p>
<p>&#9888; Version 18.10.0 of LimeSuite is used in the builds and corresponding gateware loaded in the LimeSDR should be is used. If you compile from source version 18.10.0 of LimeSuite must be used.</p>
<p>&#9888; It seems LimeSDR mini has trouble working with host sample rates lower than 2.5 MS/s particularly in Tx mode.</p>
You will need a minimal installation of LimeSuite. Presently commit 04b57e0 or later should be used with its corresponding firmware (v4) and gateware (v2.12) installed in the LimeSDR device:
<p>&#9888; LimeSDR-Mini seems to have problems with Zadig driver therefore it is supported in Linux only.</p>
- `sudo apt-get install libsqlite3-dev`
- `git clone https://github.com/myriadrf/LimeSuite.git`
@ -154,7 +180,7 @@ If you use your own location for libperseus-sdr install directory you need to sp
[PlutoSDR](https://wiki.analog.com/university/tools/pluto) is supported with the libiio interface. This library should be installed in your system for proper build of the software and operation support. Add `libiio-dev` to the list of dependencies to install. Be aware that version 0.10 is needed and is not available yet in all distributions. You may have to compile it from source instead.
If you use your own location for libiio install directory you need to specify library and include locations. Example with `/opt/install/libiio` with the following defines on `cmake` command line: `-DLIBIIO_INCLUDE_DIR=/opt/install/libiio/include -DLIBIIO_LIBRARY=/opt/install/libiio/lib/libiio.so`. In openSuse the lib directory path would be: `-DLIBIIO_LIBRARY=/opt/install/libiio/lib64/libiio.so`.
If you use your own location for libiio install directory you need to specify library and include locations. Example with `/opt/install/libiio` with the following defines on `cmake` command line: `-DLIBIIO_INCLUDE_DIR=/opt/install/libiio/include -DLIBIIO_LIBRARY=/opt/install/libiio/lib/libiio.so`. In openSUSE the lib directory path would be: `-DLIBIIO_LIBRARY=/opt/install/libiio/lib64/libiio.so`.
<h2>RTL-SDR</h2>
@ -184,9 +210,9 @@ These plugins do not use any hardware device connected to your system.
The [File source plugin](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesource/filesource) allows the playback of a recorded IQ file. Such a file is obtained using the recording feature. Click on the record button on the left of the main frequency dial to toggle recording. The file has a fixed name `test_<n>.sdriq` created in the current directory where `<n>` is the device tab index.
Note that this plugin does not require any of the hardware support libraries nor the libusb library. It is alwasys available in the list of devices as `FileSource[0]` even if no physical device is connected.
Note that this plugin does not require any of the hardware support libraries nor the libusb library. It is always available in the list of devices as `FileSource[0]` even if no physical device is connected.
The `.sdriq` format produced are the 2x2 bytes I/Q samples with a header containing the center frequency of the baseband, the sample rate and the timestamp of the recording start. Note that this header length is a multiple of the sample size so the file can be read with a simple 2x2 bytes I/Q reader such as a GNU Radio file source block. It will just produce a short glitch at the beginning corresponding to the header data.
The `.sdriq` format produced are the 2x2 bytes I/Q samples with a header containing the center frequency of the baseband, the sample rate and the timestamp of the recording start. Note that this header length is a multiple of the sample size so the file can be read with a simple 2x2 bytes I/Q reader such as a GNU Radio file source block. It will just produce a short glitch at the beginning corresponding to the header data.
<h2>File output</h2>
@ -196,19 +222,19 @@ Note that this plugin does not require any of the hardware support libraries nor
<h2>Test source</h2>
The [Test source plugin](https://github.com/f4exb/sdrangel/tree/master/plugins/samplesource/testsource) is an internal continuous wave generator that can be used to carry out test of software internals.
The [Test source plugin](https://github.com/f4exb/sdrangel/tree/master/plugins/samplesource/testsource) is an internal continuous wave generator that can be used to carry out test of software internals.
<h2>SDRdaemon receiver input</h2>
Linux only.
The [SDRdaemon source input plugin](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesource/sdrdaemonsource) is the client side of the SDRdaemon receiver server `sdrdaemonrx`. See the [SDRdaemon](https://github.com/f4exb/sdrdaemon) project in this Github repository. You must specify the local address and UDP port to which the remote server connects and samples will flow into the SDRangel application (default is `127.0.0.1`port `9090`). It uses the meta data to retrieve the sample flow characteristics such as sample rate and receiveng center frequency. It also opens a TCP link to another port to send service messages such as setting parameters specific to the hadrware device connected to the server (default port is `9091`). The `libnanomsg` library is used to support this messaging.
The [SDRdaemon source input plugin](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesource/sdrdaemonsource) is the client side of an instance of SDRangel running the Daemon Sink channel plugin. On the "Data" line you must specify the local address and UDP port to which the remote server connects and samples will flow into the SDRangel application (default is `127.0.0.1`port `9090`). It uses the meta data to retrieve the sample flow characteristics such as sample rate and receiving center frequency. The remote is entirely controlled by the REST API. On the "API" line you can specify the address and port at which the remote REST API listens. However it is used just to display basic information about the remote.
The data blocks transmitted via UDP are protected against loss with a Cauchy MDS block erasure codec. This makes the transmission more robust in particular with WiFi links.
There is an automated skew rate compensation in place. During rate readjustemnt streaming can be suspended or signal glitches can occur for about one second.
There is an automated skew rate compensation in place. During rate readjustment streaming can be suspended or signal glitches can occur for about one second.
This plugin will be built only if the libnanomsg and the [CM256cc library](https://github.com/f4exb/cm256cc) are installed in your system. libnanomsg is available as a dev package in most distributions For CM256cc if you install it in a non standard directory you will then have to specify the include and library paths on the cmake command line. Say if you install cm256cc in `/opt/install/cm256cc` you will have to add `-DCM256CC_INCLUDE_DIR=/opt/install/cm256cc/include/cm256cc -DCM256CC_LIBRARIES=/opt/install/cm256cc/lib/libcm256cc.so` to the cmake commands.
This plugin will be built only if the [CM256cc library](https://github.com/f4exb/cm256cc) is installed in your system. For CM256cc if you install it in a non standard directory you will then have to specify the include and library paths on the cmake command line. Say if you install cm256cc in `/opt/install/cm256cc` you will have to add `-DCM256CC_INCLUDE_DIR=/opt/install/cm256cc/include/cm256cc -DCM256CC_LIBRARIES=/opt/install/cm256cc/lib/libcm256cc.so` to the cmake commands.
Note that this plugin does not require any of the hardware support libraries nor the libusb library. It is always available in the list of devices as `SDRdaemonSource[0]` even if no physical device is connected.
@ -216,13 +242,11 @@ Note that this plugin does not require any of the hardware support libraries nor
Linux only.
The [SDRdaemon sink output plugin](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesink/sdrdaemonsink) is the client side of the SDRdaemon transmitter server `sdrdaemontx`. See the [SDRdaemon](https://github.com/f4exb/sdrdaemon) project in this Github repository. You must specify the distant address and UDP port to which the plugin connects and samples from the SDRangel application will flow into the transmitter server (default is `127.0.0.1`port `9092`). It also opens a TCP link to another port to exchange service messages such as setting the center frequency or getting status information from the server (default port is `9093`). The `libnanomsg` library is used to support this messaging.
The [SDRdaemon sink output plugin](https://github.com/f4exb/sdrangel/tree/dev/plugins/samplesink/sdrdaemonsink) is the client side of and instance of SDRangel running the Daemon Source channel plugin. On the "Data" line you must specify the distant address and UDP port to which the plugin connects and samples from the SDRangel application will flow into the transmitter server (default is `127.0.0.1`port `9090`). The remote is entirely controlled by the REST API. On the "API" line you can specify the address and port at which the remote REST API listens. The API is pinged regularly to retrieve the status of the data blocks queue and allow rate control to stabilize the queue length. Therefore it is important to connect to the API properly (The status line must return "API OK" and the API label should be lit in green).
The data blocks sent via UDP are protected against loss with a Cauchy MDS block erasure codec. This makes the transmission more robust in particular with WiFi links.
There is an automated skew rate compensation in place so that the generator throttling is adjusted to match the actual sample rate of the distant device. This is based on the number of buffer blocks sent back from the distant server using the TCP link.
This plugin will be built only if the libnanomsg and the [CM256cc library](https://github.com/f4exb/cm256cc) are installed in your system. libnanomsg is available as a dev package in most distributions For CM256cc if you install it in a non standard directory you will then have to specify the include and library paths on the cmake command line. Say if you install cm256cc in `/opt/install/cm256cc` you will have to add `-DCM256CC_INCLUDE_DIR=/opt/install/cm256cc/include/cm256cc -DCM256CC_LIBRARIES=/opt/install/cm256cc/lib/libcm256cc.so` to the cmake commands.
This plugin will be built only if the [CM256cc library](https://github.com/f4exb/cm256cc) IS installed in your system. For CM256cc if you install it in a non standard directory you will then have to specify the include and library paths on the cmake command line. Say if you install cm256cc in `/opt/install/cm256cc` you will have to add `-DCM256CC_INCLUDE_DIR=/opt/install/cm256cc/include/cm256cc -DCM256CC_LIBRARIES=/opt/install/cm256cc/lib/libcm256cc.so` to the cmake commands.
Note that this plugin does not require any of the hardware support libraries nor the libusb library. It is always available in the list of devices as `SDRdaemonSink[0]` even if no physical device is connected.
@ -236,21 +260,13 @@ This is the `demoddsd` plugin. At present it can be used to decode the following
- dPMR
- D-Star
- Yaesu System Fusion (YSF)
- NXDN
It is based on the [DSDcc](https://github.com/f4exb/dsdcc) C++ library which is a rewrite of the original [DSD](https://github.com/szechyjs/dsd) program. So you will need to have DSDcc installed in your system. Please follow instructions in [DSDcc readme](https://github.com/f4exb/dsdcc/blob/master/Readme.md) to build and install DSDcc. If you install it in a custom location say `/opt/install/dsdcc` you will need to add these defines to the cmake command: `-DLIBDSDCC_INCLUDE_DIR=/opt/install/dsdcc/include/dsdcc -DLIBDSDCC_LIBRARIES=/opt/install/dsdcc/lib/libdsdcc.so`
If you have one or more serial devices interfacing the AMBE3000 chip in packet mode you can use them to decode AMBE voice frames. For that purpose you will need to compile with [SerialDV](https://github.com/f4exb/serialDV) support. Please refer to this project Readme.md to compile and install SerialDV. If you install it in a custom location say `/opt/install/serialdv` you will need to add these defines to the cmake command: `-DLIBSERIALDV_INCLUDE_DIR=/opt/install/serialdv/include/serialdv -DLIBSERIALDV_LIBRARY=/opt/install/serialdv/lib/libserialdv.so` Also your user must be a member of group `dialout` to be able to use the dongle.
If you have one or more serial devices interfacing the AMBE3000 chip in packet mode you can use them to decode AMBE voice frames. For that purpose you will need to compile with [SerialDV](https://github.com/f4exb/serialDV) support. Please refer to this project Readme.md to compile and install SerialDV. If you install it in a custom location say `/opt/install/serialdv` you will need to add these defines to the cmake command: `-DLIBSERIALDV_INCLUDE_DIR=/opt/install/serialdv/include/serialdv -DLIBSERIALDV_LIBRARY=/opt/install/serialdv/lib/libserialdv.so` Also your user must be a member of group `dialout` (Ubuntu/Debian) or `uucp` (Arch) to be able to use the dongle.
Although such serial devices work with a serial interface at 400 kb in practice maybe for other reasons they are capable of handling only one conversation at a time. The software will allocate the device dynamically to a conversation with an inactivity timeout of 1 second so that conversations do not get interrupted constantly making the audio output too choppy. In practice you will have to have as many devices connected to your system as the number of conversations you would like to be handled in parallel.
Note that this is not supported in Windows because of trouble with COM port support (contributors welcome!).
---
&#9888; Since kernel 4.4.52 the default for FTDI devices (that is in the ftdi_sio kernel module) is not to set it as low latency. This results in the ThumbDV dongle not working anymore because its response is too slow to sustain the normal AMBE packets flow. The solution is to force low latency by changing the variable for your device (ex: /dev/ttyUSB0) as follows:
`echo 1 | sudo tee /sys/bus/usb-serial/devices/ttyUSB0/latency_timer` or `sudo setserial /dev/ttyUSB0 low_latency`
---
Although such serial devices work with a serial interface at 400 kb in practice maybe for other reasons they are capable of handling only one conversation at a time. The software will allocate the device dynamically to a conversation with an inactivity timeout of 1 second so that conversations do not get interrupted constantly making the audio output too choppy. In practice you will have to have as many devices connected to your system as the number of conversations you would like to be handled in parallel.
Alternatively you can use [mbelib](https://github.com/szechyjs/mbelib) but mbelib comes with some copyright issues (see next). If you have mbelib installed in a custom location, say `/opt/install/mbelib` you will need to add these defines to the cmake command: `-DLIBMBE_INCLUDE_DIR=/opt/install/mbelib/include -DLIBMBE_LIBRARY=/opt/install/mbelib/lib/libmbe.so`
@ -267,14 +283,15 @@ If you are not comfortable with this just do not install DSDcc and/or mbelib and
<h1>Software distributions</h1>
In the [releases](https://github.com/f4exb/sdrangel/releases) section one can find binary distributions for some common systems:
In the [releases](https://github.com/f4exb/sdrangel/releases) section one can find binary distributions for some Debian based distributions:
- Debian x86_64 (Ubuntu 16.04, Ubuntu 17.10, Debian Stretch)
- Windows 32 bit (runs also in 64 bit Windows)
- Ubuntu 18.04 (Bionic)
- Ubuntu 16.04 (Xenial)
- Debian Stretch
<h2>Debian distributions</h2>
It is provided in the form of .deb packages for x86_64 architectures with SSE 4.1 support.
It is provided in the form of .deb packages for x86_64 architectures with SSE 4.1 support.
Install it as usual for .deb packages:
@ -286,20 +303,27 @@ Prior to apt-get v 1.1 (before Ubuntu 16.04) in a terminal do:
- `sudo apt-get upgrade`
- `sudo dpkg -i sdrangel_vx.y.z-1_amd64.deb` where x.y.z is the version number
- `sudo apt-get -f install` this will install missing dependencies
Since apt-get v 1.1 installation is possible from a local file:
- cd to where the archive has been downloaded
- `sudo apt-get install ./sdrangel_vx.y.z-1_amd64.deb` where x.y.z is the version number
- `sudo apt-get install ./sdrangel_vx.y.z-1_amd64.deb` where x.y.z is the version number
- `sudo apt-get -f install` this will install missing dependencies
The software is installed in `/opt/sdrangel` you can start it from the command line with:
- `/opt/sdrangel/bin/sdrangel`
**&#9888;** The udev rules are not set by the package installation so you will have to set it manually in order to be able to access the various SDR hardware. The `udev-rules` folder contains the rules file and the `install.sh` script that you can run as sudo to install all rules files. You may also adapt the script to copy only the required files.
<h3>Ubuntu 18.04</h2>
The default CPU governor is now `powersave` which exhibits excessive CPU usage when running SDRangel. In the case of benchmarking and maybe high throughput usage it is recommended to switch to `performance` before running SDRangel by running the command: `sudo cpupower frequency-set --governor performance`. You can turn it back to `powersave` any time by running: `sudo cpupower frequency-set --governor powersave`. It is normal that with a lower CPU frequency the relative CPU usage rises for the same actual load. If not impairing operation this is normal and overall beneficial for heat and power consumption.
<h2>Windows distribution</h2>
This is the archive of the complete binary distribution that expands to the `sdrangel` directory. You can install it anywhere you like and click on `sdrangel.exe` to start.
<b>&#9888; Windows distribution is provided as a by product thanks to the Qt toolchain. The platform of choice to run SDRangel is definitely Linux and very little support can be given for the Windows distribution.</b>
<b>&#9888; Windows distribution is provided as a by product thanks to the Qt toolchain. The platform of choice to run SDRangel is definitely Linux and very little support can be given for this Windows distribution.</b>
<h1>Software build</h1>
@ -307,7 +331,7 @@ This is the archive of the complete binary distribution that expands to the `sdr
To be sure you will need at least Qt version 5.5. It definitely does not work with versions earlier than 5.3 but neither 5.3 nor 5.4 were tested.
- Linux builds are made with 5.5.1 (Xenial) and 5.9 (Artful, Stretch)
- Linux builds are made with 5.5.1 (Xenial), 5.9 (Artful, Stretch, Bionic) and 5.11 (Cosmic)
- Windows build is made with 5.10.1 in 32 bit mode and has Qt ANGLE support (OpenGL emulation with DirectX)
<h2>24 bit DSP</h2>
@ -336,16 +360,23 @@ Install cmake version 3:
- `sudo apt-get remove cmake` (if already installed)
- `sudo apt-get install cmake`
<h3>Prerequisites for 16.04 LTS</h3>
For DATV demodulator support you need to install the ffmpeg v.3 suite. Therefore you will need to add this PPA to the sources list using this command:
`sudo add-apt-repository ppa:jonathonf/ffmpeg-3`
Then do `sudo apt-get update` and go to the next step. Alternatively if you have an older version of ffmpeg suite already installed just do `sudo apt-get dist-upgrde`.
<h3>With newer versions just do:</h3>
- `sudo apt-get install cmake g++ pkg-config libfftw3-dev libqt5multimedia5-plugins qtmultimedia5-dev qttools5-dev qttools5-dev-tools libqt5opengl5-dev qtbase5-dev libusb-1.0 librtlsdr-dev libboost-all-dev libasound2-dev pulseaudio libnanomsg-dev libopencv-dev libsqlite3-dev libxml2-dev bison flex`
- `sudo apt-get install cmake g++ pkg-config libfftw3-dev libqt5multimedia5-plugins qtmultimedia5-dev qttools5-dev qttools5-dev-tools libqt5opengl5-dev qtbase5-dev libusb-1.0 librtlsdr-dev libboost-all-dev libasound2-dev pulseaudio libopencv-dev libsqlite3-dev libxml2-dev bison flex ffmpeg libavcodec-dev libavformat-dev`
- `mkdir build && cd build && cmake ../ && make`
`librtlsdr-dev` is in the `universe` repo. (utopic 14.10 amd64.)
<h2>Mint</h2>
Tested with Cinnamon 17.2. Since it is based on Ubuntu 14.04 LTS pleae follow instructions for this distribution (paragraph just above).
Tested with Cinnamon 17.2. Since it is based on Ubuntu 14.04 LTS please follow instructions for this distribution (paragraph just above).
<h2>Debian</h2>
@ -355,24 +386,25 @@ Debian 7 "wheezy" uses Qt4. Qt5 is available from the "wheezy-backports" repo, b
For Debian Jessie or Stretch:
`sudo apt-get install cmake g++ pkg-config libfftw3-dev libusb-1.0-0-dev libusb-dev qt5-default qtbase5-dev qtchooser libqt5multimedia5-plugins qtmultimedia5-dev qttools5-dev qttools5-dev-tools libqt5opengl5-dev qtbase5-dev librtlsdr-dev libboost-all-dev libasound2-dev pulseaudio libopencv-dev libsqlite3-dev libxml2-dev bison flex`
`sudo apt-get install cmake g++ pkg-config libfftw3-dev libusb-1.0-0-dev libusb-dev qt5-default qtbase5-dev qtchooser libqt5multimedia5-plugins qtmultimedia5-dev qttools5-dev qttools5-dev-tools libqt5opengl5-dev qtbase5-dev librtlsdr-dev libboost-all-dev libasound2-dev pulseaudio libopencv-dev libsqlite3-dev libxml2-dev bison flex ffmpeg libavcodec-dev libavformat-dev`
`mkdir build && cd build && cmake ../ && make`
<h2>openSUSE</h2>
This has been tested with the bleeding edge "Thumbleweed" distribution:
This has been tested with the Leap 42.3 distribution:
`sudo zypper install Mesa-libGL1 Mesa-libEGL-devel Mesa-libGL-devel Mesa-libGLESv1_CM-devel Mesa-libGLESv2-devel Mesa-libGLESv3-devel Mesa-libglapi-devel libOSMesa-devel`
`sudo zypper install Mesa-libGL1 Mesa-libEGL-devel Mesa-libGL-devel Mesa-libGLESv1_CM-devel Mesa-libGLESv2-devel Mesa-libGLESv3-devel Mesa-libglapi-devel libOSMesa-devel`
`sudo zypper install cmake fftw3-devel gcc-c++ libusb-1_0-devel libqt5-qtbase-devel libQt5OpenGL-devel libqt5-qtmultimedia-devel libqt5-qttools-devel libQt5Network-devel libQt5Widgets-devel boost-devel alsa-devel pulseaudio opencv-devel`
Then you should be all set to build the software with `cmake` and `make` as discussed earlier.
- Note1: if you are on Leap you will need a more recent g++ compiler so in place of `gcc-c++` use `gcc5-c++` or `gcc6-c++` then add the following in the cmake command: `-DCMAKE_C_COMPILER=/usr/bin/gcc-6 -DCMAKE_CXX_COMPILER=/usr/bin/g++-6` (for gcc 6) and then `-DCMAKE_INSTALL_PREFIX:PATH=...` for the custom install path (not `-DCMAKE_INSTALL_PREFIX=...`)
- Note2: On Leap and aarch64 architectures you will need to build and install `libnanomsg` from [source](https://github.com/nanomsg/nanomsg)
- Note3 for udev rules: installed udev rules for BladeRF and HackRF are targetted at Debian or Ubuntu systems that have a plugdev group for USB hotplug devices. This is not the case in openSUSE. To make the udev rules file compatible just remove the `GROUP` parameter on all lines and change `MODE` parameter to `666`.
- Note4: A package has been created in OpenSUSE thanks to Martin, see: [sdrangel](https://build.opensuse.org/package/show/hardware:sdr/sdrangel). It is based on the latest release on master branch.
- Note1: if you are on Leap you will need a more recent g++ compiler so in place of `gcc-c++` use `gcc6-c++` or `gcc7-c++` then add the following in the cmake command: `-DCMAKE_C_COMPILER=/usr/bin/gcc-7 -DCMAKE_CXX_COMPILER=/usr/bin/g++-7` (for gcc 7) and then `-DCMAKE_INSTALL_PREFIX:PATH=...` for the custom install path (not `-DCMAKE_INSTALL_PREFIX=...`)
- Note2 for udev rules: installed udev rules for BladeRF and HackRF are targeted at Debian or Ubuntu systems that have a plugdev group for USB hotplug devices. This is not the case in openSUSE. To fix it you can either:
- make the udev rules file compatible just remove the `GROUP` parameter on all lines and change `MODE` parameter to `666`.
- create a `plugdev` group and add it tou your user group list: `sudo groupadd plugdev` then `sudo usermod -G plugdev -a <user>`
- Note3: A package has been created in openSUSE thanks to Martin, see: [sdrangel](https://build.opensuse.org/package/show/hardware:sdr/sdrangel). It is based on the latest release on master branch.
<h2>Fedora</h2>
@ -386,16 +418,16 @@ Then you should be all set to build the software with `cmake` and `make` as disc
- Note for udev rules: the same as for openSUSE applies. This is detailed in the previous paragraph for openSUSE.
<h2>Manjaro</h2>
<h2>Arch Linux / Manjaro</h2>
Tested with the 15.09 version with LXDE desktop (community supported). The exact desktop environment should not matter anyway. Since Manjaro is Arch Linux based prerequisites should be similar for Arch and all derivatives.
Tested with the 15.09 version with LXDE desktop (community supported). The exact desktop environment should not matter anyway. Prerequisites should be similar for Arch and all derivatives.
`sudo pacman -S cmake pkg-config fftw qt5-multimedia qt5-tools qt5-base libusb boost boost-libs pulseaudio`
Then you should be all set to build the software with `cmake` and `make` as discussed earlier.
- Note1 for udev rules: the same as for openSUSE and Fedora applies.
- Note2: A package has been created in the AUR (thanks Mikos!), see: [sdrangel-git](https://aur.archlinux.org/packages/sdrangel-git). It is based on the `205fee6` commit of 8th December 2015.
- Note2: Two package are avaliable in the AUR (thanks Mikos!), [sdrangel](https://aur.archlinux.org/packages/sdrangel), which provides the lastest tagged release (stable), and [sdrangel-git](https://aur.archlinux.org/packages/sdrangel-git), which builds the latest commit from this repository (unstable).
<h2>Windows</h2>
@ -428,14 +460,13 @@ You can uninstall the software with `make uninstall` or `sudo make uninstall` fr
<h1>Limitations</h1>
- Your hardware. Still SDRangel is relatively conservative on computer resources.
- OpenGL 3+ (Linux)
- OpenGL 4.3+ (Windows) for OpenGL native support however the Qt Angle framework may be able to make it work on systems supporting Direct-X only.
- OpenGL 3+
<h1>Features</h1>
<h2>Changes from SDRangelove</h2>
See the v1.0.1 first official relase [release notes](https://github.com/f4exb/sdrangel/releases/tag/v1.0.1)
See the v1.0.1 first official release [release notes](https://github.com/f4exb/sdrangel/releases/tag/v1.0.1)
<h2>To Do</h2>
@ -451,4 +482,4 @@ Other ideas:
<h1>Developer's notes</h1>
Please check the developper's specific [readme](./ReadmeDeveloper.md)
Please check the developer's specific [readme](./ReadmeDeveloper.md)

View File

@ -19,7 +19,7 @@ You can add `-Wno-dev` on the `cmake` command line to avoid warnings.
![SDRangel code map](./doc/img/SDRangelFlow.png)
The existing receiving flow is represented with green boxes. The futrue Tx flow with red boxes. Some classes and file paths in the Rx part were renamed to avoid collision with future Tx names in this case the old name appears below the present name in italics.
The existing receiving flow is represented with green boxes. The future Tx flow with red boxes. Some classes and file paths in the Rx part were renamed to avoid collision with future Tx names in this case the old name appears below the present name in italics.
<h3>Rx path</h3>
@ -33,22 +33,22 @@ The existing receiving flow is represented with green boxes. The futrue Tx flow
At present the following plugins are available:
- `AirspyXxx` classes in `plugins/samplesource/airspy`: Inteface with Airspy devices
- `BladeRFXxx` classes in `plugins/samplesource/bladerf`: Inteface with BladeRF devices
- `BladeRFXxx` classes in `plugins/samplesource/bladerf`: Inteface with BladeRF devices
- `FCDProXxx` classes in `plugins/samplesource/fcdpro`: Inteface with Funcube Pro devices
- `FCDProPlusXxx` classes in `plugins/samplesource/fcdproplus`: Inteface with Funcube Pro+ devices
- `HackRFXxx` classes in `plugins/samplesource/hackrf`: Inteface with HackRF devices
- `RTLSDRXxx` classes in `plugins/samplesource/rtlsdr`: Inteface with RTL-SDR devices
- `SDRDaemonXxx` classes in `plugins/samplesource/sdrdaemon`: Special inteface collecting I/Q samples from an UDP flow sent by a remote device using [SDRdaemon](https://github.com/f4exb/sdrdaemon).
- `SDRDaemonFECXxx` classes in `plugins/samplesource/sdrdaemonfec`: Special inteface collecting I/Q samples from an UDP flow sent by a remote device using [SDRdaemon](https://github.com/f4exb/sdrdaemon) with FEC protection of blocks.
- `FileSource` classes in `plugins/samplesource/filesource`: Special inteface reading I/Q samples from a file directly into the baseband skipping the downsampling block
- `AirspyXxx` classes in `plugins/samplesource/airspy`: Interface with Airspy devices
- `BladeRFXxx` classes in `plugins/samplesource/bladerf`: Interface with BladeRF devices
- `BladeRFXxx` classes in `plugins/samplesource/bladerf`: Interface with BladeRF devices
- `FCDProXxx` classes in `plugins/samplesource/fcdpro`: Interface with Funcube Pro devices
- `FCDProPlusXxx` classes in `plugins/samplesource/fcdproplus`: Interface with Funcube Pro+ devices
- `HackRFXxx` classes in `plugins/samplesource/hackrf`: Interface with HackRF devices
- `RTLSDRXxx` classes in `plugins/samplesource/rtlsdr`: Interface with RTL-SDR devices
- `SDRDaemonXxx` classes in `plugins/samplesource/sdrdaemon`: Special interface collecting I/Q samples from an UDP flow sent by a remote device using [SDRdaemon](https://github.com/f4exb/sdrdaemon).
- `SDRDaemonFECXxx` classes in `plugins/samplesource/sdrdaemonfec`: Special interface collecting I/Q samples from an UDP flow sent by a remote device using [SDRdaemon](https://github.com/f4exb/sdrdaemon) with FEC protection of blocks.
- `FileSource` classes in `plugins/samplesource/filesource`: Special interface reading I/Q samples from a file directly into the baseband skipping the downsampling block
<h3>Device sample sink plugins</h3>
At present the following plugins are available:
- `FileSink` classes in `plugins/samplesink/filesink`: Special inteface writing baseband I/Q samples to a file skipping the final upsampling block
- `FileSink` classes in `plugins/samplesink/filesink`: Special interface writing baseband I/Q samples to a file skipping the final upsampling block
<h3>Channel receiver (Rx) plugins</h3>
@ -62,8 +62,7 @@ At present the following plugins are available:
- `NFMDemodXxx` classes in `plugins/channelrx/demodnfm`: Narrowband FM demodulator with audio output.
- `SSBDemodXxx` classes in `plugins/channelrx/demodssb`: SSB/DSB/CW demodulator with audio output.
- `WFMDemodXxx` classes in `plugins/channelrx/demodwfm`: Wideband FM demodulator with audio output. This is a basic demodulator.
- `TCPSrcXxx` classes in `plugins/channelrx/tcpsrc`: Sends channel I/Q samples via TCP
- `UDPSrcXxx` classes in `plugins/channelrx/udpsrc`: Sends channel I/Q or FM demodulated samples via UDP
- `UDPSinkXxx` classes in `plugins/channelrx/udpsink`: Sends channel I/Q or FM demodulated samples via UDP
<h3>Channel transmitter (Tx) plugins</h3>
@ -104,11 +103,11 @@ The `plugins` subdirectory contains the associated plugins used to manage device
- `xxxanalyzergui.h/cpp` : Analyzer GUI
- `xxxanalyzerplugin.h/cpp` : Analyzer plugin manager
- `xxxanalyzer.pro` : Qt .pro file for Windows/Android build
- `xxxsrc` : Interface to the outside (e.g xxx = udp):
- `xxxsrc.h/cpp` : Inteface core
- `xxxsrcgui.h/cpp` : Interface GUI
- `xxxsrcplugin/h/cpp` : Interface plugin manager
- `xxxsrc.pro` : Qt .pro file for Windows/Android build
- `xxxsink` : Interface to the outside (e.g xxx = udp):
- `xxxsink.h/cpp` : Interface core
- `xxxsinkgui.h/cpp` : Interface GUI
- `xxxsinkplugin/h/cpp` : Interface plugin manager
- `xxxsink.pro` : Qt .pro file for Windows/Android build
- Transmitter functions (Tx):
- `samplesink`: Device managers:
@ -130,11 +129,11 @@ The `plugins` subdirectory contains the associated plugins used to manage device
- `xxxgeneratorgui.h/cpp` : Generator GUI
- `xxxgeneratorplugin.h/cpp` : Generator plugin manager
- `xxxgenerator.pro` : Qt .pro file for Windows/Android build
- `xxxsink` : Interface to the outside (e.g xxx = udp):
- `xxxsink.h/cpp` : Inteface core
- `xxxsinkgui.h/cpp` : Interface GUI
- `xxxsinklugin/h/cpp` : Interface plugin manager
- `xxxsink.pro` : Qt .pro file for Windows/Android build
- `xxxsource` : Interface to the outside (e.g xxx = udp):
- `xxxsource.h/cpp` : Interface core
- `xxxsourcegui.h/cpp` : Interface GUI
- `xxxsourceplugin/h/cpp` : Interface plugin manager
- `xxxsource.pro` : Qt .pro file for Windows/Android build
<h2>Device interface and GUI lifecycle</h2>
@ -153,9 +152,9 @@ The lifecycle of the GUI is controlled from the "Sampling Device Control" device
- Remove the current device API from the relevant buddies lists. Buddies list are effective only for physical devices with SISO or MIMO architecture (more on that later)
- Create the new device API
- Add the new device API to the relevant devices APIs buddies list
- creates tne new GUI and hence new device interface. This will always open the physical device unless the physical device has a SISO or MIMO architecture
- Creates the new GUI and hence new device interface. This will always open the physical device unless the physical device has a SISO or MIMO architecture
Here is the relevant par ot the code (source side) in the `MainWindow::on_sampleSource_confirmClicked` method:
Here is the relevant part of the code (source side) in the `MainWindow::on_sampleSource_confirmClicked` method:
deviceUI->m_deviceSourceAPI->stopAcquisition();
deviceUI->m_deviceSourceAPI->setSampleSourcePluginInstanceUI(0); // deletes old UI and input object
@ -182,11 +181,11 @@ Note that the following would also work for multiple sample channels Rx or Tx on
In SDRangel there is a complete receiver or transmitter per I/Q sample flow. These transmitters and receivers are visually represented by the Rn and Tn tabs in the main window. They are created and disposed in the way explained in the previous paragraph using the source or sink selection confirmation button. In fact it acts as if each receiver or transmitter was controlled independently. In single input or single output (none at the moment) devices this is a true independence but with SISO or MIMO devices this cannot be the case and although each receiver or transmitter looks like it was handled independently there are things in common that have to be taken into account. For example in all cases the device handle should be unique and opening and closing the device has to be done only once per physical device usage cycle.
This is where the "buddies list" come into play. Receivers exhibit a generic interface in the form of the DeviceSourceAPI class and transmitter have the DeviceSinkAPI with the same role. Through these APIs some information and control can flow between receivers and trasmitters. The point is that all receivers and/or transmitters pertaining to the same physical device must "know" each other in order to be able to exchange information or control each other. For this purpose the DeviceSourceAPI or DeviceSinkAPI maintain a list of DeviceSourceAPI siblings and a list of DeviceSinkAPI siblings called "buddies". Thus any multi flow Rx/Tx configuration can be handled.
This is where the "buddies list" come into play. Receivers exhibit a generic interface in the form of the DeviceSourceAPI class and transmitter have the DeviceSinkAPI with the same role. Through these APIs some information and control can flow between receivers and transmitters. The point is that all receivers and/or transmitters pertaining to the same physical device must "know" each other in order to be able to exchange information or control each other. For this purpose the DeviceSourceAPI or DeviceSinkAPI maintain a list of DeviceSourceAPI siblings and a list of DeviceSinkAPI siblings called "buddies". Thus any multi flow Rx/Tx configuration can be handled.
The exact behaviour of these coupled receivers and/or transmitters is dependent on the hardware therefore a generic pointer attached to the API can be used to convey any kind of class or structure taylored for the exact hardware use case. Through this structure the state of the receiver or transmitter can be exposed therefore there is one structure per receiver and transmitter in the device interface. This structure may contain pointers to common areas (dynamically allocated) related to the physical device. One such "area" is the device handle which is present in all cases.
The exact behaviour of these coupled receivers and/or transmitters is dependent on the hardware therefore a generic pointer attached to the API can be used to convey any kind of class or structure tailored for the exact hardware use case. Through this structure the state of the receiver or transmitter can be exposed therefore there is one structure per receiver and transmitter in the device interface. This structure may contain pointers to common areas (dynamically allocated) related to the physical device. One such "area" is the device handle which is present in all cases.
Normally the first buddy would create the common areas (through new) and the last would delete them (through delete) and the indovidual structure (superstructure) would be on the stack of each buddy. Thus by copying this superstructure a buddy would gain access to common areas from another (already present) buddy along with static information from the other buddy (such as which hadrware Rx or Tx channel it uses in a MIMO architecture). Exchange of dynamic information between buddies is done using message passing.
Normally the first buddy would create the common areas (through new) and the last would delete them (through delete) and the individual structure (superstructure) would be on the stack of each buddy. Thus by copying this superstructure a buddy would gain access to common areas from another (already present) buddy along with static information from the other buddy (such as which hardware Rx or Tx channel it uses in a MIMO architecture). Exchange of dynamic information between buddies is done using message passing.
The degree of entanglement between the different coupled flows in a single hardware can be very different:
@ -194,7 +193,7 @@ The degree of entanglement between the different coupled flows in a single hardw
- independent Rx and Tx sample rates
- independent Rx and Tx center frequencies
- independent Gain, bandwidth, ...
- only the device handle and indication of the presence of the XB200 accesory board is common
- only the device handle and indication of the presence of the XB200 accessory board is common
- HackRF: this is a half duplex device. Rx and Tx might appear as tightly coupled but since you can use only one or the other then in fact you can control them differently as this is done in sequence. In fact only the common device handle has to be taken care of

View File

@ -16,7 +16,6 @@ SDRangel-3.x:
+ cm256cc
+ dsdcc
+ mbelib
+ nanomsg
+ boost_1_64_0/
### Environment preparation
@ -47,13 +46,6 @@ git clone https://github.com/f4exb/dsdcc.git
```
##### nanomsg:
```
git clone https://github.com/nanomsg/nanomsg.git
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=/opt/local ..
cmake --build . && sudo cmake --build . --target install
```
## Build
Release build configuration with QT Creator

View File

@ -8,7 +8,7 @@ You should take note that the Windows scheduler is just a piece of crap and not
There are no plugins for both flavours of Funcubes since it uses Alsa interface which is Linux exclusively. Changing for the Qt audio portable interface instead could be a solution that will be investigated in the future.
The SDRdaemon plug-in is present only in the 64 bit build version since version 1.1.4. The messaging system based on nanomsg works only in the 64 bit environment. However please be aware that the SDRdaemon plugin is not working well mainly due to the fact that it needs an OS with a decent scheduler and Windows is definitely not this sort of OS (see my previous warning). In fact depending on the case your mileage may vary however the Linux version works always beautifully so you know the options if you really want to use it!
Please be aware that the SDRdaemon plugin is not working well mainly due to the fact that it needs an OS with a decent scheduler and Windows is definitely not this sort of OS (see my previous warning). In fact depending on the case your mileage may vary however the Linux version works always beautifully so you know the options if you really want to use it!
<h3>Build environment</h3>

View File

@ -10,6 +10,7 @@ QMAKE_CXXFLAGS += -std=c++11
TEMPLATE = app
TARGET = sdrangel
INCLUDEPATH += $$PWD/../exports
INCLUDEPATH += $$PWD/../sdrbase
INCLUDEPATH += $$PWD/../sdrgui
INCLUDEPATH += $$PWD/../logging

View File

@ -35,7 +35,11 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo
*/
QCoreApplication::setOrganizationName("f4exb");
QCoreApplication::setApplicationName("SDRangel");
QCoreApplication::setApplicationVersion("3.12.0");
QCoreApplication::setApplicationVersion("4.3.0");
#if QT_VERSION >= 0x050600
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // DPI support
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); //HiDPI pixmaps
#endif
#if 1
qApp->setStyle(QStyleFactory::create("fusion"));

110
appbench/main.cpp Normal file
View File

@ -0,0 +1,110 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB. //
// //
// Swagger server adapter interface //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QCoreApplication>
#include <QSysInfo>
#include <QTimer>
#include <signal.h>
#include <unistd.h>
#include <vector>
#include "loggerwithfile.h"
#include "mainbench.h"
#include "dsp/dsptypes.h"
void handler(int sig) {
fprintf(stderr, "quit the application by signal(%d).\n", sig);
QCoreApplication::quit();
}
void catchUnixSignals(const std::vector<int>& quitSignals) {
sigset_t blocking_mask;
sigemptyset(&blocking_mask);
for (std::vector<int>::const_iterator it = quitSignals.begin(); it != quitSignals.end(); ++it) {
sigaddset(&blocking_mask, *it);
}
struct sigaction sa;
sa.sa_handler = handler;
sa.sa_mask = blocking_mask;
sa.sa_flags = 0;
for (std::vector<int>::const_iterator it = quitSignals.begin(); it != quitSignals.end(); ++it) {
sigaction(*it, &sa, 0);
}
}
static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *logger)
{
QCoreApplication a(argc, argv);
QCoreApplication::setOrganizationName("f4exb");
QCoreApplication::setApplicationName("SDRangelBench");
QCoreApplication::setApplicationVersion("4.3.0");
int catchSignals[] = {SIGQUIT, SIGINT, SIGTERM, SIGHUP};
std::vector<int> vsig(catchSignals, catchSignals + sizeof(catchSignals) / sizeof(int));
catchUnixSignals(vsig);
ParserBench parser;
parser.parse(a);
#if QT_VERSION >= 0x050400
qInfo("%s %s Qt %s %db %s %s DSP Rx:%db Tx:%db PID %lld",
qPrintable(QCoreApplication::applicationName()),
qPrintable(QCoreApplication::applicationVersion()),
qPrintable(QString(QT_VERSION_STR)),
QT_POINTER_SIZE*8,
qPrintable(QSysInfo::currentCpuArchitecture()),
qPrintable(QSysInfo::prettyProductName()),
SDR_RX_SAMP_SZ,
SDR_TX_SAMP_SZ,
QCoreApplication::applicationPid());
#else
qInfo("%s %s Qt %s %db DSP Rx:%db Tx:%db PID %lld",
qPrintable(QCoreApplication::applicationName()),
qPrintable((QCoreApplication::>applicationVersion()),
qPrintable(QString(QT_VERSION_STR)),
QT_POINTER_SIZE*8,
SDR_RX_SAMP_SZ,
SDR_TX_SAMP_SZ,
QCoreApplication::applicationPid());
#endif
MainBench m(logger, parser, &a);
// This will cause the application to exit when the main core is finished
QObject::connect(&m, SIGNAL(finished()), &a, SLOT(quit()));
// This will run the task from the application event loop
QTimer::singleShot(0, &m, SLOT(run()));
return a.exec();
}
int main(int argc, char* argv[])
{
qtwebapp::LoggerWithFile *logger = new qtwebapp::LoggerWithFile(qApp);
logger->installMsgHandler();
int res = runQtApplication(argc, argv, logger);
qWarning("SDRangel quit.");
return res;
}

View File

@ -28,7 +28,6 @@ for f in `find plugins/samplesink/ -name '*.dylib'`; do cp -v $f "${APP_PLUGINS}
for f in `find plugins/samplesource/ -name '*.dylib'`; do cp -v $f "${APP_PLUGINS}/samplesource/"; done
cd $APP_LIB
cp /opt/local/lib/libnanomsg.5.0.0.dylib .
ln -s libdsdcc.dylib libdsdcc.1.dylib
ln -s libdevices.dylib libdevices.1.dylib
ln -s libsdrbase.dylib libsdrbase.1.dylib

View File

@ -56,7 +56,7 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo
QCoreApplication::setOrganizationName("f4exb");
QCoreApplication::setApplicationName("SDRangelSrv");
QCoreApplication::setApplicationVersion("3.12.0");
QCoreApplication::setApplicationVersion("4.3.0");
int catchSignals[] = {SIGQUIT, SIGINT, SIGTERM, SIGHUP};
std::vector<int> vsig(catchSignals, catchSignals + sizeof(catchSignals) / sizeof(int));

View File

@ -9,8 +9,8 @@ QT += core
TEMPLATE = lib
TARGET = cm256cc
CONFIG(MINGW32):LIBCM256CCSRC = "D:\softs\cm256cc"
CONFIG(MINGW64):LIBCM256CCSRC = "D:\softs\cm256cc"
CONFIG(MINGW32):LIBCM256CCSRC = "C:\softs\cm256cc"
CONFIG(MINGW64):LIBCM256CCSRC = "C:\softs\cm256cc"
CONFIG(macx):LIBCM256CCSRC = "../../deps/cm256cc"
INCLUDEPATH += $$LIBCM256CCSRC

View File

@ -0,0 +1,151 @@
# vim: ts=2 sw=2
# - Try to find the required ffmpeg components(default: AVFORMAT, AVUTIL, AVCODEC)
#
# Once done this will define
# FFMPEG_FOUND - System has the all required components.
# FFMPEG_INCLUDE_DIRS - Include directory necessary for using the required components headers.
# FFMPEG_LIBRARIES - Link these to use the required ffmpeg components.
# FFMPEG_DEFINITIONS - Compiler switches required for using the required ffmpeg components.
#
# For each of the components it will additionally set.
# - AVCODEC
# - AVDEVICE
# - AVFORMAT
# - AVFILTER
# - AVUTIL
# - POSTPROC
# - SWSCALE
# the following variables will be defined
# <component>_FOUND - System has <component>
# <component>_INCLUDE_DIRS - Include directory necessary for using the <component> headers
# <component>_LIBRARIES - Link these to use <component>
# <component>_DEFINITIONS - Compiler switches required for using <component>
# <component>_VERSION - The components version
#
# Copyright (c) 2006, Matthias Kretz, <kretz@kde.org>
# Copyright (c) 2008, Alexander Neundorf, <neundorf@kde.org>
# Copyright (c) 2011, Michael Jansen, <kde@michael-jansen.biz>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
include(FindPackageHandleStandardArgs)
# The default components were taken from a survey over other FindFFMPEG.cmake files
if (NOT FFmpeg_FIND_COMPONENTS)
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL)
endif ()
#
### Macro: set_component_found
#
# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present.
#
macro(set_component_found _component )
if (${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS)
# message(STATUS " - ${_component} found.")
set(${_component}_FOUND TRUE)
else ()
# message(STATUS " - ${_component} not found.")
endif ()
endmacro()
#
### Macro: find_component
#
# Checks for the given component by invoking pkgconfig and then looking up the libraries and
# include directories.
#
macro(find_component _component _pkgconfig _library _header)
if (NOT WIN32)
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(PC_${_component} ${_pkgconfig})
endif ()
endif (NOT WIN32)
find_path(${_component}_INCLUDE_DIRS ${_header}
HINTS
${PC_LIB${_component}_INCLUDEDIR}
${PC_LIB${_component}_INCLUDE_DIRS}
PATH_SUFFIXES
ffmpeg
)
find_library(${_component}_LIBRARIES NAMES ${_library}
HINTS
${PC_LIB${_component}_LIBDIR}
${PC_LIB${_component}_LIBRARY_DIRS}
)
set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING "The ${_component} CFLAGS.")
set(${_component}_VERSION ${PC_${_component}_VERSION} CACHE STRING "The ${_component} version number.")
set_component_found(${_component})
mark_as_advanced(
${_component}_INCLUDE_DIRS
${_component}_LIBRARIES
${_component}_DEFINITIONS
${_component}_VERSION)
endmacro()
# Check for cached results. If there are skip the costly part.
if (NOT FFMPEG_LIBRARIES)
# Check for all possible component.
find_component(AVCODEC libavcodec avcodec libavcodec/avcodec.h)
find_component(AVFORMAT libavformat avformat libavformat/avformat.h)
find_component(AVDEVICE libavdevice avdevice libavdevice/avdevice.h)
find_component(AVUTIL libavutil avutil libavutil/avutil.h)
find_component(AVFILTER libavfilter avfilter libavfilter/avfilter.h)
find_component(SWSCALE libswscale swscale libswscale/swscale.h)
find_component(POSTPROC libpostproc postproc libpostproc/postprocess.h)
find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h)
# Check if the required components were found and add their stuff to the FFMPEG_* vars.
foreach (_component ${FFmpeg_FIND_COMPONENTS})
if (${_component}_FOUND)
# message(STATUS "Required component ${_component} present.")
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${${_component}_LIBRARIES})
set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} ${${_component}_DEFINITIONS})
list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS})
else ()
# message(STATUS "Required component ${_component} missing.")
endif ()
endforeach ()
# Build the include path with duplicates removed.
if (FFMPEG_INCLUDE_DIRS)
list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS)
endif ()
# cache the vars.
set(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} CACHE STRING "The FFmpeg include directories." FORCE)
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} CACHE STRING "The FFmpeg libraries." FORCE)
set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} CACHE STRING "The FFmpeg cflags." FORCE)
mark_as_advanced(FFMPEG_INCLUDE_DIRS
FFMPEG_LIBRARIES
FFMPEG_DEFINITIONS)
endif ()
# Now set the noncached _FOUND vars for the components.
foreach (_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROCESS SWSCALE)
set_component_found(${_component})
endforeach ()
# Compile the list of required vars
set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS)
foreach (_component ${FFmpeg_FIND_COMPONENTS})
list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS)
endforeach ()
# Give a nice error message if some of the required vars are missing.
find_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_REQUIRED_VARS})

View File

@ -1,6 +1,6 @@
if(NOT LIBHACKRF_FOUND)
pkg_check_modules (LIBHACKRF_PKG libairspy)
pkg_check_modules (LIBHACKRF_PKG libhackrf)
find_path(LIBHACKRF_INCLUDE_DIR NAMES libhackrf/hackrf.h
PATHS
${LIBHACKRF_PKG_INCLUDE_DIRS}

View File

@ -1,28 +0,0 @@
if(NOT LIBNANOMSG_FOUND)
pkg_check_modules (LIBNANOMSG_PKG libnanomsg)
find_path(LIBNANOMSG_INCLUDE_DIR NAMES nanomsg/nn.h
PATHS
${LIBNANOMSG_PKG_INCLUDE_DIRS}
/usr/include
/usr/local/include
)
find_library(LIBNANOMSG_LIBRARIES NAMES nanomsg
PATHS
${LIBNANOMSG_PKG_LIBRARY_DIRS}
/usr/lib
/usr/local/lib
)
if(LIBNANOMSG_INCLUDE_DIR AND LIBNANOMSG_LIBRARIES)
set(LIBNANOMSG_FOUND TRUE CACHE INTERNAL "libnanomsg found")
message(STATUS "Found libnanomsg: ${LIBNANOMSG_INCLUDE_DIR}, ${LIBNANOMSG_LIBRARIES}")
else(LIBNANOMSG_INCLUDE_DIR AND LIBNANOMSG_LIBRARIES)
set(LIBNANOMSG_FOUND FALSE CACHE INTERNAL "libnanomsg found")
message(STATUS "libnanomsg not found.")
endif(LIBNANOMSG_INCLUDE_DIR AND LIBNANOMSG_LIBRARIES)
mark_as_advanced(LIBNANOMSG_INCLUDE_DIR LIBNANOMSG_LIBRARIES)
endif(NOT LIBNANOMSG_FOUND)

View File

@ -0,0 +1,34 @@
# Find Soapy SDR
if (NOT SOAPYSDR_INCLUDE_DIR)
FIND_PATH (SOAPYSDR_INCLUDE_DIR
NAMES SoapySDR/Version.h
PATHS
/usr/include
/usr/local/include
)
endif()
if (NOT SOAPYSDR_LIBRARY)
FIND_LIBRARY (SOAPYSDR_LIBRARY
NAMES SoapySDR
HINTS ${CMAKE_INSTALL_PREFIX}/lib
${CMAKE_INSTALL_PREFIX}/lib64
PATHS /usr/local/lib
/usr/local/lib64
/usr/lib
/usr/lib64
)
endif()
if (SOAPYSDR_INCLUDE_DIR AND SOAPYSDR_LIBRARY)
SET(SOAPYSDR_FOUND TRUE)
endif()
if (SOAPYSDR_FOUND)
MESSAGE (STATUS "Found SoapySDR: ${SOAPYSDR_INCLUDE_DIR}, ${SOAPYSDR_LIBRARY}")
else()
MESSAGE (STATUS "Could not find SoapySDR")
endif()
mark_as_advanced(SOAPYSDR_INCLUDE_DIR SOAPYSDR_LIBRARY)

238
debian/changelog vendored
View File

@ -1,10 +1,220 @@
sdrangel (4.3.0-1) unstable; urgency=medium
* SoapySDR support
* BladeRF2 corrections
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 18 Nov 2018 21:14:18 +0100
sdrangel (4.2.4-1) unstable; urgency=medium
* LimeSDR: use LimeSuite 18.10.0 for builds
* DSD demod: use 1 dB steps for squelch
* Scope: fixed some trigger issues. Fixes issue #233
* Scope: implemented trigger holdoff. May fix more trigger issues.
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sat, 27 Oct 2018 21:14:18 +0200
sdrangel (4.2.3-1) unstable; urgency=medium
* Scope: fixed channel rate affecting scope in memory mode. Issue #227
* Spectrum: limit depth to 1000 when in moving average mode to avoid RAM exhaustion
* Spectrum: reworked phosphor display controls. Re-implements issue #207
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Fri, 19 Oct 2018 21:14:18 +0200
sdrangel (4.2.2-1) unstable; urgency=medium
* Spectrum: option to get max over a number of FFTs. Implements issue #207
* File Input: fixed wrong times displays due to 32 bit integer ovevlow. Issue #206
* File Input: implemented play loop and playback acceleration
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 14 Oct 2018 21:14:18 +0200
sdrangel (4.2.1-1) unstable; urgency=medium
* FileRecord improvement with robust header and some fixes. Fixes issue #206
* BladeRF2 MO Tx fix so that the two channels are used effectively. Fixes issue #225
* NFM demod: set squelch step to 1 dB
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Wed, 10 Oct 2018 21:14:18 +0200
sdrangel (4.2.0-1) unstable; urgency=medium
* LibbladeRF 2.0 support with BladeRF Micro
* Scope: corrected trace memory index position
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 7 Oct 2018 21:14:18 +0200
sdrangel (4.1.0-1) unstable; urgency=medium
* Integrated SDRdaemon with a pair of new channel plugins
* Exchanged UDP sink and source names for better consistency
* Fixed AudioFifo to prevent deadlocks. Fixes issue #210
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 16 Sep 2018 21:14:18 +0200
sdrangel (4.0.7-1) unstable; urgency=medium
* Scope: removed old scope objects
* Web API: reduced HTTP server debug messages
* Sink plugins: corrected name getters and setters
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 19 Aug 2018 21:14:18 +0200
sdrangel (4.0.6-1) unstable; urgency=medium
* Web API: RTL-SDR: fixed RF bandwidth setting
* Web API: enhanced DV serial and AM demod interfaces
* Web API: fixed bug in PUT/PATCH of modulators not setting differentially
* Fixed power display going to floor value in some demods
* SSB modulator: fixed sample not reset when no modulation is present
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Tue, 07 Aug 2018 19:14:18 +0200
sdrangel (4.0.5-1) unstable; urgency=medium
* Web API: handle pre-flight requests
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 22 Jul 2018 09:14:18 +0200
sdrangel (4.0.4-1) unstable; urgency=medium
* Fixed PlutoSDR output sample width. Fixes issue #198
* Web API: implemented CORS
* Fix preset group delete not removing presets from the preset window
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Wed, 18 Jul 2018 19:14:18 +0200
sdrangel (4.0.3-1) unstable; urgency=medium
* Spectrum: linear mode for spectrum
* Scope: fixed power display overlay
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 08 Jul 2018 15:14:18 +0200
sdrangel (4.0.2-1) unstable; urgency=medium
* Spectrum: added averaging
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 01 Jul 2018 21:14:18 +0200
sdrangel (4.0.1-1) unstable; urgency=medium
* DSD demod: added NXDN support
* DATV demod: include it only if FFmpeg > 3.1 is installed
* Fixes for Arch. Manual merge of pull request #183
* Scope: new magnitude squared projection mainly for radioastronomy
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sat, 23 Jun 2018 09:14:18 +0200
sdrangel (4.0.0-1) unstable; urgency=medium
* Finalization of REST API and server instance
* Removal of old ChannelAnalyzer and TCPSrc plugins
* Renamed Channel Analyzer NG to Channel Analyzer
* DATV demod: added missing AVUTIL cmake variables
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sat, 09 Jun 2018 20:14:18 +0200
sdrangel (3.14.7-1) unstable; urgency=medium
* ChanelAnalyzerNG: added PLL option and source selection with auto correlation
* RTL-SDR: fixed inf/sup decimators
* AM demod: syncrhronous AM detection option
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 20 May 2018 20:14:18 +0200
sdrangel (3.14.6-1) unstable; urgency=medium
* Fixed keyboard input for negative values on realtive integer value dials
* Get rid of ugly native dialogs
* Inf/Sup frequency shift scheme change to be closer to device center frequency
* PlutoSDR input: fixed Inf/Sup frequency shift calculation
* File record default file name with ISO datetime stamp
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Fri, 11 May 2018 20:14:18 +0200
sdrangel (3.14.5-1) unstable; urgency=medium
* DSD demod: allow audio rates integer multiples of 8k other than 48k
* Added a benchmark program testing decimators
* Optimization of decimators using even/odd technique
* SSB mod: fixed channel unregistration
* AM demod: fixed delayed squelch
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 06 May 2018 20:14:18 +0200
sdrangel (3.14.4-1) unstable; urgency=medium
* AM demod: squelch buffer to open at start of valid squelch
* NFM demod: same as AM with squelch noise tail cut
* SSB demod: squelch buffer to cut squelch noise tail
* DSD demod: squelch buffer to open at start of valid squelch not loosing any samples
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 22 Apr 2018 17:14:18 +0200
sdrangel (3.14.3-1) unstable; urgency=medium
* LimeSDR: compiled with LimeSuite release 18.04.1
* LimeSDR: implemented transverter dialog (issue #157)
* UDP source and sink: make sure audio samples are always on 16 bits
* UDP source and sink: dialog elements for address and port
* Reviewed FFT destruction in many channel sources and sinks (issue #159)
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Fri, 20 Apr 2018 20:14:18 +0200
sdrangel (3.14.2-1) unstable; urgency=medium
* Web API: settings and report for all channel Tx plugins
* Server: AirspyHF, BladeRF and all channel Tx plugins support
* PVS-Studio static analysis corrections (4)
* NFM demod: fixed AF squelch and audio sample rate handling
* BFM demod: fixed segfault in RDS parser
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 15 Apr 2018 12:14:18 +0200
sdrangel (3.14.1-1) unstable; urgency=medium
* NFM: fixed lowpass filter initialization (CTCSS)
* DSD demod: set FM deviation independent from RF bandwidth
* DSD demod: implemented DMR negative with DSDcc v1.7.5
* DSD demod: implemented dialog to view the log of status text messages
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 01 Apr 2018 12:14:18 +0200
sdrangel (3.14.0-1) unstable; urgency=medium
* New audio devices management
* DATV demod: fixed message handling and thus screen initialization issue
* Removed UDP/RTP copy audio from channel sink plugins entirely
* Removed UDP address and port from Channel marker
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Fri, 30 Mar 2018 16:14:18 +0200
sdrangel (3.13.1-1) unstable; urgency=medium
* Web API: settings and report enry points for AM demod and AirspyHF
* Web API: client Python script scanner example
* LimeSDR: fixed channelA/B frequency setting with latest LimeSuite
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 25 Mar 2018 06:14:18 +0100
sdrangel (3.13.0-1) unstable; urgency=medium
* DATV (Digital Amateur TV) demodulator.
* Option to use RTP protocol for UDP audio for AM, NFM, SSB, WFM.
* LimeSDR: show NCO and center frequency actual values
* DSD demod: new simplified symbol scope display. Reworked GUI.
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 11 Mar 2018 06:14:18 +0100
sdrangel (3.12.0-1) unstable; urgency=medium
* Perseus support.
* 24 bit Rx DSP Debian builds
* DC and IQ correction fixes
* AirspyHF: fall back to official library support
* Test source: implemented phase imbalance
* Test source: implemented phase imbalance
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 11 Feb 2018 12:14:18 +0100
@ -17,7 +227,7 @@ sdrangel (3.11.1-1) unstable; urgency=medium
sdrangel (3.11.0-1) unstable; urgency=medium
* AirspyHF: support
* Refactored 8 bit samples shifting during decimation (RTL-SDR and HackRF Rx)
* Refactored 8 bit samples shifting during decimation (RTL-SDR and HackRF Rx)
* RTL-SDR: implemented RF filter control (tuner bandwidth)
* Airspy, BladeRF, HackRF, PlutoSDR, RTLSDR, SDRPlay: fix for no decimation
* Test source input plugin for test of software internals
@ -41,7 +251,7 @@ sdrangel (3.10.0-1) unstable; urgency=medium
* AM, SSB demodulators and SSB modulator: fix sample rate handling
* Enhancements to presets processing and GUI
* Improved build and system info logging
* Web API: added function to set device set focus (GUI only)
* Web API: added function to set device set focus (GUI only)
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sun, 07 Jan 2018 09:14:18 +0100
@ -58,7 +268,7 @@ sdrangel (3.9.0-1) unstable; urgency=medium
* Server: proof of concept
* DSD demodulator: added optional high pass filter on audio (uese dsdcc v1.7.3)
* Down/Up channelizers: enqeue MsgChannelizerNotification to sample sink/source
* Down/Up channelizers: enqeue MsgChannelizerNotification to sample sink/source
* Separate channel sample rate and offset frequency this data from settings
* Use specific method to apply channelizer sample rate and frequency offset changes
@ -181,14 +391,14 @@ sdrangel (3.7.1-1) unstable; urgency=medium
sdrangel (3.7.0-1) unstable; urgency=medium
* PlutoSDR: Rx support
* PlutoSDR: Rx support
* GUI segregation: preliminary works
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Thu, 17 Sep 2017 23:14:18 +0200
sdrangel (3.6.1-1) unstable; urgency=medium
* Basic channel settings dialog with title+color update and UDP parameters
* Basic channel settings dialog with title+color update and UDP parameters
* Applied to UDPSink, UDPSource, DSDDemod, AMDemod, BFMDemod, NFMDemod
* DSD, AM, NFM, BFM demods: added possibility to send AF via UDP
@ -227,7 +437,7 @@ sdrangel (3.5.3-1) unstable; urgency=medium
sdrangel (3.5.2-1) unstable; urgency=medium
* HackRF: stop Rx before start Tx automatically and vice versa
* HackRF: added option on Rx to drive Tx frequency change
* HackRF: added option on Rx to drive Tx frequency change
* SSB mod and demod: make UI displays consistent with DSB, USB and LSB modes
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Sat, 22 Jul 2017 09:14:18 +0200
@ -250,13 +460,13 @@ sdrangel (3.5.0-1) unstable; urgency=medium
* Changed frequency thumbweels color scheme
* Activated compiler warnings and fixed warnings
* Lots of little GUI fixes
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Mon, 11 Jun 2017 19:14:18 +0200
sdrangel (3.4.5-1) unstable; urgency=medium
* Removed default constuctors in Moving average and AGC classes
* Removed default constuctors in Moving average and AGC classes
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Mon, 11 May 2017 21:14:18 +0100
sdrangel (3.4.4-1) unstable; urgency=medium
@ -266,14 +476,14 @@ sdrangel (3.4.4-1) unstable; urgency=medium
* LimeSDR: Windows 64 build
* LimeSDR: integrated Debian build
* cmake modules: search lib64 libraries
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Mon, 08 May 2017 21:14:18 +0100
sdrangel (3.4.3-1) unstable; urgency=medium
* DSD demod: use version 1.7.1 of dsdcc with PLL for symbol synchronization as an option
* LimeSDR: fixed antenna selection in both input and output plugins
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Mon, 08 May 2017 23:14:18 +0100
sdrangel (3.4.2-1) unstable; urgency=medium
@ -281,7 +491,7 @@ sdrangel (3.4.2-1) unstable; urgency=medium
* DSD demod: use version 1.7.0 of dsdcc with PLL for symbol synchronization
* DSD demod: kernel >= 4.4.52 workaround for SerialDV
* Code cleanup: cppchack and Eclipse warnings
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Wed, 26 Apr 2017 23:14:18 +0100
sdrangel (3.4.1-1) unstable; urgency=medium
@ -290,7 +500,7 @@ sdrangel (3.4.1-1) unstable; urgency=medium
* HackRF support: fixed start/stop sequence
* WFM Demod enhancement
* CW Keyer: specifiy char signedness to fix error with some compilers
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Wed, 26 Apr 2017 23:14:18 +0100
sdrangel (3.4.0-1) unstable; urgency=medium

2
debian/control vendored
View File

@ -10,7 +10,7 @@ Homepage: https://github.com/f4exb/sdrangel
Package: sdrangel
Architecture: any
Depends: libc6, libasound2, libfftw3-single3, libgcc1, libgl1-mesa-glx, libnanomsg0|libnanomsg4, libqt5core5a, libqt5gui5, libqt5multimedia5, libqt5network5, libqt5opengl5, libqt5widgets5, libqt5multimedia5-plugins, libstdc++6, libusb-1.0-0, libopencv-dev, libsqlite3-dev, pulseaudio, libxml2, ${shlibs:Depends}, ${misc:Depends}
Depends: libc6, libasound2, libfftw3-single3, libgcc1, libgl1-mesa-glx, libqt5core5a, libqt5gui5, libqt5multimedia5, libqt5network5, libqt5opengl5, libqt5widgets5, libqt5multimedia5-plugins, libstdc++6, libusb-1.0-0, libopencv-dev, pulseaudio, libxml2, ffmpeg, libavcodec-dev, libavformat-dev, ${shlibs:Depends}, ${misc:Depends}
Description: SDR/Analyzer/Generator front-end for various hardware
SDR/Analyzer/Generator front-end for Airspy, BladeRF, HackRF, RTL-SDR, FunCube, LimeSDR, PlutoSDR.
Also File source and sink for I/Q samples, network I/Q sources with SDRDaemon.

View File

@ -3,15 +3,18 @@ project(devices)
find_package(LibUSB)
if (BUILD_DEBIAN)
add_subdirectory(bladerf)
add_subdirectory(bladerf1)
add_subdirectory(bladerf2)
add_subdirectory(hackrf)
add_subdirectory(limesdr)
add_subdirectory(perseus)
add_subdirectory(plutosdr)
add_subdirectory(soapysdr)
else(BUILD_DEBIAN)
find_package(LibBLADERF)
if(LIBUSB_FOUND AND LIBBLADERF_FOUND)
add_subdirectory(bladerf)
add_subdirectory(bladerf1)
add_subdirectory(bladerf2)
endif(LIBUSB_FOUND AND LIBBLADERF_FOUND)
find_package(LibHACKRF)
@ -34,4 +37,8 @@ else(BUILD_DEBIAN)
add_subdirectory(perseus)
endif()
find_package(SoapySDR)
if(LIBUSB_FOUND AND SOAPYSDR_FOUND)
add_subdirectory(soapysdr)
endif()
endif (BUILD_DEBIAN)

View File

@ -0,0 +1,50 @@
project(bladerf1device)
set(bladerf1device_SOURCES
devicebladerf1.cpp
devicebladerf1values.cpp
devicebladerf1shared.cpp
)
set(bladerf1device_HEADERS
devicebladerf1.h
devicebladerf1values.h
devicebladerf1param.h
devicebladerf1shared.h
)
if (BUILD_DEBIAN)
include_directories(
.
${CMAKE_CURRENT_BINARY_DIR}
${LIBBLADERFLIBSRC}/include
${LIBBLADERFLIBSRC}/src
)
else (BUILD_DEBIAN)
include_directories(
.
${CMAKE_CURRENT_BINARY_DIR}
${LIBBLADERF_INCLUDE_DIR}
)
endif (BUILD_DEBIAN)
#add_definitions(${QT_DEFINITIONS})
#add_definitions(-DQT_SHARED)
add_library(bladerf1device SHARED
${bladerf1device_SOURCES}
)
if (BUILD_DEBIAN)
target_link_libraries(bladerf1device
bladerf
sdrbase
)
else (BUILD_DEBIAN)
target_link_libraries(bladerf1device
${LIBBLADERF_LIBRARIES}
sdrbase
)
endif (BUILD_DEBIAN)
install(TARGETS bladerf1device DESTINATION lib)

View File

@ -14,17 +14,20 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "../bladerf1/devicebladerf1.h"
#include <QtGlobal>
#include <cstdio>
#include <cstring>
#include "devicebladerf.h"
bool DeviceBladeRF::open_bladerf(struct bladerf **dev, const char *serial)
bool DeviceBladeRF1::open_bladerf(struct bladerf **dev, const char *serial)
{
int fpga_loaded;
if ((*dev = open_bladerf_from_serial(serial)) == 0)
{
fprintf(stderr, "DeviceBladeRF::open_bladerf: could not open BladeRF\n");
qCritical("DeviceBladeRF::open_bladerf: could not open BladeRF");
return false;
}
@ -32,20 +35,20 @@ bool DeviceBladeRF::open_bladerf(struct bladerf **dev, const char *serial)
if (fpga_loaded < 0)
{
fprintf(stderr, "DeviceBladeRF::open_bladerf: failed to check FPGA state: %s\n",
bladerf_strerror(fpga_loaded));
qCritical("DeviceBladeRF::open_bladerf: failed to check FPGA state: %s",
bladerf_strerror(fpga_loaded));
return false;
}
else if (fpga_loaded == 0)
{
fprintf(stderr, "BladerfOutput::start: the device's FPGA is not loaded.\n");
qCritical("BladerfOutput::start: the device's FPGA is not loaded.");
return false;
}
return true;
}
struct bladerf *DeviceBladeRF::open_bladerf_from_serial(const char *serial)
struct bladerf *DeviceBladeRF1::open_bladerf_from_serial(const char *serial)
{
int status;
struct bladerf *dev;
@ -69,12 +72,12 @@ struct bladerf *DeviceBladeRF::open_bladerf_from_serial(const char *serial)
if (status == BLADERF_ERR_NODEV)
{
fprintf(stderr, "DeviceBladeRF::open_bladerf_from_serial: No devices available with serial=%s\n", serial);
qCritical("DeviceBladeRF::open_bladerf_from_serial: No devices available with serial %s", serial);
return 0;
}
else if (status != 0)
{
fprintf(stderr, "DeviceBladeRF::open_bladerf_from_serial: Failed to open device with serial=%s (%s)\n",
qCritical("DeviceBladeRF::open_bladerf_from_serial: Failed to open device with serial %s (%s)",
serial, bladerf_strerror(status));
return 0;
}
@ -84,61 +87,6 @@ struct bladerf *DeviceBladeRF::open_bladerf_from_serial(const char *serial)
}
}
const unsigned int BladerfSampleRates::m_nb_rates = 22;
const unsigned int BladerfSampleRates::m_rates[BladerfSampleRates::m_nb_rates] = {
1536000,
1600000,
2000000,
2304000,
2400000,
3072000,
3200000,
4333333, // for GSM
4608000,
4800000,
6144000,
7680000,
9216000,
9600000,
10752000,
12288000,
18432000,
19200000,
24576000,
30720000,
36864000,
39936000};
unsigned int BladerfSampleRates::getRate(unsigned int rate_index)
{
if (rate_index < m_nb_rates)
{
return m_rates[rate_index];
}
else
{
return m_rates[0];
}
}
unsigned int BladerfSampleRates::getRateIndex(unsigned int rate)
{
for (unsigned int i=0; i < m_nb_rates; i++)
{
if (rate == m_rates[i])
{
return i;
}
}
return 0;
}
unsigned int BladerfSampleRates::getNbRates()
{
return BladerfSampleRates::m_nb_rates;
}
const unsigned int BladerfBandwidths::m_nb_halfbw = 16;
const unsigned int BladerfBandwidths::m_halfbw[BladerfBandwidths::m_nb_halfbw] = {
750,

View File

@ -19,7 +19,9 @@
#include <libbladeRF.h>
class DeviceBladeRF
#include "export.h"
class DEVICES_API DeviceBladeRF1
{
public:
static bool open_bladerf(struct bladerf **dev, const char *serial);
@ -28,16 +30,6 @@ private:
static struct bladerf *open_bladerf_from_serial(const char *serial);
};
class BladerfSampleRates {
public:
static unsigned int getRate(unsigned int rate_index);
static unsigned int getRateIndex(unsigned int rate);
static unsigned int getNbRates();
private:
static const unsigned int m_nb_rates;
static const unsigned int m_rates[];
};
class BladerfBandwidths {
public:
static unsigned int getBandwidth(unsigned int bandwidth_index);

View File

@ -14,8 +14,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef DEVICES_BLADERF_DEVICEBLADERFPARAM_H_
#define DEVICES_BLADERF_DEVICEBLADERFPARAM_H_
#ifndef DEVICES_BLADERF1_DEVICEBLADERF1PARAM_H_
#define DEVICES_BLADERF1_DEVICEBLADERF1PARAM_H_
#include <libbladeRF.h>
@ -23,16 +23,16 @@
* This structure is owned by each of the parties sharing the same physical device
* It allows exchange of information on the common resources
*/
struct DeviceBladeRFParams
struct DeviceBladeRF1Params
{
struct bladerf *m_dev; //!< device handle if the party has ownership else 0
bool m_xb200Attached; //!< true if XB200 is attached and owned by the party
DeviceBladeRFParams() :
DeviceBladeRF1Params() :
m_dev(0),
m_xb200Attached(false)
{
}
};
#endif /* DEVICES_BLADERF_DEVICEBLADERFPARAM_H_ */
#endif /* DEVICES_BLADERF1_DEVICEBLADERF1PARAM_H_ */

View File

@ -14,8 +14,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "devicebladerfshared.h"
#include "../bladerf1/devicebladerf1shared.h"
const float DeviceBladeRFShared::m_sampleFifoLengthInSeconds = 0.25;
const int DeviceBladeRFShared::m_sampleFifoMinSize = 75000; // 300 kS/s knee
const int DeviceBladeRFShared::m_sampleFifoMinSize32 = 150000; // Fixed for interpolation by 32
const float DeviceBladeRF1Shared::m_sampleFifoLengthInSeconds = 0.25;
const int DeviceBladeRF1Shared::m_sampleFifoMinSize = 75000; // 300 kS/s knee
const int DeviceBladeRF1Shared::m_sampleFifoMinSize32 = 150000; // Fixed for interpolation by 32

View File

@ -18,8 +18,9 @@
#define DEVICES_BLADERF_DEVICEHACKRFSHARED_H_
#include "util/message.h"
#include "export.h"
class DeviceBladeRFShared
class DEVICES_API DeviceBladeRF1Shared
{
public:
static const float m_sampleFifoLengthInSeconds;

View File

@ -14,11 +14,11 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "devicebladerfvalues.h"
#include "../bladerf1/devicebladerf1values.h"
unsigned int DeviceBladeRFBandwidths::m_nb_halfbw = 16;
unsigned int DeviceBladeRFBandwidths::m_halfbw[] = {
unsigned int DeviceBladeRF1Bandwidths::m_nb_halfbw = 16;
unsigned int DeviceBladeRF1Bandwidths::m_halfbw[] = {
750,
875,
1250,
@ -36,7 +36,7 @@ unsigned int DeviceBladeRFBandwidths::m_halfbw[] = {
10000,
14000};
unsigned int DeviceBladeRFBandwidths::getBandwidth(unsigned int bandwidth_index)
unsigned int DeviceBladeRF1Bandwidths::getBandwidth(unsigned int bandwidth_index)
{
if (bandwidth_index < m_nb_halfbw)
{
@ -48,7 +48,7 @@ unsigned int DeviceBladeRFBandwidths::getBandwidth(unsigned int bandwidth_index)
}
}
unsigned int DeviceBladeRFBandwidths::getBandwidthIndex(unsigned int bandwidth)
unsigned int DeviceBladeRF1Bandwidths::getBandwidthIndex(unsigned int bandwidth)
{
for (unsigned int i=0; i < m_nb_halfbw; i++)
{
@ -61,9 +61,9 @@ unsigned int DeviceBladeRFBandwidths::getBandwidthIndex(unsigned int bandwidth)
return 0;
}
unsigned int DeviceBladeRFBandwidths::getNbBandwidths()
unsigned int DeviceBladeRF1Bandwidths::getNbBandwidths()
{
return DeviceBladeRFBandwidths::m_nb_halfbw;
return DeviceBladeRF1Bandwidths::m_nb_halfbw;
}

View File

@ -14,11 +14,12 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef DEVICES_BLADERF_DEVICEBLADERFVALUES_H_
#define DEVICES_BLADERF_DEVICEBLADERFVALUES_H_
#ifndef DEVICES_BLADERF1_DEVICEBLADERF1VALUES_H_
#define DEVICES_BLADERF1_DEVICEBLADERF1VALUES_H_
#include "export.h"
class DeviceBladeRFBandwidths {
class DEVICES_API DeviceBladeRF1Bandwidths {
public:
static unsigned int getBandwidth(unsigned int bandwidth_index);
static unsigned int getBandwidthIndex(unsigned int bandwidth);
@ -28,4 +29,4 @@ private:
static unsigned int m_nb_halfbw;
};
#endif /* DEVICES_BLADERF_DEVICEBLADERFVALUES_H_ */
#endif /* DEVICES_BLADERF1_DEVICEBLADERF1VALUES_H_ */

View File

@ -1,16 +1,13 @@
project(bladerfdevice)
project(bladerf2device)
set(bladerfdevice_SOURCES
devicebladerf.cpp
devicebladerfvalues.cpp
devicebladerfshared.cpp
set(bladerf2device_SOURCES
devicebladerf2.cpp
devicebladerf2shared.cpp
)
set(bladerfdevice_HEADERS
devicebladerf.h
devicebladerfvalues.h
devicebladerfparam.h
devicebladerfshared.h
set(bladerf2device_HEADERS
devicebladerf2.h
devicebladerf2shared.h
)
if (BUILD_DEBIAN)
@ -31,20 +28,20 @@ endif (BUILD_DEBIAN)
#add_definitions(${QT_DEFINITIONS})
#add_definitions(-DQT_SHARED)
add_library(bladerfdevice SHARED
${bladerfdevice_SOURCES}
add_library(bladerf2device SHARED
${bladerf2device_SOURCES}
)
if (BUILD_DEBIAN)
target_link_libraries(bladerfdevice
target_link_libraries(bladerf2device
bladerf
sdrbase
)
else (BUILD_DEBIAN)
target_link_libraries(bladerfdevice
target_link_libraries(bladerf2device
${LIBBLADERF_LIBRARIES}
sdrbase
)
endif (BUILD_DEBIAN)
install(TARGETS bladerfdevice DESTINATION lib)
install(TARGETS bladerf2device DESTINATION lib)

View File

@ -0,0 +1,504 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016-2017 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <QtGlobal>
#include "devicebladerf2.h"
DeviceBladeRF2::DeviceBladeRF2() :
m_dev(0),
m_nbRxChannels(0),
m_nbTxChannels(0),
m_rxOpen(0),
m_txOpen(0)
{}
DeviceBladeRF2::~DeviceBladeRF2()
{
if (m_dev)
{
bladerf_close(m_dev);
m_dev = 0;
}
if (m_rxOpen) {
delete[] m_rxOpen;
}
if (m_txOpen) {
delete[] m_txOpen;
}
}
bool DeviceBladeRF2::open(const char *serial)
{
int fpga_loaded;
if ((m_dev = open_bladerf_from_serial(serial)) == 0)
{
qCritical("DeviceBladeRF2::open: could not open BladeRF");
return false;
}
fpga_loaded = bladerf_is_fpga_configured(m_dev);
if (fpga_loaded < 0)
{
qCritical("DeviceBladeRF2::open: failed to check FPGA state: %s",
bladerf_strerror(fpga_loaded));
return false;
}
else if (fpga_loaded == 0)
{
qCritical("DeviceBladeRF2::open: the device's FPGA is not loaded.");
return false;
}
m_nbRxChannels = bladerf_get_channel_count(m_dev, BLADERF_RX);
m_nbTxChannels = bladerf_get_channel_count(m_dev, BLADERF_TX);
m_rxOpen = new bool[m_nbRxChannels];
m_txOpen = new bool[m_nbTxChannels];
std::fill(m_rxOpen, m_rxOpen + m_nbRxChannels, false);
std::fill(m_txOpen, m_txOpen + m_nbTxChannels, false);
return true;
}
void DeviceBladeRF2::close()
{
if (m_dev)
{
bladerf_close(m_dev);
m_dev = 0;
}
}
struct bladerf *DeviceBladeRF2::open_bladerf_from_serial(const char *serial)
{
int status;
struct bladerf *dev;
struct bladerf_devinfo info;
/* Initialize all fields to "don't care" wildcard values.
*
* Immediately passing this to bladerf_open_with_devinfo() would cause
* libbladeRF to open any device on any available backend. */
bladerf_init_devinfo(&info);
/* Specify the desired device's serial number, while leaving all other
* fields in the info structure wildcard values */
if (serial != 0)
{
strncpy(info.serial, serial, BLADERF_SERIAL_LENGTH - 1);
info.serial[BLADERF_SERIAL_LENGTH - 1] = '\0';
}
status = bladerf_open_with_devinfo(&dev, &info);
if (status == BLADERF_ERR_NODEV)
{
qCritical("DeviceBladeRF2::open_bladerf_from_serial: No devices available with serial %s", serial);
return 0;
}
else if (status != 0)
{
qCritical("DeviceBladeRF2::open_bladerf_from_serial: Failed to open device with serial %s (%s)",
serial, bladerf_strerror(status));
return 0;
}
else
{
return dev;
}
}
bool DeviceBladeRF2::openRx(int channel)
{
if (!m_dev) {
return false;
}
if ((channel < 0) || (channel >= m_nbRxChannels))
{
qCritical("DeviceBladeRF2::openRx: invalid Rx channel index %d", channel);
return false;
}
int status;
if (!m_rxOpen[channel])
{
status = bladerf_enable_module(m_dev, BLADERF_CHANNEL_RX(channel), true);
if (status < 0)
{
qCritical("DeviceBladeRF2::openRx: failed to enable Rx channel %d: %s",
channel, bladerf_strerror(status));
return false;
}
else
{
qDebug("DeviceBladeRF2::openRx: Rx channel %d enabled", channel);
m_rxOpen[channel] = true;
return true;
}
}
else
{
qDebug("DeviceBladeRF2::openRx: Rx channel %d already opened", channel);
return true;
}
}
bool DeviceBladeRF2::openTx(int channel)
{
if (!m_dev) {
return false;
}
if ((channel < 0) || (channel >= m_nbTxChannels))
{
qCritical("DeviceBladeRF2::openTx: invalid Tx channel index %d", channel);
return false;
}
int status;
if (!m_txOpen[channel])
{
status = bladerf_enable_module(m_dev, BLADERF_CHANNEL_TX(channel), true);
if (status < 0)
{
qCritical("DeviceBladeRF2::openTx: Failed to enable Tx channel %d: %s",
channel, bladerf_strerror(status));
return false;
}
else
{
qDebug("DeviceBladeRF2::openTx: Tx channel %d enabled", channel);
m_txOpen[channel] = true;
return true;
}
}
else
{
qDebug("DeviceBladeRF2::openTx: Tx channel %d already opened", channel);
return true;
}
}
void DeviceBladeRF2::closeRx(int channel)
{
if (!m_dev) {
return;
}
if ((channel < 0) || (channel >= m_nbRxChannels))
{
qCritical("DeviceBladeRF2::closeRx: invalid Rx channel index %d", channel);
return;
}
if (m_rxOpen[channel])
{
int status = bladerf_enable_module(m_dev, BLADERF_CHANNEL_RX(channel), false);
m_rxOpen[channel] = false;
if (status < 0) {
qCritical("DeviceBladeRF2::closeRx: failed to disable Rx channel %d: %s", channel, bladerf_strerror(status));
} else {
qDebug("DeviceBladeRF2::closeRx: Rx channel %d disabled", channel);
}
}
else
{
qDebug("DeviceBladeRF2::closeRx: Rx channel %d already closed", channel);
}
}
void DeviceBladeRF2::closeTx(int channel)
{
if (!m_dev) {
return;
}
if ((channel < 0) || (channel >= m_nbTxChannels))
{
qCritical("DeviceBladeRF2::closeTx: invalid Tx channel index %d", channel);
return;
}
if (m_txOpen[channel])
{
int status = bladerf_enable_module(m_dev, BLADERF_CHANNEL_TX(channel), false);
m_txOpen[channel] = false;
if (status < 0) {
qCritical("DeviceBladeRF2::closeTx: failed to disable Tx channel %d: %s", channel, bladerf_strerror(status));
} else {
qDebug("DeviceBladeRF2::closeTx: Tx channel %d disabled", channel);
}
}
else
{
qDebug("DeviceBladeRF2::closeTx: Rx channel %d already closed", channel);
}
}
void DeviceBladeRF2::getFrequencyRangeRx(uint64_t& min, uint64_t& max, int& step)
{
if (m_dev)
{
const struct bladerf_range *range;
int status;
status = bladerf_get_frequency_range(m_dev, BLADERF_CHANNEL_RX(0), &range);
if (status < 0)
{
qCritical("DeviceBladeRF2::getFrequencyRangeRx: Failed to get Rx frequency range: %s",
bladerf_strerror(status));
}
else
{
min = range->min;
max = range->max;
step = range->step;
}
}
}
void DeviceBladeRF2::getFrequencyRangeTx(uint64_t& min, uint64_t& max, int& step)
{
if (m_dev)
{
const struct bladerf_range *range;
int status;
status = bladerf_get_frequency_range(m_dev, BLADERF_CHANNEL_TX(0), &range);
if (status < 0)
{
qCritical("DeviceBladeRF2::getFrequencyRangeTx: Failed to get Tx frequency range: %s",
bladerf_strerror(status));
}
else
{
min = range->min;
max = range->max;
step = range->step;
}
}
}
void DeviceBladeRF2::getSampleRateRangeRx(int& min, int& max, int& step)
{
if (m_dev)
{
const struct bladerf_range *range;
int status;
status = bladerf_get_sample_rate_range(m_dev, BLADERF_CHANNEL_RX(0), &range);
if (status < 0)
{
qCritical("DeviceBladeRF2::getSampleRateRangeRx: Failed to get Rx sample rate range: %s",
bladerf_strerror(status));
}
else
{
min = range->min;
max = range->max;
step = range->step;
}
}
}
void DeviceBladeRF2::getSampleRateRangeTx(int& min, int& max, int& step)
{
if (m_dev)
{
const struct bladerf_range *range;
int status;
status = bladerf_get_sample_rate_range(m_dev, BLADERF_CHANNEL_TX(0), &range);
if (status < 0)
{
qCritical("DeviceBladeRF2::getSampleRateRangeTx: Failed to get Tx sample rate range: %s",
bladerf_strerror(status));
}
else
{
min = range->min;
max = range->max;
step = range->step;
}
}
}
void DeviceBladeRF2::getBandwidthRangeRx(int& min, int& max, int& step)
{
if (m_dev)
{
const struct bladerf_range *range;
int status;
status = bladerf_get_bandwidth_range(m_dev, BLADERF_CHANNEL_RX(0), &range);
if (status < 0)
{
qCritical("DeviceBladeRF2::getBandwidthRangeRx: Failed to get Rx bandwidth range: %s",
bladerf_strerror(status));
}
else
{
min = range->min;
max = range->max;
step = range->step;
}
}
}
void DeviceBladeRF2::getBandwidthRangeTx(int& min, int& max, int& step)
{
if (m_dev)
{
const struct bladerf_range *range;
int status;
status = bladerf_get_bandwidth_range(m_dev, BLADERF_CHANNEL_TX(0), &range);
if (status < 0)
{
qCritical("DeviceBladeRF2::getBandwidthRangeTx: Failed to get Tx bandwidth range: %s",
bladerf_strerror(status));
}
else
{
min = range->min;
max = range->max;
step = range->step;
}
}
}
void DeviceBladeRF2::getGlobalGainRangeRx(int& min, int& max, int& step)
{
if (m_dev)
{
const struct bladerf_range *range;
int status;
status = bladerf_get_gain_range(m_dev, BLADERF_CHANNEL_RX(0), &range);
if (status < 0)
{
qCritical("DeviceBladeRF2::getGlobalGainRangeRx: Failed to get Rx global gain range: %s",
bladerf_strerror(status));
}
else
{
min = range->min;
max = range->max;
step = range->step;
}
}
}
void DeviceBladeRF2::getGlobalGainRangeTx(int& min, int& max, int& step)
{
if (m_dev)
{
const struct bladerf_range *range;
int status;
status = bladerf_get_gain_range(m_dev, BLADERF_CHANNEL_TX(0), &range);
if (status < 0)
{
qCritical("DeviceBladeRF2::getGlobalGainRangeTx: Failed to get Tx global gain range: %s",
bladerf_strerror(status));
}
else
{
min = range->min;
max = range->max;
step = range->step;
}
}
}
int DeviceBladeRF2::getGainModesRx(const bladerf_gain_modes **modes)
{
if (m_dev)
{
int n = bladerf_get_gain_modes(m_dev, BLADERF_CHANNEL_RX(0), 0);
if (n < 0)
{
qCritical("DeviceBladeRF2::getGainModesRx: Failed to get the number of Rx gain modes: %s", bladerf_strerror(n));
return 0;
}
int status = bladerf_get_gain_modes(m_dev, BLADERF_CHANNEL_RX(0), modes);
if (status < 0)
{
qCritical("DeviceBladeRF2::getGainModesRx: Failed to get Rx gain modes: %s", bladerf_strerror(status));
return 0;
}
else
{
return n;
}
}
else
{
return 0;
}
}
void DeviceBladeRF2::setBiasTeeRx(bool enable)
{
if (m_dev)
{
int status = bladerf_set_bias_tee(m_dev, BLADERF_CHANNEL_RX(0), enable);
if (status < 0) {
qCritical("DeviceBladeRF2::setBiasTeeRx: Failed to set Rx bias tee: %s", bladerf_strerror(status));
}
}
}
void DeviceBladeRF2::setBiasTeeTx(bool enable)
{
if (m_dev)
{
int status = bladerf_set_bias_tee(m_dev, BLADERF_CHANNEL_TX(0), enable);
if (status < 0) {
qCritical("DeviceBladeRF2::setBiasTeeTx: Failed to set Tx bias tee: %s", bladerf_strerror(status));
}
}
}

View File

@ -0,0 +1,67 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef DEVICES_BLADERF2_DEVICEBLADERF2_H_
#define DEVICES_BLADERF2_DEVICEBLADERF2_H_
#include <stdint.h>
#include <libbladeRF.h>
#include "export.h"
class DEVICES_API DeviceBladeRF2
{
public:
DeviceBladeRF2();
~DeviceBladeRF2();
bool open(const char *serial);
void close();
bladerf *getDev() { return m_dev; }
bool openRx(int channel);
bool openTx(int channel);
void closeRx(int channel);
void closeTx(int channel);
void getFrequencyRangeRx(uint64_t& min, uint64_t& max, int& step);
void getFrequencyRangeTx(uint64_t& min, uint64_t& max, int& step);
void getSampleRateRangeRx(int& min, int& max, int& step);
void getSampleRateRangeTx(int& min, int& max, int& step);
void getBandwidthRangeRx(int& min, int& max, int& step);
void getBandwidthRangeTx(int& min, int& max, int& step);
void getGlobalGainRangeRx(int& min, int& max, int& step);
void getGlobalGainRangeTx(int& min, int& max, int& step);
int getGainModesRx(const bladerf_gain_modes**);
void setBiasTeeRx(bool enable);
void setBiasTeeTx(bool enable);
static const unsigned int blockSize = (1<<14);
private:
bladerf *m_dev;
int m_nbRxChannels;
int m_nbTxChannels;
bool *m_rxOpen;
bool *m_txOpen;
static struct bladerf *open_bladerf_from_serial(const char *serial);
};
#endif /* DEVICES_BLADERF2_DEVICEBLADERF2_H_ */

View File

@ -0,0 +1,36 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "devicebladerf2shared.h"
MESSAGE_CLASS_DEFINITION(DeviceBladeRF2Shared::MsgReportBuddyChange, Message)
const float DeviceBladeRF2Shared::m_sampleFifoLengthInSeconds = 0.25;
const int DeviceBladeRF2Shared::m_sampleFifoMinSize = 75000; // 300 kS/s knee
const int DeviceBladeRF2Shared::m_sampleFifoMinSize32 = 150000; // Fixed for interpolation by 32
DeviceBladeRF2Shared::DeviceBladeRF2Shared() :
m_dev(0),
m_channel(-1),
m_source(0),
m_sink(0)
{}
DeviceBladeRF2Shared::~DeviceBladeRF2Shared()
{}

View File

@ -0,0 +1,96 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef DEVICES_BLADERF2_DEVICEBLADERF2SHARED_H_
#define DEVICES_BLADERF2_DEVICEBLADERF2SHARED_H_
#include "util/message.h"
#include "devicebladerf2.h"
class SampleSinkFifo;
class SampleSourceFifo;
class BladeRF2Input;
class BladeRF2Output;
/**
* Structure shared by a buddy with other buddies
*/
class DEVICES_API DeviceBladeRF2Shared
{
public:
class MsgReportBuddyChange : public Message {
MESSAGE_CLASS_DECLARATION
public:
uint64_t getCenterFrequency() const { return m_centerFrequency; }
int getLOppmTenths() const { return m_LOppmTenths; }
int getFcPos() const { return m_fcPos; }
int getDevSampleRate() const { return m_devSampleRate; }
bool getRxElseTx() const { return m_rxElseTx; }
static MsgReportBuddyChange* create(
uint64_t centerFrequency,
int LOppmTenths,
int fcPos,
int devSampleRate,
bool rxElseTx)
{
return new MsgReportBuddyChange(
centerFrequency,
LOppmTenths,
fcPos,
devSampleRate,
rxElseTx);
}
private:
uint64_t m_centerFrequency; //!< Center frequency
int m_LOppmTenths; //!< LO soft correction in tenths of ppm
int m_fcPos; //!< Center frequency position
int m_devSampleRate; //!< device/host sample rate
bool m_rxElseTx; //!< tells which side initiated the message
MsgReportBuddyChange(
uint64_t centerFrequency,
int LOppmTenths,
int fcPos,
int devSampleRate,
bool rxElseTx) :
Message(),
m_centerFrequency(centerFrequency),
m_LOppmTenths(LOppmTenths),
m_fcPos(fcPos),
m_devSampleRate(devSampleRate),
m_rxElseTx(rxElseTx)
{ }
};
DeviceBladeRF2Shared();
~DeviceBladeRF2Shared();
DeviceBladeRF2 *m_dev;
int m_channel; //!< allocated channel (-1 if none)
BladeRF2Input *m_source;
BladeRF2Output *m_sink;
static const float m_sampleFifoLengthInSeconds;
static const int m_sampleFifoMinSize;
static const int m_sampleFifoMinSize32;
};
#endif /* DEVICES_BLADERF2_DEVICEBLADERF2SHARED_H_ */

View File

@ -1,108 +1,175 @@
#--------------------------------------------------------
#
# Pro file for Android and Windows builds with Qt Creator
#
#--------------------------------------------------------
QT += core gui multimedia opengl
TEMPLATE = lib
TARGET = devices
DEFINES += USE_SSE2=1
QMAKE_CXXFLAGS += -msse2
DEFINES += USE_SSSE3=1
QMAKE_CXXFLAGS += -mssse3
DEFINES += USE_SSE4_1=1
QMAKE_CXXFLAGS += -msse4.1
QMAKE_CXXFLAGS += -std=c++11
macx:QMAKE_LFLAGS += -F/Library/Frameworks
CONFIG(MINGW32):LIBBLADERFSRC = "D:\softs\bladeRF\host\libraries\libbladeRF\include"
CONFIG(MINGW64):LIBBLADERFSRC = "D:\softs\bladeRF\host\libraries\libbladeRF\include"
CONFIG(macx):LIBHACKRFSRC = "/opt/local/include"
CONFIG(MINGW32):LIBHACKRFSRC = "D:\softs\hackrf\host"
CONFIG(MINGW64):LIBHACKRFSRC = "D:\softs\hackrf\host"
CONFIG(macx):LIBLIMESUITESRC = "../../../LimeSuite-17.12.0"
CONFIG(MINGW32):LIBLIMESUITESRC = "D:\softs\LimeSuite"
CONFIG(MINGW64):LIBLIMESUITESRC = "D:\softs\LimeSuite"
CONFIG(MINGW32):LIBPERSEUSSRC = "D:\softs\libperseus-sdr"
CONFIG(macx):LIBIIOSRC = "../../../libiio"
CONFIG(MINGW32):LIBIIOSRC = "D:\softs\libiio"
CONFIG(MINGW64):LIBIIOSRC = "D:\softs\libiio"
INCLUDEPATH += $$PWD
INCLUDEPATH += ../sdrbase
INCLUDEPATH += $$LIBBLADERFSRC
INCLUDEPATH += $$LIBHACKRFSRC
INCLUDEPATH += "D:\boost_1_58_0"
INCLUDEPATH += "D:\softs\libusb-1.0.20\include"
INCLUDEPATH += ../liblimesuite/srcmw
INCLUDEPATH += $$LIBLIMESUITESRC/src
INCLUDEPATH += $$LIBLIMESUITESRC/src/ADF4002
INCLUDEPATH += $$LIBLIMESUITESRC/src/ConnectionRegistry
INCLUDEPATH += $$LIBLIMESUITESRC/src/FPGA_common
INCLUDEPATH += $$LIBLIMESUITESRC/src/GFIR
INCLUDEPATH += $$LIBLIMESUITESRC/src/lms7002m
INCLUDEPATH += $$LIBLIMESUITESRC/src/lms7002m_mcu
INCLUDEPATH += $$LIBLIMESUITESRC/src/Si5351C
INCLUDEPATH += $$LIBLIMESUITESRC/src/protocols
INCLUDEPATH += $$LIBLIMESUITESRC/external/cpp-feather-ini-parser
INCLUDEPATH += $$LIBPERSEUSSRC
!macx:INCLUDEPATH += $$LIBIIOSRC
CONFIG(Release):build_subdir = release
CONFIG(Debug):build_subdir = debug
!macx:SOURCES += bladerf/devicebladerf.cpp\
bladerf/devicebladerfvalues.cpp\
bladerf/devicebladerfshared.cpp
SOURCES += hackrf/devicehackrf.cpp\
hackrf/devicehackrfvalues.cpp\
hackrf/devicehackrfshared.cpp
SOURCES += limesdr/devicelimesdr.cpp\
limesdr/devicelimesdrparam.cpp\
limesdr/devicelimesdrshared.cpp
!macx:SOURCES += plutosdr/deviceplutosdr.cpp\
plutosdr/deviceplutosdrbox.cpp\
plutosdr/deviceplutosdrparams.cpp\
plutosdr/deviceplutosdrscan.cpp\
plutosdr/deviceplutosdrshared.cpp
!macx:HEADERS -= bladerf/devicebladerf.h\
bladerf/devicebladerfparam.h\
bladerf/devicebladerfvalues.h\
bladerf/devicebladerfshared.h
HEADERS += hackrf/devicehackrf.h\
hackrf/devicehackrfparam.h\
hackrf/devicehackrfvalues.h\
hackrf/devicehackrfshared.h
HEADERS += limesdr/devicelimesdr.h\
limesdr/devicelimesdrparam.h\
limesdr/devicelimesdrshared.h
HEADERS += plutosdr/deviceplutosdr.h\
plutosdr/deviceplutosdrbox.h\
plutosdr/deviceplutosdrparams.h\
plutosdr/deviceplutosdrscan.h\
plutosdr/deviceplutosdrshared.h
LIBS += -L../sdrbase/$${build_subdir} -lsdrbase
!macx {
LIBS += -L../libbladerf/$${build_subdir} -llibbladerf
LIBS += -L../libhackrf/$${build_subdir} -llibhackrf
LIBS += -L../liblimesuite/$${build_subdir} -lliblimesuite
LIBS += -L../libiio/$${build_subdir} -llibiio
}
macx {
LIBS -= -L../libbladerf/$${build_subdir} -llibbladerf
LIBS -= -L../libhackrf/$${build_subdir} -llibhackrf
LIBS += -L/opt/local/lib -lhackrf
LIBS += -L/usr/local/lib -lLimeSuite
LIBS += -framework iio
}
#--------------------------------------------------------
#
# Pro file for Android and Windows builds with Qt Creator
#
#--------------------------------------------------------
QT += core gui multimedia opengl
TEMPLATE = lib
TARGET = devices
DEFINES += USE_SSE2=1
QMAKE_CXXFLAGS += -msse2
DEFINES += USE_SSSE3=1
QMAKE_CXXFLAGS += -mssse3
DEFINES += USE_SSE4_1=1
QMAKE_CXXFLAGS += -msse4.1
QMAKE_CXXFLAGS += -std=c++11
macx:QMAKE_LFLAGS += -F/Library/Frameworks
CONFIG(MSVC):DEFINES += devices_EXPORTS
CONFIG(MINGW32):LIBBLADERF = "C:\Programs\bladeRF"
CONFIG(MINGW64):LIBBLADERF = "C:\Programs\bladeRF"
CONFIG(macx):LIBHACKRFSRC = "/opt/local/include"
CONFIG(MINGW32):LIBHACKRFSRC = "C:\softs\hackrf\host"
CONFIG(MINGW64):LIBHACKRFSRC = "C:\softs\hackrf\host"
CONFIG(MSVC):LIBHACKRFSRC = "C:\softs\hackrf\host"
CONFIG(macx):LIBLIMESUITESRC = "../../../LimeSuite-17.12.0"
CONFIG(MINGW32):LIBLIMESUITESRC = "C:\softs\LimeSuite"
CONFIG(MINGW64):LIBLIMESUITESRC = "C:\softs\LimeSuite"
CONFIG(MINGW32):LIBPERSEUSSRC = "C:\softs\libperseus-sdr"
CONFIG(macx):LIBIIOSRC = "../../../libiio"
CONFIG(MINGW32):LIBIIOSRC = "C:\softs\libiio"
CONFIG(MINGW64):LIBIIOSRC = "C:\softs\libiio"
INCLUDEPATH += $$PWD
INCLUDEPATH += ../exports
INCLUDEPATH += ../sdrbase
INCLUDEPATH += "C:\softs\boost_1_66_0"
INCLUDEPATH += "C:\softs\libusb-1.0.22\include"
INCLUDEPATH += $$LIBBLADERF/include
INCLUDEPATH += $$LIBHACKRFSRC
MINGW32 || MINGW64 || macx {
INCLUDEPATH += ../liblimesuite/srcmw
INCLUDEPATH += $$LIBLIMESUITESRC/src
INCLUDEPATH += $$LIBLIMESUITESRC/src/ADF4002
INCLUDEPATH += $$LIBLIMESUITESRC/src/ConnectionRegistry
INCLUDEPATH += $$LIBLIMESUITESRC/src/FPGA_common
INCLUDEPATH += $$LIBLIMESUITESRC/src/GFIR
INCLUDEPATH += $$LIBLIMESUITESRC/src/lms7002m
INCLUDEPATH += $$LIBLIMESUITESRC/src/lms7002m_mcu
INCLUDEPATH += $$LIBLIMESUITESRC/src/Si5351C
INCLUDEPATH += $$LIBLIMESUITESRC/src/protocols
INCLUDEPATH += $$LIBLIMESUITESRC/external/cpp-feather-ini-parser
}
MSVC {
INCLUDEPATH += "C:\softs\PothosSDR\include"
}
INCLUDEPATH += $$LIBPERSEUSSRC
!macx:INCLUDEPATH += $$LIBIIOSRC
CONFIG(Release):build_subdir = release
CONFIG(Debug):build_subdir = debug
MINGW32 || MINGW64 {
SOURCES += bladerf1/devicebladerf1.cpp\
bladerf1/devicebladerf1values.cpp\
bladerf1/devicebladerf1shared.cpp
SOURCES += bladerf2/devicebladerf2.cpp\
bladerf2/devicebladerf2shared.cpp
SOURCES += hackrf/devicehackrf.cpp\
hackrf/devicehackrfvalues.cpp\
hackrf/devicehackrfshared.cpp
SOURCES += limesdr/devicelimesdr.cpp\
limesdr/devicelimesdrparam.cpp\
limesdr/devicelimesdrshared.cpp
SOURCES += plutosdr/deviceplutosdr.cpp\
plutosdr/deviceplutosdrbox.cpp\
plutosdr/deviceplutosdrparams.cpp\
plutosdr/deviceplutosdrscan.cpp\
plutosdr/deviceplutosdrshared.cpp
HEADERS += bladerf2/devicebladerf2.h\
bladerf2/devicebladerf2shared.h
HEADERS += bladerf1/devicebladerf1.h\
bladerf1/devicebladerf1param.h\
bladerf1/devicebladerf1values.h\
bladerf1/devicebladerf1shared.h
HEADERS += hackrf/devicehackrf.h\
hackrf/devicehackrfparam.h\
hackrf/devicehackrfvalues.h\
hackrf/devicehackrfshared.h
HEADERS += limesdr/devicelimesdr.h\
limesdr/devicelimesdrparam.h\
limesdr/devicelimesdrshared.h
HEADERS += plutosdr/deviceplutosdr.h\
plutosdr/deviceplutosdrbox.h\
plutosdr/deviceplutosdrparams.h\
plutosdr/deviceplutosdrscan.h\
plutosdr/deviceplutosdrshared.h
}
macx {
SOURCES += hackrf/devicehackrf.cpp\
hackrf/devicehackrfvalues.cpp\
hackrf/devicehackrfshared.cpp
SOURCES += limesdr/devicelimesdr.cpp\
limesdr/devicelimesdrparam.cpp\
limesdr/devicelimesdrshared.cpp
HEADERS += hackrf/devicehackrf.h\
hackrf/devicehackrfparam.h\
hackrf/devicehackrfvalues.h\
hackrf/devicehackrfshared.h
HEADERS += limesdr/devicelimesdr.h\
limesdr/devicelimesdrparam.h\
limesdr/devicelimesdrshared.h
}
MSVC {
SOURCES += hackrf/devicehackrf.cpp\
hackrf/devicehackrfvalues.cpp\
hackrf/devicehackrfshared.cpp
SOURCES += limesdr/devicelimesdr.cpp\
limesdr/devicelimesdrparam.cpp\
limesdr/devicelimesdrshared.cpp
HEADERS += hackrf/devicehackrf.h\
hackrf/devicehackrfparam.h\
hackrf/devicehackrfvalues.h\
hackrf/devicehackrfshared.h
HEADERS += limesdr/devicelimesdr.h\
limesdr/devicelimesdrparam.h\
limesdr/devicelimesdrshared.h
}
LIBS += -L../sdrbase/$${build_subdir} -lsdrbase
MINGW32 || MINGW64 {
LIBS += -L$$LIBBLADERF/lib -lbladeRF
LIBS += -L../libhackrf/$${build_subdir} -llibhackrf
LIBS += -L../liblimesuite/$${build_subdir} -lliblimesuite
LIBS += -L../libiio/$${build_subdir} -llibiio
}
macx {
LIBS += -L/opt/local/lib -lhackrf
LIBS += -L/usr/local/lib -lLimeSuite
LIBS += -framework iio
}
MSVC {
LIBS += -L../libhackrf/$${build_subdir} -llibhackrf
LIBS += -LC:\softs\PothosSDR\lib -lLimeSuite
}

View File

@ -19,7 +19,9 @@
#include "libhackrf/hackrf.h"
class DeviceHackRF
#include "export.h"
class DEVICES_API DeviceHackRF
{
public:
static DeviceHackRF& instance();
@ -28,7 +30,11 @@ public:
protected:
DeviceHackRF();
DeviceHackRF(const DeviceHackRF&) {}
#ifdef _MSC_VER
DeviceHackRF& operator=(const DeviceHackRF& other) { return *this; }
#else
DeviceHackRF& operator=(const DeviceHackRF& other __attribute__((unused))) { return *this; }
#endif
~DeviceHackRF();
private:
static hackrf_device *open_hackrf_from_sequence(int sequence);

View File

@ -18,8 +18,9 @@
#define DEVICES_HACKRF_DEVICEHACKRFSHARED_H_
#include "util/message.h"
#include "export.h"
class DeviceHackRFShared
class DEVICES_API DeviceHackRFShared
{
public:
class MsgConfigureFrequencyDelta : public Message

View File

@ -17,7 +17,9 @@
#ifndef DEVICES_HACKRF_DEVICEHACKRFVALUES_H_
#define DEVICES_HACKRF_DEVICEHACKRFVALUES_H_
class HackRFBandwidths {
#include "export.h"
class DEVICES_API HackRFBandwidths {
public:
static unsigned int getBandwidth(unsigned int bandwidth_index);
static unsigned int getBandwidthIndex(unsigned int bandwidth);

View File

@ -50,7 +50,7 @@ bool DeviceLimeSDR::setNCOFrequency(lms_device_t *device, bool dir_tx, std::size
return false;
}
if (LMS_SetNCOIndex(device, dir_tx, chan, 0, !positive) < 0)
if (LMS_SetNCOIndex(device, dir_tx, chan, 0, dir_tx^positive) < 0)
{
fprintf(stderr, "DeviceLimeSDR::setNCOFrequency: cannot set conversion direction %sfreq\n", positive ? "+" : "-");
return false;
@ -180,10 +180,10 @@ bool DeviceLimeSDR::SetRBBPGA_dB(lms_device_t *device, std::size_t chan, float v
int rcc_ctl_pga_rbb = (430.0*pow(0.65, (g_pga_rbb/10.0))-110.35)/20.4516 + 16;
int c_ctl_pga_rbb = 0;
if (0 <= g_pga_rbb && g_pga_rbb < 8) c_ctl_pga_rbb = 3;
if (8 <= g_pga_rbb && g_pga_rbb < 13) c_ctl_pga_rbb = 2;
if (13 <= g_pga_rbb && g_pga_rbb < 21) c_ctl_pga_rbb = 1;
if (21 <= g_pga_rbb) c_ctl_pga_rbb = 0;
if (g_pga_rbb < 8) { c_ctl_pga_rbb = 3; }
if (8 <= g_pga_rbb && g_pga_rbb < 13) { c_ctl_pga_rbb = 2; }
if (13 <= g_pga_rbb && g_pga_rbb < 21) { c_ctl_pga_rbb = 1; }
if (21 <= g_pga_rbb) { c_ctl_pga_rbb = 0; }
if (LMS_WriteParam(device, LMS7param(RCC_CTL_PGA_RBB), rcc_ctl_pga_rbb) < 0)
{

View File

@ -19,7 +19,9 @@
#include "lime/LimeSuite.h"
class DeviceLimeSDR
#include "export.h"
class DEVICES_API DeviceLimeSDR
{
public:
enum PathRxRFE

View File

@ -19,6 +19,8 @@
#include "lime/LimeSuite.h"
#include "export.h"
/**
* This structure refers to one physical device shared among parties (logical devices represented by
* the DeviceSinkAPI or DeviceSourceAPI).
@ -26,7 +28,7 @@
* There is only one copy that is constructed by the first participant and destroyed by the last.
* A participant knows it is the first or last by checking the lists of buddies (Rx + Tx).
*/
struct DeviceLimeSDRParams
struct DEVICES_API DeviceLimeSDRParams
{
lms_device_t *m_dev; //!< device handle
uint32_t m_nbRxChannels; //!< number of Rx channels (normally 2, we'll see if we really use it...)
@ -53,6 +55,29 @@ struct DeviceLimeSDRParams
m_rxFrequency(1e6),
m_txFrequency(1e6)
{
m_lpfRangeRx.max = 0.0f;
m_lpfRangeRx.min = 0.0f;
m_lpfRangeRx.step = 0.0f;
m_lpfRangeTx.max = 0.0f;
m_lpfRangeTx.min = 0.0f;
m_lpfRangeTx.step = 0.0f;
m_loRangeRx.max = 0.0f;
m_loRangeRx.min = 0.0f;
m_loRangeRx.step = 0.0f;
m_loRangeTx.max = 0.0f;
m_loRangeTx.min = 0.0f;
m_loRangeTx.step = 0.0f;
m_srRangeRx.max = 0.0f;
m_srRangeRx.min = 0.0f;
m_srRangeRx.step = 0.0f;
m_srRangeTx.max = 0.0f;
m_srRangeTx.min = 0.0f;
m_srRangeTx.step = 0.0f;
}
/**

View File

@ -20,11 +20,12 @@
#include <cstddef>
#include "devicelimesdrparam.h"
#include "util/message.h"
#include "export.h"
/**
* Structure shared by a buddy with other buddies
*/
class DeviceLimeSDRShared
class DEVICES_API DeviceLimeSDRShared
{
public:
class MsgReportBuddyChange : public Message {

View File

@ -19,7 +19,9 @@
#include "deviceperseusscan.h"
class DevicePerseus
#include "export.h"
class DEVICES_API DevicePerseus
{
public:
static DevicePerseus& instance();

View File

@ -23,8 +23,9 @@
#include <map>
#include <QString>
#include "export.h"
class DevicePerseusScan
class DEVICES_API DevicePerseusScan
{
public:
struct DeviceScan

View File

@ -22,7 +22,9 @@
#include "deviceplutosdrscan.h"
#include "deviceplutosdrbox.h"
class DevicePlutoSDR
#include "export.h"
class DEVICES_API DevicePlutoSDR
{
public:
static DevicePlutoSDR& instance();

View File

@ -22,7 +22,9 @@
#include <sys/types.h>
#include "deviceplutosdrscan.h"
class DevicePlutoSDRBox
#include "export.h"
class DEVICES_API DevicePlutoSDRBox
{
public:
typedef enum

View File

@ -19,7 +19,9 @@
#include <string>
class DevicePlutoSDRBox;
#include "export.h"
class DEVICES_API DevicePlutoSDRBox;
/**
* This structure refers to one physical device shared among parties (logical devices represented by
@ -28,7 +30,7 @@ class DevicePlutoSDRBox;
* There is only one copy that is constructed by the first participant and destroyed by the last.
* A participant knows it is the first or last by checking the lists of buddies (Rx + Tx).
*/
struct DevicePlutoSDRParams
class DevicePlutoSDRParams
{
public:
DevicePlutoSDRParams();

View File

@ -21,7 +21,9 @@
#include <vector>
#include <map>
class DevicePlutoSDRScan
#include "export.h"
class DEVICES_API DevicePlutoSDRScan
{
public:
struct DeviceScan

View File

@ -20,13 +20,14 @@
#include <stdint.h>
#include "util/message.h"
#include "export.h"
class DevicePlutoSDRParams;
/**
* Structure shared by a buddy with other buddies
*/
class DevicePlutoSDRShared
class DEVICES_API DevicePlutoSDRShared
{
public:
/**

View File

@ -2,15 +2,19 @@
This folder contains classes and methods that can be used by different plugins that work with a common physical device or via network. Thus this can be one of the following devices:
- BladeRF: one Rx and one Tx full duplex. Plugins are:
- bladerfinput
- bladerfoutput
- BladeRF1: one Rx and one Tx full duplex. Plugins are:
- bladerf1input
- bladerf1output
- BladeRF2: 2 Rx and 2 Tx full duplex (BladeRF 2.0 micro). Plugins are:
- bladerf2input
- bladerf2output
- HackRF: one Rx and one Tx half duplex. Plugins are:
- hackrfinput
- hackrfoutput
- LimeSDR: 2 Rx and 2 Tx full duplex. Plugins are
- LimeSDR: 2 Rx and 2 Tx full duplex (Lime-USB). 1 Rx and 1 Tx full duplex (Lime-Mini). Plugins are
- limesdrinput
- limesdroutput
@ -18,5 +22,6 @@ This folder contains classes and methods that can be used by different plugins t
- plutosdrinput
- plutosdroutput
- SDRdaemon: sends or receive samples to/from device remotely through the network. Used on the Tx plugin only
- sdrdaemonsink
- SoapySDR: Soapy SDR virtual device
- soapysdrinput
- soapysdroutput

View File

@ -0,0 +1,52 @@
project(soapysdrdevice)
set (CMAKE_CXX_STANDARD 11)
set(soapysdrdevice_SOURCES
devicesoapysdr.cpp
devicesoapysdrscan.cpp
devicesoapysdrshared.cpp
devicesoapysdrparams.cpp
)
set(soapysdrdevice_HEADERS
devicesoapysdr.h
devicesoapysdrscan.h
devicesoapysdrshared.h
devicesoapysdrparams.h
)
if (BUILD_DEBIAN)
include_directories(
.
${CMAKE_CURRENT_BINARY_DIR}
${SOAPYSDRSRC}
)
else (BUILD_DEBIAN)
include_directories(
.
${CMAKE_CURRENT_BINARY_DIR}
${SOAPYSDR_INCLUDE_DIR}
)
endif (BUILD_DEBIAN)
#add_definitions(${QT_DEFINITIONS})
#add_definitions(-DQT_SHARED)
add_library(soapysdrdevice SHARED
${soapysdrdevice_SOURCES}
)
if (BUILD_DEBIAN)
target_link_libraries(soapysdrdevice
soapysdr
sdrbase
)
else (BUILD_DEBIAN)
target_link_libraries(soapysdrdevice
${SOAPYSDR_LIBRARY}
sdrbase
)
endif (BUILD_DEBIAN)
install(TARGETS soapysdrdevice DESTINATION lib)

View File

@ -0,0 +1,73 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "devicesoapysdr.h"
DeviceSoapySDR::DeviceSoapySDR()
{
m_scanner.scan();
}
DeviceSoapySDR::~DeviceSoapySDR()
{}
DeviceSoapySDR& DeviceSoapySDR::instance()
{
static DeviceSoapySDR inst;
return inst;
}
SoapySDR::Device *DeviceSoapySDR::openSoapySDR(uint32_t sequence)
{
instance();
return openopenSoapySDRFromSequence(sequence);
}
void DeviceSoapySDR::closeSoapySdr(SoapySDR::Device *device)
{
SoapySDR::Device::unmake(device);
}
SoapySDR::Device *DeviceSoapySDR::openopenSoapySDRFromSequence(uint32_t sequence)
{
if (sequence > m_scanner.getNbDevices())
{
return 0;
}
else
{
const DeviceSoapySDRScan::SoapySDRDeviceEnum& deviceEnum = m_scanner.getDevicesEnumeration()[sequence];
try
{
SoapySDR::Kwargs kwargs;
kwargs["driver"] = deviceEnum.m_driverName.toStdString();
if (deviceEnum.m_idKey.size() > 0) {
kwargs[deviceEnum.m_idKey.toStdString()] = deviceEnum.m_idValue.toStdString();
}
SoapySDR::Device *device = SoapySDR::Device::make(kwargs);
return device;
}
catch (const std::exception &ex)
{
qWarning("DeviceSoapySDR::openopenSoapySDRFromSequence: %s cannot be opened: %s",
deviceEnum.m_label.toStdString().c_str(), ex.what());
return 0;
}
}
}

View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef DEVICES_SOAPYSDR_DEVICESOAPYSDR_H_
#define DEVICES_SOAPYSDR_DEVICESOAPYSDR_H_
#include <stdint.h>
#include <SoapySDR/Device.hpp>
#include "export.h"
#include "devicesoapysdrscan.h"
class DEVICES_API DeviceSoapySDR
{
public:
static DeviceSoapySDR& instance();
SoapySDR::Device *openSoapySDR(uint32_t sequence);
void closeSoapySdr(SoapySDR::Device *device);
uint32_t getNbDevices() const { return m_scanner.getNbDevices(); }
const std::vector<DeviceSoapySDRScan::SoapySDRDeviceEnum>& getDevicesEnumeration() const { return m_scanner.getDevicesEnumeration(); }
static const unsigned int blockSize = (1<<14);
protected:
DeviceSoapySDR();
DeviceSoapySDR(const DeviceSoapySDR&) {}
DeviceSoapySDR& operator=(const DeviceSoapySDR& other __attribute__((unused))) { return *this; }
~DeviceSoapySDR();
private:
SoapySDR::Device *openopenSoapySDRFromSequence(uint32_t sequence);
DeviceSoapySDRScan m_scanner;
};
#endif /* DEVICES_SOAPYSDR_DEVICESOAPYSDR_H_ */

View File

@ -0,0 +1,298 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <sstream>
#include <iostream>
#include <QDebug>
#include "devicesoapysdrparams.h"
DeviceSoapySDRParams::DeviceSoapySDRParams(SoapySDR::Device *device) :
m_device(device)
{
fillParams();
printParams();
}
DeviceSoapySDRParams::~DeviceSoapySDRParams()
{}
std::string DeviceSoapySDRParams::getRxChannelMainTunableElementName(uint32_t index)
{
if (index < m_nbRx)
{
return std::string("RF");
}
else
{
const ChannelSettings& channelSettings = m_RxChannelsSettings[index];
if (channelSettings.m_frequencySettings.size() > 0) {
return channelSettings.m_frequencySettings.front().m_name;
} else {
return std::string("RF");
}
}
}
std::string DeviceSoapySDRParams::getTxChannelMainTunableElementName(uint32_t index)
{
if (index < m_nbRx)
{
return std::string("RF");
}
else
{
const ChannelSettings& channelSettings = m_RxChannelsSettings[index];
if (channelSettings.m_frequencySettings.size() > 0) {
return channelSettings.m_frequencySettings.front().m_name;
} else {
return std::string("RF");
}
}
}
void DeviceSoapySDRParams::fillParams()
{
m_deviceSettingsArgs = m_device->getSettingInfo();
m_nbRx = m_device->getNumChannels(SOAPY_SDR_RX);
m_nbTx = m_device->getNumChannels(SOAPY_SDR_TX);
for (unsigned int ichan = 0; ichan < m_nbRx; ichan++) {
fillChannelParams(m_RxChannelsSettings, SOAPY_SDR_RX, ichan);
}
for (unsigned int ichan = 0; ichan < m_nbTx; ichan++) {
fillChannelParams(m_TxChannelsSettings, SOAPY_SDR_TX, ichan);
}
}
void DeviceSoapySDRParams::fillChannelParams(std::vector<ChannelSettings>& channelSettings, int direction, unsigned int ichan)
{
channelSettings.push_back(ChannelSettings());
channelSettings.back().m_streamSettingsArgs = m_device->getStreamArgsInfo(direction, ichan);
channelSettings.back().m_antennas = m_device->listAntennas(direction, ichan);
channelSettings.back().m_hasDCAutoCorrection = m_device->hasDCOffsetMode(direction, ichan);
channelSettings.back().m_hasDCOffsetValue = m_device->hasDCOffset(direction, ichan);
channelSettings.back().m_hasIQBalanceValue = m_device->hasIQBalance(direction, ichan);
channelSettings.back().m_hasFrequencyCorrectionValue = m_device->hasFrequencyCorrection(direction, ichan);
// gains
channelSettings.back().m_hasAGC = m_device->hasGainMode(direction, ichan);
channelSettings.back().m_gainRange = m_device->getGainRange(direction, ichan);
std::vector<std::string> gainsList = m_device->listGains(direction, ichan);
for (const auto &it : gainsList)
{
channelSettings.back().m_gainSettings.push_back(GainSetting());
channelSettings.back().m_gainSettings.back().m_name = it;
channelSettings.back().m_gainSettings.back().m_range = m_device->getGainRange(direction, ichan, it);
}
// frequencies
std::vector<std::string> freqsList = m_device->listFrequencies(direction, ichan);
for (const auto &it : freqsList)
{
channelSettings.back().m_frequencySettings.push_back(FrequencySetting());
channelSettings.back().m_frequencySettings.back().m_name = it;
channelSettings.back().m_frequencySettings.back().m_ranges = m_device->getFrequencyRange(direction, ichan, it);
}
channelSettings.back().m_frequencySettingsArgs = m_device->getFrequencyArgsInfo(direction, ichan);
// sample rates
channelSettings.back().m_ratesRanges = m_device->getSampleRateRange(direction, ichan);
// bandwidths
channelSettings.back().m_bandwidthsRanges = m_device->getBandwidthRange(direction, ichan);
}
void DeviceSoapySDRParams::printParams()
{
qDebug() << "DeviceSoapySDRParams::printParams: m_deviceSettingsArgs:\n" << argInfoListToString(m_deviceSettingsArgs).c_str();
int ichan = 0;
for (const auto &it : m_RxChannelsSettings)
{
qDebug() << "DeviceSoapySDRParams::printParams: Rx channel " << ichan;
printChannelParams(it);
ichan++;
}
ichan = 0;
for (const auto &it : m_TxChannelsSettings)
{
qDebug() << "DeviceSoapySDRParams::printParams: Tx channel " << ichan;
printChannelParams(it);
ichan++;
}
}
void DeviceSoapySDRParams::printChannelParams(const ChannelSettings& channelSetting)
{
qDebug() << "DeviceSoapySDRParams::printParams: m_streamSettingsArgs:\n" << argInfoListToString(channelSetting.m_streamSettingsArgs).c_str();
qDebug() << "DeviceSoapySDRParams::printParams:"
<< " m_hasDCAutoCorrection: " << channelSetting.m_hasDCAutoCorrection
<< " m_hasDCOffsetValue: " << channelSetting.m_hasDCOffsetValue
<< " m_hasIQBalanceValue: " << channelSetting.m_hasIQBalanceValue
<< " m_hasFrequencyCorrectionValue: " << channelSetting.m_hasFrequencyCorrectionValue
<< " m_hasAGC: " << channelSetting.m_hasAGC;
qDebug() << "DeviceSoapySDRParams::printParams: m_antennas: " << vectorToString(channelSetting.m_antennas).c_str();
qDebug() << "DeviceSoapySDRParams::printParams: m_gainRange: " << rangeToString(channelSetting.m_gainRange).c_str();
qDebug() << "DeviceSoapySDRParams::printParams: individual gains...";
for (const auto &gainIt : channelSetting.m_gainSettings)
{
qDebug() << "DeviceSoapySDRParams::printParams: m_name: " << gainIt.m_name.c_str();
qDebug() << "DeviceSoapySDRParams::printParams: m_range: " << rangeToString(gainIt.m_range).c_str();
}
qDebug() << "DeviceSoapySDRParams::printParams: tunable elements...";
for (const auto &freqIt : channelSetting.m_frequencySettings)
{
qDebug() << "DeviceSoapySDRParams::printParams: m_name: " << freqIt.m_name.c_str();
qDebug() << "DeviceSoapySDRParams::printParams: m_range (kHz): " << rangeListToString(freqIt.m_ranges, 1e3).c_str();
}
qDebug() << "DeviceSoapySDRParams::printParams: m_frequencySettingsArgs:\n" << argInfoListToString(channelSetting.m_frequencySettingsArgs).c_str();
qDebug() << "DeviceSoapySDRParams::printParams: m_ratesRanges (kHz): " << rangeListToString(channelSetting.m_ratesRanges, 1e3).c_str();
qDebug() << "DeviceSoapySDRParams::printParams: m_bandwidthsRanges (kHz): " << rangeListToString(channelSetting.m_bandwidthsRanges, 1e3).c_str();
}
std::string DeviceSoapySDRParams::argInfoToString(const SoapySDR::ArgInfo &argInfo, const std::string indent)
{
std::stringstream ss;
//name, or use key if missing
std::string name = argInfo.name;
if (argInfo.name.empty()) name = argInfo.key;
ss << indent << " * " << name;
//optional description
std::string desc = argInfo.description;
const std::string replace("\n"+indent+" ");
for (std::size_t pos = 0; (pos=desc.find("\n", pos)) != std::string::npos; pos+=replace.size()) {
desc.replace(pos, 1, replace);
}
if (not desc.empty()) {
ss << " - " << desc << std::endl << indent << " ";
}
//other fields
ss << " [key=" << argInfo.key;
if (not argInfo.units.empty()) {
ss << ", units=" << argInfo.units;
}
if (not argInfo.value.empty()) {
ss << ", default=" << argInfo.value;
}
//type
switch (argInfo.type)
{
case SoapySDR::ArgInfo::BOOL:
ss << ", type=bool";
break;
case SoapySDR::ArgInfo::INT:
ss << ", type=int";
break;
case SoapySDR::ArgInfo::FLOAT:
ss << ", type=float";
break;
case SoapySDR::ArgInfo::STRING:
ss << ", type=string";
break;
}
//optional range/enumeration
if (argInfo.range.minimum() < argInfo.range.maximum()) {
ss << ", range=" << rangeToString(argInfo.range);
}
if (not argInfo.options.empty()) {
ss << ", options=(" << vectorToString(argInfo.options) << ")";
}
ss << "]";
return ss.str();
}
std::string DeviceSoapySDRParams::argInfoListToString(const SoapySDR::ArgInfoList &argInfos)
{
std::stringstream ss;
for (std::size_t i = 0; i < argInfos.size(); i++) {
ss << argInfoToString(argInfos[i]) << std::endl;
}
return ss.str();
}
std::string DeviceSoapySDRParams::rangeToString(const SoapySDR::Range &range)
{
std::stringstream ss;
ss << "[" << range.minimum() << ", " << range.maximum();
if (range.step() != 0.0) {
ss << ", " << range.step();
}
ss << "]";
return ss.str();
}
std::string DeviceSoapySDRParams::rangeListToString(const SoapySDR::RangeList &range, const double scale)
{
std::stringstream ss;
for (std::size_t i = 0; i < range.size(); i++)
{
if (not ss.str().empty()) {
ss << ", ";
}
if (range[i].minimum() == range[i].maximum())
{
ss << (range[i].minimum()/scale);
}
else
{
ss << "[" << (range[i].minimum()/scale) << ", " << (range[i].maximum()/scale);
if (range[i].step() != 0.0) {
ss << ", " << (range[i].step()/scale);
}
ss << "]";
}
}
return ss.str();
}

View File

@ -0,0 +1,134 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef DEVICES_SOAPYSDR_DEVICESOAPYSDRPARAMS_H_
#define DEVICES_SOAPYSDR_DEVICESOAPYSDRPARAMS_H_
#include <stdint.h>
#include <string>
#include <vector>
#include <SoapySDR/Device.hpp>
#include "export.h"
/**
* This structure refers to one physical device shared among parties (logical devices represented by
* the DeviceSinkAPI or DeviceSourceAPI).
* It allows storing information on the common resources in one place and is shared among participants.
* There is only one copy that is constructed by the first participant and destroyed by the last.
* A participant knows it is the first or last by checking the lists of buddies (Rx + Tx).
*/
class DEVICES_API DeviceSoapySDRParams
{
public:
struct GainSetting
{
std::string m_name; //!< Name of the gain element
SoapySDR::Range m_range; //!< Gain range
};
struct FrequencySetting
{
std::string m_name; //!< Name of the tunable element
SoapySDR::RangeList m_ranges; //!< List of ranges of the tunable element
};
struct ChannelSettings
{
SoapySDR::ArgInfoList m_streamSettingsArgs; //!< common stream parameters
bool m_hasDCAutoCorrection; //!< DC offset auto correction flag
bool m_hasDCOffsetValue; //!< DC offset value flag
bool m_hasIQBalanceValue; //!< IQ correction value flag
bool m_hasFrequencyCorrectionValue; //!< Frequency correction value flag
std::vector<std::string> m_antennas; //!< Antenna ports names
bool m_hasAGC; //!< AGC flag
SoapySDR::Range m_gainRange; //!< Global gain range
std::vector<GainSetting> m_gainSettings; //!< gain elements settings
std::vector<FrequencySetting> m_frequencySettings; //!< tunable elements settings
SoapySDR::ArgInfoList m_frequencySettingsArgs; //!< common tuning parameters
SoapySDR::RangeList m_ratesRanges; //!< list of ranges of sample rates
SoapySDR::RangeList m_bandwidthsRanges; //!< list of ranges of bandwidths
};
DeviceSoapySDRParams(SoapySDR::Device *device);
~DeviceSoapySDRParams();
const ChannelSettings* getRxChannelSettings(uint32_t index)
{
if (index < m_nbRx) {
return &m_RxChannelsSettings[index];
} else {
return 0;
}
}
const ChannelSettings* getTxChannelSettings(uint32_t index)
{
if (index < m_nbTx) {
return &m_TxChannelsSettings[index];
} else {
return 0;
}
}
std::string getRxChannelMainTunableElementName(uint32_t index);
std::string getTxChannelMainTunableElementName(uint32_t index);
private:
void fillParams();
void fillChannelParams(std::vector<ChannelSettings>& channelSettings, int direction, unsigned int ichan);
void printParams();
void printChannelParams(const ChannelSettings& channelSetting);
// Printing functions copied from SoapySDR's SoapySDRProbe.cpp
std::string argInfoToString(const SoapySDR::ArgInfo &argInfo, const std::string indent = " ");
std::string argInfoListToString(const SoapySDR::ArgInfoList &argInfos);
std::string rangeToString(const SoapySDR::Range &range);
std::string rangeListToString(const SoapySDR::RangeList &range, const double scale);
template <typename Type>
std::string vectorToString(const std::vector<Type> &options)
{
std::stringstream ss;
if (options.empty()) {
return "";
}
for (std::size_t i = 0; i < options.size(); i++)
{
if (not ss.str().empty()) {
ss << ", ";
}
ss << options[i];
}
return ss.str();
}
SoapySDR::Device *m_device;
SoapySDR::ArgInfoList m_deviceSettingsArgs; //!< list (vector) of device settings arguments
uint32_t m_nbRx; //!< number of Rx channels
uint32_t m_nbTx; //!< number of Tx channels
std::vector<ChannelSettings> m_RxChannelsSettings;
std::vector<ChannelSettings> m_TxChannelsSettings;
};
#endif /* DEVICES_SOAPYSDR_DEVICESOAPYSDRPARAMS_H_ */

View File

@ -0,0 +1,130 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <SoapySDR/Version.hpp>
#include <SoapySDR/Modules.hpp>
#include <SoapySDR/Registry.hpp>
#include <SoapySDR/Device.hpp>
#include <QDebug>
#include <QString>
#include "devicesoapysdrscan.h"
void DeviceSoapySDRScan::scan()
{
qDebug("DeviceSoapySDRScan::scan: Lib Version: v%s", SoapySDR::getLibVersion().c_str());
qDebug("DeviceSoapySDRScan::scan: API Version: v%s", SoapySDR::getAPIVersion().c_str());
qDebug("DeviceSoapySDRScan::scan: ABI Version: v%s", SoapySDR::getABIVersion().c_str());
qDebug("DeviceSoapySDRScan::scan: Install root: %s", SoapySDR::getRootPath().c_str());
const std::vector<std::string>& modules = SoapySDR::listModules();
for (const auto &it : modules)
{
const auto &errMsg = SoapySDR::loadModule(it);
if (not errMsg.empty()) {
qWarning("DeviceSoapySDRScan::scan: cannot load module %s: %s", it.c_str(), errMsg.c_str());
} else {
qDebug("DeviceSoapySDRScan::scan: loaded module: %s", it.c_str());
}
}
SoapySDR::FindFunctions findFunctions = SoapySDR::Registry::listFindFunctions();
SoapySDR::Kwargs kwargs;
m_deviceEnums.clear();
for (const auto &it : findFunctions) // for each driver
{
qDebug("DeviceSoapySDRScan::scan: driver: %s", it.first.c_str());
kwargs["driver"] = it.first;
SoapySDR::KwargsList kwargsList = SoapySDR::Device::enumerate(kwargs);
SoapySDR::KwargsList::const_iterator kit = kwargsList.begin();
for (int deviceSeq = 0; kit != kwargsList.end(); ++kit, deviceSeq++) // for each device
{
m_deviceEnums.push_back(SoapySDRDeviceEnum());
m_deviceEnums.back().m_driverName = QString(it.first.c_str());
m_deviceEnums.back().m_sequence = deviceSeq;
// collect identification information
SoapySDR::Kwargs::const_iterator kargIt;
if ((kargIt = kit->find("label")) != kit->end())
{
m_deviceEnums.back().m_label = QString(kargIt->second.c_str());
qDebug("DeviceSoapySDRScan::scan: %s #%u %s",
m_deviceEnums.back().m_driverName.toStdString().c_str(),
deviceSeq,
kargIt->second.c_str());
}
if ((kargIt = kit->find("serial")) != kit->end())
{
m_deviceEnums.back().m_idKey = QString(kargIt->first.c_str());
m_deviceEnums.back().m_idValue = QString(kargIt->second.c_str());
}
else if ((kargIt = kit->find("device_id")) != kit->end())
{
m_deviceEnums.back().m_idKey = QString(kargIt->first.c_str());
m_deviceEnums.back().m_idValue = QString(kargIt->second.c_str());
}
else if ((kargIt = kit->find("addr")) != kit->end())
{
m_deviceEnums.back().m_idKey = QString(kargIt->first.c_str());
m_deviceEnums.back().m_idValue = QString(kargIt->second.c_str());
}
// access the device to get the number of Rx and Tx channels and at the same time probe
// whether it is available for Soapy
try
{
SoapySDR::Device *device;
SoapySDR::Kwargs kwargs;
kwargs["driver"] = m_deviceEnums.back().m_driverName.toStdString();
if (m_deviceEnums.back().m_idKey.size() > 0) {
kwargs[m_deviceEnums.back().m_idKey.toStdString()] = m_deviceEnums.back().m_idValue.toStdString();
}
device = SoapySDR::Device::make(kwargs);
m_deviceEnums.back().m_nbRx = device->getNumChannels(SOAPY_SDR_RX);
m_deviceEnums.back().m_nbTx = device->getNumChannels(SOAPY_SDR_TX);
qDebug("DeviceSoapySDRScan::scan: %s #%u driver=%s hardware=%s #Rx=%u #Tx=%u",
m_deviceEnums.back().m_driverName.toStdString().c_str(),
deviceSeq,
device->getDriverKey().c_str(),
device->getHardwareKey().c_str(),
m_deviceEnums.back().m_nbRx,
m_deviceEnums.back().m_nbTx);
SoapySDR::Device::unmake(device);
}
catch (const std::exception &ex)
{
qWarning("DeviceSoapySDRScan::scan: %s #%u cannot be opened: %s",
m_deviceEnums.back().m_driverName.toStdString().c_str(),
deviceSeq,
ex.what());
m_deviceEnums.pop_back();
}
} // for each device
}
}

View File

@ -0,0 +1,52 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef DEVICES_SOAPYSDR_DEVICESOAPYSDRSCAN_H_
#define DEVICES_SOAPYSDR_DEVICESOAPYSDRSCAN_H_
#include <vector>
#include <QString>
#include "export.h"
class DEVICES_API DeviceSoapySDRScan
{
public:
struct SoapySDRDeviceEnum
{
QString m_driverName;
uint32_t m_sequence; //!< device sequence for this driver
QString m_label; //!< the label key for display should always be present
QString m_idKey; //!< key to uniquely identify device
QString m_idValue; //!< value for the above key
uint32_t m_nbRx;
uint32_t m_nbTx;
SoapySDRDeviceEnum() : m_sequence(0), m_nbRx(0), m_nbTx(0)
{}
};
void scan();
uint32_t getNbDevices() const { return m_deviceEnums.size(); }
const std::vector<SoapySDRDeviceEnum>& getDevicesEnumeration() const { return m_deviceEnums; }
private:
std::vector<SoapySDRDeviceEnum> m_deviceEnums;
};
#endif /* DEVICES_SOAPYSDR_DEVICESOAPYSDRSCAN_H_ */

View File

@ -0,0 +1,33 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "devicesoapysdrshared.h"
MESSAGE_CLASS_DEFINITION(DeviceSoapySDRShared::MsgReportBuddyChange, Message)
const float DeviceSoapySDRShared::m_sampleFifoLengthInSeconds = 0.25;
const int DeviceSoapySDRShared::m_sampleFifoMinSize = 75000; // 300 kS/s knee
const int DeviceSoapySDRShared::m_sampleFifoMinSize32 = 150000; // Fixed for interpolation by 32
DeviceSoapySDRShared::DeviceSoapySDRShared() :
m_device(0),
m_channel(-1),
m_source(0),
m_sink(0)
{}
DeviceSoapySDRShared::~DeviceSoapySDRShared()
{}

View File

@ -0,0 +1,97 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef DEVICES_SOAPYSDR_DEVICESOAPYSDRSHARED_H_
#define DEVICES_SOAPYSDR_DEVICESOAPYSDRSHARED_H_
#include <SoapySDR/Device.hpp>
#include "util/message.h"
#include "export.h"
#include "devicesoapysdrparams.h"
class SoapySDRInput;
class SoapySDROutput;
/**
* Structure shared by a buddy with other buddies
*/
class DEVICES_API DeviceSoapySDRShared
{
public:
class MsgReportBuddyChange : public Message {
MESSAGE_CLASS_DECLARATION
public:
uint64_t getCenterFrequency() const { return m_centerFrequency; }
int getLOppmTenths() const { return m_LOppmTenths; }
int getFcPos() const { return m_fcPos; }
int getDevSampleRate() const { return m_devSampleRate; }
bool getRxElseTx() const { return m_rxElseTx; }
static MsgReportBuddyChange* create(
uint64_t centerFrequency,
int LOppmTenths,
int fcPos,
int devSampleRate,
bool rxElseTx)
{
return new MsgReportBuddyChange(
centerFrequency,
LOppmTenths,
fcPos,
devSampleRate,
rxElseTx);
}
private:
uint64_t m_centerFrequency; //!< Center frequency
int m_LOppmTenths; //!< LO soft correction in tenths of ppm
int m_fcPos; //!< Center frequency position
int m_devSampleRate; //!< device/host sample rate
bool m_rxElseTx; //!< tells which side initiated the message
MsgReportBuddyChange(
uint64_t centerFrequency,
int LOppmTenths,
int fcPos,
int devSampleRate,
bool rxElseTx) :
Message(),
m_centerFrequency(centerFrequency),
m_LOppmTenths(LOppmTenths),
m_fcPos(fcPos),
m_devSampleRate(devSampleRate),
m_rxElseTx(rxElseTx)
{ }
};
DeviceSoapySDRShared();
~DeviceSoapySDRShared();
SoapySDR::Device *m_device;
DeviceSoapySDRParams *m_deviceParams;
int m_channel; //!< allocated channel (-1 if none)
SoapySDRInput *m_source;
SoapySDROutput *m_sink;
static const float m_sampleFifoLengthInSeconds;
static const int m_sampleFifoMinSize;
static const int m_sampleFifoMinSize32;
};
#endif /* DEVICES_SOAPYSDR_DEVICESOAPYSDRSHARED_H_ */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

BIN
doc/img/APIdocHome.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More