-
Notifications
You must be signed in to change notification settings - Fork 598
Developers notes
A consistent flow of samples is grouped into a "device set" that combines one device plugin and many channel plugins sharing the same baseband. The following figure depicts the flow of samples taking place in one device set.
The critical parts of plugins run on their own thread. FIFOs at their boundaries ensure the independence of threads and thus effective multi-threading. The "DSP device engine" also runs on its own thread.
The DSP Device Engine is specialized for each category of device sets:
- Source device sets (Rx): the
DSPDeviceSourceEnginedispatches the baseband samples to the attached channels - Sink device sets (Tx):
DSPDeviceSinkEnginecombines the samples extracted from the attached channels into the baseband - MIMO device sets (v5 only):
DSPDeviceMIMOEnginedispatches and combines samples coming from attached channels into a multi-stream baseband
The GUI and management modules of the plugins run on the main thread. Communication between threads is done via message queues.
Legend of figures:
- Black arrows follow (loosely) the UML standard
- Hollow arrows represent inheritance oriented towards the parent class
- Filled diamond arrows represent composition oriented towards the composed class
- Hollow diamond arrows represent aggregation (reference) oriented towards the referenced class
- Green arrows represent the direction of the Rx stream
- Red arrows represent the direction of the Tx stream
- Blue arrows represent the direction of the MIMO stream. The MIMO stream is a simultaneous (synchronous or asynchronous) stream composed of any number of input or output streams
Since v4.12.2
- The I/Q samples are collected from a physical device or UDP flow with a device plugin that derives from the
DeviceSampleSourceclass. - These I/Q samples are downsampled in a bank of half-band decimators to reach the baseband sample rate and are fed into a
BasebandSampleSinkby theDSPDeviceSOourceEngine - The
Xxxclass delegates the processing of samples at baseband sample rate to theXxxBasebandclass - The
XxxBasebandclass realizes the baseband processor described in the device set general flow. It has aDownChannelizerclass to decimate the samples down to the channel sample rate and send them to theXxxSinkclass. TheDownChannelizerclass contains a bank of half-band decimators that cascade the downsampling at the center, left or right half of the input band at each stage in order to fit the Rx sink bandwidth. - The
xxxSinkclass realizes the Sink processor described in the device set general flow. It contains a NCO to adjust to the Rx plugin center frequency and a rational downsampler to adjust the sample rate at the output of theDownChannelizer(channel sample rate) to fit the exact rate required (sink sample rate). - The
FileRecordclass records the baseband stream. - The baseband stream is also sent to the spectrum display.
Since v4.12.0
- The I/Q samples are sent to a physical device or UDP flow with a device plugin that derives from the
DeviceSampleSinkclass. - These I/Q samples have been upsampled in a bank of half-band interpolators from the baseband sample rate and have been taken from a
BasebandSampleSourceusing theDSPDeviceSinkEngine - The
Xxxclass delegates the generation of samples at baseband sample rate to theXxxBasebandclass - The
XxxBasebandclass realizes the baseband processor described in the device set general flow. It has anUpChannelizerclass to interpolate the samples generated by theXxxSourceclass up to the baseband sample rate. TheUpChannelizerclass contains a bank of half-band interpolators that cascade the upsampling to the center, left or right half of the output band at each stage in order to fit the Tx source bandwidth. - The
XxxSourceclass realizes the Source processor described in the device set general flow. It contains a NCO to adjust to the Tx plugin center frequency and a rational upsampler to adjust the sample rate at the input of theUpChannelizer(channel sample rate) to fit the exact rate required (source sample rate). - The generated baseband stream is also sent to the spectrum display.
Work in progress...
Generally one would start from an existing plugin and adapt it. In any case developing from bottom to top will allow you to validate the code compilation progressively. Thus this is the recommended order for the main source files:
- start with the "...settings"
- do the "..thread(s)"
- do the Swagger
.yamlfile(s) and generate REST API code (you may as well do it after the "settings") - do the static "web...adapter"
- do the "...input" or "...output" or "...mimo"
- do the "...gui" with the ".ui" XML form file from QtCreator
- end with the "...plugin"
At present the following plugins are available:
-
AirspyXxxclasses inplugins/samplesource/airspy: Interface with Airspy devices -
AirspyHFXxxclasses inplugins/samplesource/airspyhf: Interface with Airspy HF devices -
BladeRF1InputXxxclasses inplugins/samplesource/bladerf1input: Interface with BladeRF v1 devices -
BladeRF2InputXxxclasses inplugins/samplesource/bladerf2input: Interface with BladeRF v2 (or micro) devices -
FCDProXxxclasses inplugins/samplesource/fcdpro: Interface with Funcube Pro devices -
FCDProPlusXxxclasses inplugins/samplesource/fcdproplus: Interface with Funcube Pro+ devices -
HackRFInputXxxclasses inplugins/samplesource/hackrfinput: Interface with HackRF devices -
KiwiSDRxxxclasses inplugins/samplesource/kiwisdr: Interface with remote Kiwi SDR devices -
LimeSDRInputxxxclasses inplugins/samplesource/limesdrinput: Interface with Lime SDR devices -
Perseusxxxclasses inplugins/samplesource/perseus: Interface with Perseus devices -
PlutoSDRInputxxxclasses inplugins/samplesource/plutosdr: Interface with Pluto SDR devices -
RTLSDRXxxclasses inplugins/samplesource/rtlsdr: Interface with RTL-SDR devices -
SDRPlayXxxclasses inplugins/samplesource/sdrplay: Interface with SDRplay RSP1 devices -
XTRXInputXxxclasses inplugins/samplesource/xtrxinput: Interface with XTRX devices -
RemoteInputclass inplugins/samplesource/remoteinput: Special interface collecting I/Q samples from an UDP flow sent by a remote instance of SDRangel using Remote sink channel. -
LocalInputclass inplugins/samplesource/localinput: Special interface collecting I/Q samples from another device set having theLocalInputas its device. -
FileInputclasses inplugins/samplesource/fileinput: Special interface reading I/Q samples from a file directly into the baseband skipping the downsampling block -
SoapySDRInputclasses inplugins/samplesource/soapysdrinput: Special interface working with devices interfaced with SoapySDR library -
TestSourceclasses inplugins/samplesource/testsource: Special device to generate samples internally for mocking a device source
At present the following plugins are available:
-
BladeRF1OutputXxxclasses inplugins/samplesource/bladerf1output: Interface with BladeRF v1 devices -
BladeRF2OutputXxxclasses inplugins/samplesource/bladerf2output: Interface with BladeRF v2 (or micro) devices -
FileSinkclasses inplugins/samplesink/filesink: Special interface writing baseband I/Q samples to a file skipping the final upsampling block -
HackRFOutputXxxclasses inplugins/samplesource/hackrfoutput: Interface with HackRF devices -
LimeSDROutputxxxclasses inplugins/samplesource/limesdroutput: Interface with Lime SDR devices -
LocalOutputclass inplugins/samplesource/localoutput: Special interface getting I/Q samples from another device set having theLocalOutputas its device. -
PlutoSDROutputxxxclasses inplugins/samplesource/plutosdroutput: Interface with Pluto SDR devices -
RemoteOutputclass inplugins/samplesource/remoteoutput: Special interface getting I/Q samples from an UDP flow sent by a remote instance of SDRangel using Remote source channel. -
SoapySDROutputclasses inplugins/samplesource/soapysdroutput: Special interface working with devices interfaced with SoapySDR library -
TestSinkclasses inplugins/samplesource/testsink: Special device to direct generated samples to a spectrum display -
XTRXOutputXxxclasses inplugins/samplesource/xtrxoutput: Interface with XTRX devices
At present the following plugins are available:
-
ChannelAnalyzerXxxclasses inplugins/channelrx/chanalyzer: Signal analysis tool pretty much like a DSA/DSO signal analyzer like the venerable HP 4406A (although still far from it!) -
AMDemodXxxclasses inplugins/channelrx/demodam: AM demodulator with audio output -
ATVDemodXxxclasses inplugins/channelrx/demodatv: Demodulator and visualization of analog TV signals mostly those used in Amateur TeleVision (ATV) -
BFMDemodXxxclasses inplugins/channelrx/demodbfm: Broadcast FM demodulator with audio mono/stereo output and RDS -
DATVDemodXxxclasses inplugins/channelrx/demoddatv: Demodulator and visualization of digital TV signals mostly those used in Digital Amateur TeleVision (DATV) -
DSDDemodXxxclasses inplugins/channelrx/demoddsd: Digital Speech demodulator/decoder built on top of the DSDcc library. Produces audio output and some communication data from various digital voice standards: DMR, dPMR, D-Star, Yaesu System Fusion (YSF). -
FreeDVDemodXxxclasses inplugins/channelrx/demodfreedv: Demodulator and decoder of signals using the Free DV digital modes -
LoraDemodXxxclasses inplugins/channelrx/demodlora: Decodes LoRa transmissions. This is legacy code that is not maintained so it does not work most probably. -
NFMDemodXxxclasses inplugins/channelrx/demodnfm: Narrowband FM demodulator with audio output. -
SSBDemodXxxclasses inplugins/channelrx/demodssb: SSB/DSB/CW demodulator with audio output. -
WFMDemodXxxclasses inplugins/channelrx/demodwfm: Wideband FM demodulator with audio output. This is a basic demodulator not for broadcast reception. -
FreqTrackerXxxclasses inplugins/channelrx/freqtracker: Plugin that follows the frequency of the input signal using a Frequency Locked Loop or a Phase Locked Loop for signals with phase modulation (BPSK, QPSK, ...). To be used in cooperation with an external script to control the frequency of other plugins via REST API. -
LocalSinkXxxclasses inplugins/channelrx/localsink: Sends channel I/Q to another source device set that has aLocalInputsource for its device. -
RemoteSinkXxxclasses inplugins/channelrx/remotesink: Sends channel I/Q samples to another instance of SDRangel via UDP. TheRemoteInputplugin is used to receive the samples. -
UDPSinkXxxclasses inplugins/channelrx/udpsink: Sends channel I/Q or FM demodulated samples via UDP
At present the following plugins are available:
-
FileSourceXxxclasses inplugins/channeltx/filesource: takes I/Q samples from a file saved in.sdriqformat -
LocalSourceXxxclasses inplugins/channeltx/localource: takes I/Q samples from another sink device set that has aLocalOutputsink for its device -
AMMmodXxxclasses inplugins/channeltx/modam: AM modulator -
ATVModXxxclasses inplugins/channeltx/modatv: Modulator for analog TV signals mostly those used in Amateur TeleVision (ATV) -
FreeDVModXxxclasses inplugins/channeltx/modfreedv: Coder and modulator for signals using the Free DV digital modes -
NFMModXxxclasses inplugins/channeltx/modnfm: Narrowband FM modulator -
SSBModXxxclasses inplugins/channeltx/modssb: Single Side Band modulator. Can be used for CW. -
WFMModXxxclasses inplugins/channeltx/modwfm: Wideband FM modulator (not broadcast quality) -
RemoteSourceXxxclasses inplugins/channeltx/remotesource: takes I/Q samples from another SDRangel instance using theRemoteOutputplugin to send samples over UDP. -
UDPSourceXxxclasses inplugins/channeltx/udpsoutce: takes channel I/Q or FM demodulated samples sent via UDP as raw samples (not SDRangel UDP format)
This describes only the main components
The HTTP server used for REST API communication and internal web server
Classes used to log messages to console or file
Rewrite of the jrtplib library for the Qt environment. It handles RTP over UDP communication.
Script written in Go language to process or restore .sdriq files so that their header is compatible with the present version of SDRangel
Collection of Python scripts that use the REST API of SDRangel to perform common tasks
The sdrbase subdirectory contain the common core components. It is further broken down in subdirectories corresponding to a specific area:
-
ambecontains classes to interface with AMBE digital voice processors -
audiocontains the interface with the audio device(s) -
channelcontains the channel API interface and related classes -
commandsclasses to deal with the commands -
devicecontains the device API interface and related classes -
dspcontains the common blocks for Digital Signal Processing like filters, scope and spectrum analyzer internals -
plugincontains the common blocks for managing plugins -
resourcescontains Qt resources including web server static files -
settingscontains components to manage presets and preferences -
utilcontains common utilities such as the message queue -
webapicontains common classes to handle web REST API
The sdrbase subdirectory contain the common GUI components. It is further broken down in subdirectories corresponding to a specific area:
-
devicecontains the UI parts of the Device Sets -
dspcontains DSP related GUI specific classes including the scope and spectrum interfaces -
guicontains the GUI core components -
resourcescontains Qt resources with GUI artifacts (icons...) -
soapyguicontains GUI components specific to the SoapySDR plugins -
webapicontains GUI related classes related to the web REST API
This is also where the MainWindow class resides
The sdrsrv subdirectory contains classes specific to the server variant of
SDRangel
The swagger sudirectory contains classes and resources related to the REST API interface of SDRangel. As the name suggests the REST API is designed using Swagger.
The plugins subdirectory contains the associated plugins used to manage devices and channel components. Naming convention of various items depend on the usage and Rx (reception side) or Tx (transmission side) affinity. MIMO is a work in progress and not described here yet.
-
Receiver functions (Rx):
-
samplesource: Device managers:-
xxx: Device manager (e.g. xxx = airspy)-
xxxinput.h/cpp: Device interface -
xxxgui.h/cpp: GUI -
xxxplugin.h/cpp: Plugin interface -
xxxsettings.h/cpp: Configuration manager -
xxxthread.h/cpp: Reading samples -
xxxwebapiadapter.h/cpp: Detached web API functions to handle settings via REST API
-
-
-
channelrx: Channel handlers:-
demodxxx: Demodulator internal handler (e.g xxx = demodam)-
xxxdemod.h/cpp: Demodulator core -
xxxdemodgui.h/cpp: Demodulator GUI -
xxxdemodplugin.h/cpp: Plugin interface -
xxxdemodwebapiadapter.h/cpp: Detached web API functions to handle settings via REST API
-
-
xxxanalyzer: Analyzer internal handler (e.g xxx = channel)-
xxxanalyzer.h/cpp: Analyzer core -
xxxanalyzergui.h/cpp: Analyzer GUI -
xxxanalyzerplugin.h/cpp: Analyzer plugin manager -
xxxanalyzerwebapiadapter.h/cpp: Detached web API functions to handle settings via REST API
-
-
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 -
xxxwebapiadapter.h/cpp: Detached web API functions to handle settings via REST API
-
-
xxx: Not conventinally named module (ex: freqtracker):-
xxx.h/cpp: Module manager -
xxxgui.h/cpp: Module GUI -
xxxplugin/h/cpp: Module plugin manager -
xxxwebapiadapter.h/cpp: Detached web API functions to handle settings via REST API
-
-
-
-
Transmitter functions (Tx):
-
samplesink: Device managers:-
xxx: Device manager (e.g. xxx = bladerf1)-
xxxsinkoutput.h/cpp: Device interface -
xxxsinkgui.h/cpp: GUI -
xxxsinkplugin.h/cpp: Plugin interface -
xxxsinksettings.h/cpp: Configuration manager -
xxxsinkthread.h/cpp: Writing samples -
xxxsinkwebapiadapter.h/cpp: Detached web API functions to handle settings via REST API
-
-
-
channeltx: Channel handlers:-
modxxx: Modulator internal handler (e.g xxx = modam)-
xxxmod.h/cpp: Modulator manager -
xxxmodbaseband.h/cpp: Baseband generator -
xxxmodsource.h/cpp: Source generator -
xxxmodgui.h/cpp: Modulator GUI -
xxxmodplugin.h/cpp: Plugin interface -
xxxmodsettings.h/cpp: Configuration manager -
xxxmodwebapiadapter.h/cpp: Detached web API functions to handle settings via REST API
-
-
xxxsource: Interface to the outside (e.g xxx = udp):-
xxxsource.h/cpp: Interface manager -
xxxsourcebaseband.h/cpp: Baseband generator -
xxxsourcesource.h/cpp: Source generator -
xxxsourcegui.h/cpp: Interface GUI -
xxxsourceplugin/h/cpp: Interface plugin manager -
xxxsourcesettings.h/cpp: Configuration manager -
xxxsourcewebapiadapter.h/cpp: Detached web API functions to handle settings via REST API
-
-
-
To be reviewed ...
Since version 3.4.0 the opening and closing of the physical device has been split off the start and stop methods of the device interface. The opening and closing of the physical device is handled in private methods called from the constructor and destructor of the device interface respectively.
The device interface is itself created in the constructor of the GUI and is deleted at the destruction of the GUI.
The lifecycle of the GUI is controlled from the "Sampling Device Control" device selector in the main window using the plugin manager. When there is a change in the hardware device selection (you can also re-cycle the same device by clicking again on this button) validated by the confirmation button (check sign icon). the following steps are executed in sequence:
- Stop streaming
- Delete the current GUI this will in turn delete the device interface and always close the physical device unless the physical device has a SISO or MIMO architecture (more on that later)
- 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 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 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
deviceUI->m_deviceSourceAPI->clearBuddiesLists(); // clear old API buddies lists
m_pluginManager->selectSampleSourceByDevice(devicePtr, deviceUI->m_deviceSourceAPI); // sets the new API
// add to buddies list
... here it looks for open tabs with the same physical device and adds the deviceUI->m_deviceSourceAPI to the corresponding m_deviceSourceAPI buddies list ...
// constructs new GUI and input object
QWidget *gui;
PluginManager::SamplingDevice *sampleSourceDevice = (PluginManager::SamplingDevice *) devicePtr; // lightweight representation of the device
PluginInstanceUI *pluginUI = sampleSourceDevice->m_plugin->createSampleSourcePluginInstanceUI(sampleSourceDevice->m_deviceId, &gui, deviceUI->m_deviceSourceAPI);
deviceUI->m_deviceSourceAPI->setSampleSourcePluginInstanceUI(pluginUI);
deviceUI->m_deviceSourceAPI->setInputGUI(gui, sampleSourceDevice->m_displayName);
Some SDR hardware have Rx/Tx capabilities in a SISO or MIMO configuration. That is a physical device can handle more than one I/Q sample flow in either direction. Such devices supported by SDRangel are the following:
- SISO full duplex: BladeRF
- SISO half duplex: HackRF
- MIMO: LimeSDR
Note that the following would also work for multiple sample channels Rx or Tx only devices but none exists or is supported at this moment.
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. Devices exhibit a generic interface in the form of the DeviceAPI class. Through this API 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 DeviceAPI maintain a list of DeviceAPI 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 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 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:
-
BladeRF: a single Rx and Tx in SISO configuration loosely coupled:
- 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 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
-
LimeSDR: dual Rx and dual Tx in MIMO configuration. This implies tightly coupling between receivers on one part and transmitter on the other. But in the case of the LimeSDR (LMS7002M chip) there is even a tight coupling between Rx and Tx parts since the ADC/DAC clock is in common which means both have the same base sample rate that can only be varied by the mean of the hardware decimators and interpolators. This means:
- Rx share the same sample rate, hardware decimation factor and center frequency
- Tx share the same sample rate, hardware interpolation factor and center frequency
- Rx and Tx share the same base sample rate (decimation/interpolation apart)
- Independent Rx and Tx center frequencies
- Independent gains, bandwidths, etc... per Rx or Tx channel
The openDevice and closeDevice methods of the device interface are designed specifically for each physical device type in order to manage the common resources appropriately at receiver or transmitter construction and destruction. For example opening and closing the device and the related device handle is always done this way:
-
openDevice:
- check if there is any "buddy" present in one of the lists
- if there is a buddy then grab the device handle and use it for next operations
- if there is no buddy open the device and store the handle in the common area so it will be visible for future buddies
-
closeDevice:
- if there are no buddies then effectively close the device else just zero out the own copy of the device handle
Exchange of dynamic information when necessary such as sample rate or center frequency is done by message passing between buddies.
- Home
- Quick start
- Hardware requirements
- High DPI displays
- Compile in Linux
- Compile in Windows
- Compile in MacOS
- History and major releases
- Audio related
- Plugins
- Advanced
- Server and API