This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/osmocom-sdr@lists.osmocom.org/.
Jeff Long willcode4 at gmail.comLatest version. Added a couple new features, but also fixed a buffer
locking problem.
Diff is against master.
On Sun, Jan 14, 2018 at 8:51 AM, Jeff Long <willcode4 at gmail.com> wrote:
> Latest version of diff.
>
> On Fri, Jan 12, 2018 at 12:48 PM, Jeff Long <willcode4 at gmail.com> wrote:
>
>> SDRplay support, rewritten, supporting RSP1, RSP1A, and RSP2
>>
>> Requires ENABLE_NONFREE=yes. Requires SDRplay's SDK v2.11 to be installed
>> by the user. In the future, if there is a way to redistribute
>> mirsdrapi-rsp.h from the SDK, that problem could be addressed using a shim
>> library that looks for /usr/local/lib/libmirsdrapi-rsp.so at runtime.
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/osmocom-sdr/attachments/20180115/26d115c3/attachment.htm>
-------------- next part --------------
diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt
index 09838c1..4229eea 100644
--- a/grc/CMakeLists.txt
+++ b/grc/CMakeLists.txt
@@ -40,6 +40,7 @@ add_custom_target(osmosdr_grc_xml_blocks ALL DEPENDS ${xml_blocks})
install(FILES
${xml_blocks}
+ sdrplay_source.xml
# DESTINATION ${GRC_BLOCKS_DIR}
DESTINATION share/gnuradio/grc/blocks
)
diff --git a/grc/sdrplay_source.xml b/grc/sdrplay_source.xml
new file mode 100644
index 0000000..0f4e264
--- /dev/null
+++ b/grc/sdrplay_source.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0"?>
+<block>
+ <name>SDRplay Source</name>
+ <key>sdrplay_source</key>
+ <category>Sources</category>
+ <import>import osmosdr</import>
+ <make>osmosdr.source(args = $args + ",bias=" + str($bias) + ",lo=" + str($loFreq))
+self.$(id).set_sample_rate($sample_rate)
+self.$(id).set_center_freq($freq, 0)
+self.$(id).set_freq_corr($corr, 0)
+self.$(id).set_dc_offset_mode($dc_offset_mode, 0)
+self.$(id).set_iq_balance_mode($iq_balance_mode, 0)
+self.$(id).set_gain_mode($gain_mode, 0)
+self.$(id).set_gain($lna, "LNA_ATTEN_STEP", 0)
+self.$(id).set_gain($grdb, "IF_ATTEN_DB", 0)
+self.$(id).set_antenna($ant, 0)
+self.$(id).set_bandwidth($bw, 0)
+ </make>
+ <callback>set_sample_rate($sample_rate)</callback>
+ <callback>set_center_freq($freq, 0)</callback>
+ <callback>set_freq_corr($corr, 0)</callback>
+ <callback>set_dc_offset_mode($dc_offset_mode, 0)</callback>
+ <callback>set_iq_balance_mode($iq_balance_mode, 0)</callback>
+ <callback>set_gain_mode($gain_mode, 0)</callback>
+ <callback>set_gain($lna, "LNA_ATTEN_STEP", 0)</callback>
+ <callback>set_gain($grdb, "IF_ATTEN_DB", 0)</callback>
+ <callback>set_antenna($ant, 0)</callback>
+ <callback>set_bandwidth($bw, 0)</callback>
+ <param>
+ <name>Output Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex float32</name>
+ <key>fc32</key>
+ <opt>type:fc32</opt>
+ </option>
+ </param>
+ <param>
+ <name>Device Arguments</name>
+ <key>args</key>
+ <value></value>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Num Channels</name>
+ <key>nchan</key>
+ <value>1</value>
+ <type>int</type>
+ <option>
+ <name>1</name>
+ <key>1</key>
+ </option>
+ </param>
+ <param>
+ <name>Sample Rate (sps)</name>
+ <key>sample_rate</key>
+ <value>samp_rate</value>
+ <type>real</type>
+ </param>
+
+ <param>
+ <name>Frequency (Hz)</name>
+ <key>freq</key>
+ <value>100e6</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Freq. Corr. (ppm)</name>
+ <key>corr</key>
+ <value>0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>DC Offset Mode</name>
+ <key>dc_offset_mode</key>
+ <value>0</value>
+ <type>int</type>
+ <option><name>Off</name><key>0</key></option>
+ <option><name>Automatic</name><key>2</key></option>
+ </param>
+ <param>
+ <name>IQ Balance Mode</name>
+ <key>iq_balance_mode</key>
+ <value>0</value>
+ <type>int</type>
+ <option><name>Off</name><key>0</key></option>
+ <option><name>Automatic</name><key>2</key></option>
+ </param>
+ <param>
+ <name>Gain Mode</name>
+ <key>gain_mode</key>
+ <value>False</value>
+ <type>bool</type>
+ <option><name>Manual</name><key>False</key></option>
+ <option><name>Automatic</name><key>True</key></option>
+ </param>
+ <param>
+ <name>LNA Atten Step</name>
+ <key>lna</key>
+ <value>0</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>IF Atten (dB)</name>
+ <key>grdb</key>
+ <value>40</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Antenna</name>
+ <key>ant</key>
+ <value></value>
+ <type>string</type>
+ <option><name>Default</name><key></key></option>
+ <option><name>RX</name><key>RX</key></option>
+ <option><name>A</name><key>A</key></option>
+ <option><name>B</name><key>B</key></option>
+ <option><name>High Z</name><key>HIGHZ</key></option>
+ </param>
+ <param>
+ <name>Bandwidth (Hz)</name>
+ <key>bw</key>
+ <value>1536e3</value>
+ <type>real</type>
+ </param>
+ <param>
+ <name>Bias Voltage</name>
+ <key>bias</key>
+ <value>0</value>
+ <type>int</type>
+ <option><name>Off</name><key>0</key></option>
+ <option><name>On</name><key>1</key></option>
+ </param>
+ <param>
+ <name>AM LO Freq</name>
+ <key>loFreq</key>
+ <value>0</value>
+ <type>int</type>
+ <option><name>Auto</name><key>0</key></option>
+ <option><name>120 MHz</name><key>120</key></option>
+ <option><name>144 MHz</name><key>144</key></option>
+ <option><name>168 MHz</name><key>168</key></option>
+ </param>
+ <source>
+ <name>out</name>
+ <type>$type.type</type>
+ <nports>1</nports>
+ </source>
+</block>
diff --git a/lib/sdrplay/sdrplay_source_c.cc b/lib/sdrplay/sdrplay_source_c.cc
index 9a9ee40..8c3d6fd 100644
--- a/lib/sdrplay/sdrplay_source_c.cc
+++ b/lib/sdrplay/sdrplay_source_c.cc
@@ -1,15 +1,13 @@
/* -*- c++ -*- */
/*
- * Copyright 2015 SDRplay Ltd <support at sdrplay.com>
- * Copyright 2012 Dimitri Stolnikov <horiz0n at gmx.net>
- * Copyright 2012 Steve Markgraf <steve at steve-m.de>
+ * Copyright 2018 Jeff Long <willcode4 at gmail.com>
*
* GNU Radio 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; either version 3, or (at your option)
* any later version.
*
- * GNU Radio is distributed in the hope that it will be useful,
+ * Gnu Radio 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 for more details.
@@ -20,11 +18,6 @@
* Boston, MA 02110-1301, USA.
*/
-/*
- * config.h is generated by configure. It contains the results
- * of probing for features, options etc. It should be the first
- * file included in your .cc file.
- */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -32,569 +25,738 @@
#include "sdrplay_source_c.h"
#include <gnuradio/io_signature.h>
#include "osmosdr/source.h"
+#include "arg_helpers.h"
#include <boost/assign.hpp>
#include <boost/format.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <boost/chrono.hpp>
-#include <stdexcept>
#include <iostream>
-#include <stdio.h>
-#include <math.h>
-
-#include <mirsdrapi-rsp.h>
-
-#include "arg_helpers.h"
+#include <mutex>
#define MAX_SUPPORTED_DEVICES 4
-struct sdrplay_dev
-{
- int gRdB;
- double gain_dB;
- double fsHz;
- double rfHz;
- mir_sdr_Bw_MHzT bwType;
- mir_sdr_If_kHzT ifType;
- int samplesPerPacket;
- int maxGain;
- int minGain;
- int dcMode;
-};
-
using namespace boost::assign;
-#define BYTES_PER_SAMPLE 4 // sdrplay device delivers 16 bit signed IQ data
- // containing 12 bits of information
+// Index by mir_sdr_Bw_MHzT
+static std::vector<double> bandwidths = {
+ 0, // Dummy
+ 200e3,
+ 300e3,
+ 600e3,
+ 1536e3,
+ 5000e3,
+ 6000e3,
+ 7000e3,
+ 8000e3
+};
-#define SDRPLAY_AM_MIN 150e3
-#define SDRPLAY_AM_MAX 30e6
-#define SDRPLAY_FM_MIN 64e6
-#define SDRPLAY_FM_MAX 108e6
-#define SDRPLAY_B3_MIN 162e6
-#define SDRPLAY_B3_MAX 240e6
-#define SDRPLAY_B45_MIN 470e6
-#define SDRPLAY_B45_MAX 960e6
-#define SDRPLAY_L_MIN 1450e6
-#define SDRPLAY_L_MAX 1675e6
+// TODO - RSP1 lower freq is 10e3.
+#define SDRPLAY_FREQ_MIN 1e3
+#define SDRPLAY_FREQ_MAX 2000e6
-#define SDRPLAY_MAX_BUF_SIZE 504
+static std::string hwName(int hwVer)
+{
+ if (hwVer == 1)
+ return "RSP1";
+ if (hwVer == 2)
+ return "RSP2";
+ if (hwVer ==255)
+ return "RSP1A";
+ return "UNK";
+}
-/*
- * Create a new instance of sdrplay_source_c and return
- * a boost shared_ptr. This is effectively the public constructor.
- */
sdrplay_source_c_sptr
make_sdrplay_source_c (const std::string &args)
{
return gnuradio::get_initial_sptr(new sdrplay_source_c (args));
}
-/*
- * Specify constraints on number of input and output streams.
- * This info is used to construct the input and output signatures
- * (2nd & 3rd args to gr::block's constructor). The input and
- * output signatures are used by the runtime system to
- * check that a valid number and type of inputs and outputs
- * are connected to this block. In this case, we accept
- * only 0 input and 1 output.
- */
-static const int MIN_IN = 0; // mininum number of input streams
-static const int MAX_IN = 0; // maximum number of input streams
-static const int MIN_OUT = 1; // minimum number of output streams
-static const int MAX_OUT = 1; // maximum number of output streams
+// 0 inputs, 1 output
+static const int MIN_IN = 0;
+static const int MAX_IN = 0;
+static const int MIN_OUT = 1;
+static const int MAX_OUT = 1;
-/*
- * The private constructor
- */
sdrplay_source_c::sdrplay_source_c (const std::string &args)
: gr::sync_block ("sdrplay_source_c",
- gr::io_signature::make(MIN_IN, MAX_IN, sizeof (gr_complex)),
- gr::io_signature::make(MIN_OUT, MAX_OUT, sizeof (gr_complex))),
- _running(false),
- _uninit(false),
- _auto_gain(false)
-{
- _dev = (sdrplay_dev_t *)malloc(sizeof(sdrplay_dev_t));
- if (_dev == NULL)
- {
- return;
+ gr::io_signature::make(MIN_IN, MAX_IN, sizeof (gr_complex)),
+ gr::io_signature::make(MIN_OUT, MAX_OUT, sizeof (gr_complex))),
+ _auto_gain(false),
+ _gRdB(40),
+ _lna(0),
+ _bcastNotch(0),
+ _dabNotch(0),
+ _fsHz(8e6),
+ _decim(1),
+ _rfHz(100e6),
+ _bwType(mir_sdr_BW_6_000),
+ _ifType(mir_sdr_IF_Zero),
+ _loMode(mir_sdr_LO_Auto),
+ _dcMode(false),
+ _iqMode(false),
+ _buffer(NULL),
+ _streaming(false),
+ _flowgraphRunning(false),
+ _reinit(false)
+{
+ dict_t dict = params_to_dict(args);
+ if (dict.count("sdrplay")) {
+ _devIndex = boost::lexical_cast<unsigned int>(dict["sdrplay"]);
+ }
+ else {
+ _devIndex = 0;
+ }
+
+ mir_sdr_DebugEnable(1);
+
+ unsigned int numDevices;
+ mir_sdr_DeviceT mirDevices[MAX_SUPPORTED_DEVICES];
+ mir_sdr_GetDevices(mirDevices, &numDevices, MAX_SUPPORTED_DEVICES);
+ _hwVer = mirDevices[_devIndex].hwVer;
+
+ if (_hwVer == 2) {
+ _antenna = "A";
+ }
+ else {
+ _antenna = "RX";
+ }
+
+ // bias=[0|1] to turn [off|on] bias tee. Default is off.
+ _biasT = 0;
+ if (dict.count("bias")) {
+ _biasT = boost::lexical_cast<int>(dict["bias"]);
+ }
+
+ // lo=[120|144|168] to set first LO to 120/144/168 MHz. Default is Auto.
+ if (dict.count("lo")) {
+ int loMode = boost::lexical_cast<int>(dict["lo"]);
+ if (loMode == 120)
+ _loMode = mir_sdr_LO_120MHz;
+ else if (loMode == 144)
+ _loMode = mir_sdr_LO_144MHz;
+ else if (loMode == 168)
+ _loMode = mir_sdr_LO_168MHz;
+ }
}
- _dev->fsHz = 2048e3;
- _dev->rfHz = 200e6;
- _dev->bwType = mir_sdr_BW_1_536;
- _dev->ifType = mir_sdr_IF_Zero;
- _dev->samplesPerPacket = 0;
- _dev->dcMode = 0;
- _dev->gRdB = 60;
- set_gain_limits(_dev->rfHz);
- _dev->gain_dB = _dev->maxGain - _dev->gRdB;
-
- _bufi.reserve(SDRPLAY_MAX_BUF_SIZE);
- _bufq.reserve(SDRPLAY_MAX_BUF_SIZE);
- _buf_mutex.lock();
- _buf_offset = 0;
- _buf_mutex.unlock();
+sdrplay_source_c::~sdrplay_source_c ()
+{
+ if (_streaming) {
+ stopStreaming();
+ }
}
-/*
- * Our virtual destructor.
- */
-sdrplay_source_c::~sdrplay_source_c ()
+bool sdrplay_source_c::start(void)
{
- free(_dev);
- _dev = NULL;
- _buf_mutex.lock();
- if (_running)
- {
- _running = false;
- }
- _uninit = true;
- _buf_mutex.unlock();
-}
-
-void sdrplay_source_c::reinit_device()
-{
- std::cerr << "reinit_device started" << std::endl;
- _buf_mutex.lock();
- std::cerr << "after mutex.lock" << std::endl;
- if (_running)
- {
- std::cerr << "mir_sdr_Uninit started" << std::endl;
- mir_sdr_Uninit();
- }
-
- std::cerr << "mir_sdr_Init started" << std::endl;
- mir_sdr_Init(_dev->gRdB, _dev->fsHz / 1e6, _dev->rfHz / 1e6, _dev->bwType, _dev->ifType, &_dev->samplesPerPacket);
-
- if (_dev->dcMode)
- {
- std::cerr << "mir_sdr_SetDcMode started" << std::endl;
- mir_sdr_SetDcMode(4, 1);
- }
-
- _buf_offset = 0;
- _buf_mutex.unlock();
- std::cerr << "reinit_device end" << std::endl;
-}
-
-void sdrplay_source_c::set_gain_limits(double freq)
-{
- if (freq <= SDRPLAY_AM_MAX)
- {
- _dev->minGain = -4;
- _dev->maxGain = 98;
- }
- else if (freq <= SDRPLAY_FM_MAX)
- {
- _dev->minGain = 1;
- _dev->maxGain = 103;
- }
- else if (freq <= SDRPLAY_B3_MAX)
- {
- _dev->minGain = 5;
- _dev->maxGain = 107;
- }
- else if (freq <= SDRPLAY_B45_MAX)
- {
- _dev->minGain = 9;
- _dev->maxGain = 94;
- }
- else if (freq <= SDRPLAY_L_MAX)
- {
- _dev->minGain = 24;
- _dev->maxGain = 105;
- }
-}
-
-int sdrplay_source_c::work( int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items )
-{
- gr_complex *out = (gr_complex *)output_items[0];
- int cnt = noutput_items;
- unsigned int sampNum;
- int grChanged;
- int rfChanged;
- int fsChanged;
-
- if (_uninit)
- {
- return WORK_DONE;
- }
-
- if (!_running)
- {
- reinit_device();
- _running = true;
- }
-
- _buf_mutex.lock();
-
- if (_buf_offset)
- {
- for (int i = _buf_offset; i < _dev->samplesPerPacket; i++)
- {
- *out++ = gr_complex( float(_bufi[i]) * (1.0f/2048.0f), float(_bufq[i]) * (1.0f/2048.0f) );
- }
- cnt -= (_dev->samplesPerPacket - _buf_offset);
- }
-
- while ((cnt - _dev->samplesPerPacket) >= 0)
- {
- mir_sdr_ReadPacket(_bufi.data(), _bufq.data(), &sampNum, &grChanged, &rfChanged, &fsChanged);
- for (int i = 0; i < _dev->samplesPerPacket; i++)
- {
- *out++ = gr_complex( float(_bufi[i]) * (1.0f/2048.0f), float(_bufq[i]) * (1.0f/2048.0f) );
- }
- cnt -= _dev->samplesPerPacket;
- }
-
- _buf_offset = 0;
- if (cnt)
- {
- mir_sdr_ReadPacket(_bufi.data(), _bufq.data(), &sampNum, &grChanged, &rfChanged, &fsChanged);
- for (int i = 0; i < cnt; i++)
- {
- *out++ = gr_complex( float(_bufi[i]) * (1.0f/2048.0f), float(_bufq[i]) * (1.0f/2048.0f) );
- }
- _buf_offset = cnt;
- }
- _buf_mutex.unlock();
+ boost::mutex::scoped_lock lock(_bufferMutex);
+ _flowgraphRunning = true;
+ return true;
+}
- return noutput_items;
+bool sdrplay_source_c::stop(void)
+{
+ boost::mutex::scoped_lock lock(_bufferMutex);
+ _flowgraphRunning = false;
+ // FG may be modified, so assume copied pointer is invalid
+ _buffer = NULL;
+ return true;
}
-std::vector<std::string> sdrplay_source_c::get_devices()
+int sdrplay_source_c::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
{
- std::vector<std::string> devices;
- std::cerr << "get_devices started" << std::endl;
+ gr_complex *out = (gr_complex *)output_items[0];
- unsigned int dev_cnt = 0;
- int samplesPerPacket;
- while(mir_sdr_Init(60, 2.048, 200.0, mir_sdr_BW_1_536, mir_sdr_IF_Zero, &samplesPerPacket) == mir_sdr_Success)
- {
- dev_cnt++;
- }
+ if (!_streaming)
+ startStreaming();
- std::cerr << "Device count: " << dev_cnt << std::endl;
+ {
+ boost::mutex::scoped_lock lock(_bufferMutex);
+ _buffer = out;
+ _bufferSpaceRemaining = noutput_items;
+ _bufferOffset = 0;
+ _bufferReady.notify_one();
- for (unsigned int i = 0; i < dev_cnt; i++)
- {
- mir_sdr_Uninit();
- std::string args = "sdrplay=" + boost::lexical_cast< std::string >( i );
- args += ",label='" + std::string("SDRplay RSP") + "'";
- std::cerr << args << std::endl;
- devices.push_back( args );
- }
+ while (_buffer && _streaming) {
+ _bufferReady.wait(lock);
+ }
+ }
- std::cerr << "get_devices end" << std::endl;
- return devices;
-}
+ if (!_streaming) {
+ return 0;
+ }
-size_t sdrplay_source_c::get_num_channels()
-{
- std::cerr << "get_num_channels: 1" << std::endl;
- return 1;
+ return noutput_items - _bufferSpaceRemaining;
}
-osmosdr::meta_range_t sdrplay_source_c::get_sample_rates()
+// Called by sdrplay streamer thread when data is available
+void sdrplay_source_c::streamCallback(short *xi, short *xq,
+ unsigned int firstSampleNum,
+ int grChanged, int rfChanged, int fsChanged,
+ unsigned int numSamples, unsigned int reset)
{
- osmosdr::meta_range_t range;
+ unsigned int i = 0;
+ _reinit = false;
+
+ boost::mutex::scoped_lock lock(_bufferMutex);
+
+ while (i < numSamples) {
- range += osmosdr::range_t( 2000e3, 12000e3 );
+ // Discard samples if not streaming, if flowgraph not running, or reinit needed.
+ if (!_streaming || _reinit || !_flowgraphRunning)
+ return;
+
+ // While buffer is not ready for write, wait a short time.
+ while (!_buffer) {
+ if (boost::cv_status::timeout ==
+ _bufferReady.wait_for(lock, boost::chrono::milliseconds(250)))
+ return;
+ }
+
+ // Copy until out of samples or buffer is full
+ while ((i < numSamples) && (_bufferSpaceRemaining > 0)) {
+ _buffer[_bufferOffset] =
+ gr_complex(float(xi[i]) / 32768.0, float(xq[i]) / 32768.0);
+
+ i++;
+ _bufferOffset++;
+ _bufferSpaceRemaining--;
+ }
- return range;
+ if (_bufferSpaceRemaining == 0) {
+ _buffer = NULL;
+ _bufferReady.notify_one();
+ }
+ }
}
-double sdrplay_source_c::set_sample_rate(double rate)
+// Callback wrapper
+void sdrplay_source_c::streamCallbackWrap(short *xi, short *xq,
+ unsigned int firstSampleNum,
+ int grChanged, int rfChanged, int fsChanged,
+ unsigned int numSamples, unsigned int reset,
+ void *cbContext)
{
- std::cerr << "set_sample_rate start" << std::endl;
- double diff = rate - _dev->fsHz;
- _dev->fsHz = rate;
-
- std::cerr << "rate = " << rate << std::endl;
- std::cerr << "diff = " << diff << std::endl;
- if (_running)
- {
- if (fabs(diff) < 10000.0)
- {
- std::cerr << "mir_sdr_SetFs started" << std::endl;
- mir_sdr_SetFs(diff, 0, 0, 0);
- }
- else
- {
- std::cerr << "reinit_device started" << std::endl;
- reinit_device();
- }
- }
- std::cerr << "set_sample_rate end" << std::endl;
+ sdrplay_source_c *obj = (sdrplay_source_c *)cbContext;
+ obj->streamCallback(xi, xq,
+ firstSampleNum,
+ grChanged, rfChanged, fsChanged,
+ numSamples, reset);
+}
- return get_sample_rate();
+// Called by strplay streamer thread when gain reduction is changed.
+void sdrplay_source_c::gainChangeCallback(unsigned int gRdB,
+ unsigned int lnaGRdB)
+{
+ std::cerr << "GR change, BB+MIX -" << gRdB << "dB, LNA -" << lnaGRdB << std::endl;
}
-double sdrplay_source_c::get_sample_rate()
+// Callback wrapper
+void sdrplay_source_c::gainChangeCallbackWrap(unsigned int gRdB,
+ unsigned int lnaGRdB,
+ void *cbContext)
{
- if (_running)
- {
- return _dev->fsHz;
- }
+ sdrplay_source_c *obj = (sdrplay_source_c *)cbContext;
+ obj->gainChangeCallback(gRdB, lnaGRdB);
+}
+
+void sdrplay_source_c::startStreaming(void)
+{
+ if (_streaming)
+ return;
+
+ unsigned int numDevices;
+ mir_sdr_DeviceT mirDevices[MAX_SUPPORTED_DEVICES];
+ mir_sdr_ReleaseDeviceIdx();
+ mir_sdr_GetDevices(mirDevices, &numDevices, MAX_SUPPORTED_DEVICES);
+ mir_sdr_SetDeviceIdx(_devIndex);
+
+ std::cerr << "Using SDRplay " << hwName(_hwVer) << " "
+ << mirDevices[_devIndex].SerNo << std::endl;
+
+ // Set bias voltage on/off (RSP1A/RSP2).
+ std::cerr << "Bias voltage: " << _biasT << std::endl;
+ if (_hwVer == 2)
+ mir_sdr_RSPII_BiasTControl(_biasT);
+ else if (_hwVer == 255)
+ mir_sdr_rsp1a_BiasT(_biasT);
+
+ // Set first LO frequency
+ mir_sdr_SetLoMode(_loMode);
+
+ _streaming = true;
+
+ set_gain_mode(get_gain_mode(/*channel*/ 0), /*channel*/ 0);
+
+ int gRdB = _gRdB;
+ int gRdBsystem = 0;
+
+ mir_sdr_StreamInit(&gRdB,
+ _fsHz / 1e6,
+ _rfHz / 1e6,
+ _bwType,
+ _ifType,
+ checkLNA(_lna),
+ &gRdBsystem,
+ mir_sdr_USE_RSP_SET_GR,
+ &_samplesPerPacket,
+ &streamCallbackWrap,
+ &gainChangeCallbackWrap,
+ this);
-// return 0;
- return _dev->fsHz;
+ // Set decimation with halfband filter
+ mir_sdr_DecimateControl(_decim != 1, _decim, 1);
+
+ mir_sdr_DCoffsetIQimbalanceControl(_dcMode, _iqMode);
+
+ // Model-specific initialization
+ if (_hwVer == 2) {
+ set_antenna(get_antenna(), 0);
+ mir_sdr_RSPII_RfNotchEnable(_bcastNotch);
+ }
+
+ else if (_hwVer == 255) {
+ mir_sdr_rsp1a_BroadcastNotch(_bcastNotch);
+ mir_sdr_rsp1a_DabNotch(_dabNotch);
+ }
}
-osmosdr::freq_range_t sdrplay_source_c::get_freq_range( size_t chan )
+void sdrplay_source_c::stopStreaming(void)
{
- osmosdr::freq_range_t range;
+ if (!_streaming)
+ return;
- range += osmosdr::range_t( SDRPLAY_AM_MIN, SDRPLAY_AM_MAX ); /* LW/MW/SW (150 kHz - 30 MHz) */
- range += osmosdr::range_t( SDRPLAY_FM_MIN, SDRPLAY_FM_MAX ); /* VHF Band II (64 - 108 MHz) */
- range += osmosdr::range_t( SDRPLAY_B3_MIN, SDRPLAY_B3_MAX ); /* Band III (162 - 240 MHz) */
- range += osmosdr::range_t( SDRPLAY_B45_MIN, SDRPLAY_B45_MAX ); /* Band IV/V (470 - 960 MHz) */
- range += osmosdr::range_t( SDRPLAY_L_MIN, SDRPLAY_L_MAX ); /* L-Band (1450 - 1675 MHz) */
+ _streaming = false;
- return range;
+ mir_sdr_StreamUninit();
+ mir_sdr_ReleaseDeviceIdx();
}
-double sdrplay_source_c::set_center_freq( double freq, size_t chan )
+void sdrplay_source_c::reinitDevice(int reason)
{
- std::cerr << "set_center_freq start" << std::endl;
- std::cerr << "freq = " << freq << std::endl;
- double diff = freq - _dev->rfHz;
- std::cerr << "diff = " << diff << std::endl;
- _dev->rfHz = freq;
- set_gain_limits(freq);
- if (_running)
- {
- if (fabs(diff) < 10000.0)
- {
- std::cerr << "mir_sdr_SetRf started" << std::endl;
- mir_sdr_SetRf(diff, 0, 0);
- }
- else
- {
- std::cerr << "reinit_device started" << std::endl;
- reinit_device();
- }
- }
+ // If no reason given, reinit everything
+ if (reason == (int)mir_sdr_CHANGE_NONE)
+ reason = (mir_sdr_CHANGE_GR |
+ mir_sdr_CHANGE_FS_FREQ |
+ mir_sdr_CHANGE_RF_FREQ |
+ mir_sdr_CHANGE_BW_TYPE |
+ mir_sdr_CHANGE_IF_TYPE |
+ mir_sdr_CHANGE_LO_MODE |
+ mir_sdr_CHANGE_AM_PORT);
+
+ int gRdB;
+ int gRdBsystem; // Returned overall system gain reduction
+
+ gRdB = _gRdB;
- std::cerr << "set_center_freq end" << std::endl;
- return get_center_freq( chan );
+ // Tell stream CB to return
+ _reinit = true;
+
+ mir_sdr_Reinit(&gRdB,
+ _fsHz / 1e6,
+ _rfHz / 1e6,
+ _bwType,
+ _ifType,
+ _loMode,
+ checkLNA(_lna),
+ &gRdBsystem,
+ mir_sdr_USE_RSP_SET_GR,
+ &_samplesPerPacket,
+ (mir_sdr_ReasonForReinitT)reason
+ );
+
+ // Set decimation with halfband filter
+ if (reason && (int)mir_sdr_CHANGE_FS_FREQ)
+ mir_sdr_DecimateControl(_decim != 1, _decim, 1);
+
+ _bufferReady.notify_one();
}
-double sdrplay_source_c::get_center_freq( size_t chan )
+std::vector<std::string> sdrplay_source_c::get_devices()
{
- if (_running)
- {
- return _dev->rfHz;
- }
+ unsigned int numDevices;
+ mir_sdr_DeviceT mirDevices[MAX_SUPPORTED_DEVICES];
+ std::vector<std::string> devices;
-// return 0;
- return _dev->rfHz;
+ mir_sdr_GetDevices(mirDevices, &numDevices, MAX_SUPPORTED_DEVICES);
+
+ for (unsigned int i=0; i<numDevices; i++) {
+ mir_sdr_DeviceT *dev = &mirDevices[i];
+ if (!dev->devAvail)
+ continue;
+ std::string args = boost::str(boost::format("sdrplay=%d,label='SDRplay %s %s'")
+ % i % hwName((int)dev->hwVer) % dev->SerNo );
+ std::cerr << args << std::endl;
+ devices.push_back( args );
+ }
+
+ return devices;
}
-double sdrplay_source_c::set_freq_corr( double ppm, size_t chan )
+size_t sdrplay_source_c::get_num_channels()
{
- return get_freq_corr( chan );
+ return 1;
}
-double sdrplay_source_c::get_freq_corr( size_t chan )
+osmosdr::meta_range_t sdrplay_source_c::get_sample_rates()
{
- return 0;
+ osmosdr::meta_range_t range;
+ range += osmosdr::range_t( 62.5e3, 10e6 );
+ return range;
}
-std::vector<std::string> sdrplay_source_c::get_gain_names( size_t chan )
+double sdrplay_source_c::set_sample_rate(double rate)
{
- std::vector< std::string > gains;
+ rate = std::min( std::max(rate,62.5e3), 10e6 );
+ _fsHz = rate;
+
+ // Decimation is required for rates below 2MS/s
+ _decim = 1;
+ while (_fsHz < 2e6) {
+ _decim *= 2;
+ _fsHz *= 2;
+ }
+
+ if (_streaming)
+ reinitDevice((int)mir_sdr_CHANGE_FS_FREQ);
- gains += "LNA_MIX_BB";
+ return get_sample_rate();
+}
+
+double sdrplay_source_c::get_sample_rate()
+{
+ return _fsHz/_decim;
+}
- return gains;
+osmosdr::freq_range_t sdrplay_source_c::get_freq_range(size_t chan)
+{
+ osmosdr::freq_range_t range;
+ range += osmosdr::range_t(SDRPLAY_FREQ_MIN, SDRPLAY_FREQ_MAX);
+ return range;
}
-osmosdr::gain_range_t sdrplay_source_c::get_gain_range( size_t chan )
+double sdrplay_source_c::set_center_freq(double freq, size_t chan)
{
- osmosdr::gain_range_t range;
+ _rfHz = freq;
- for (int i = _dev->minGain; i < _dev->maxGain; i++)
- {
- range += osmosdr::range_t( (float)i );
- }
+ if (_streaming) {
+ reinitDevice((int)mir_sdr_CHANGE_RF_FREQ);
+ }
- return range;
+ return get_center_freq( chan );
}
-osmosdr::gain_range_t sdrplay_source_c::get_gain_range( const std::string & name, size_t chan )
+double sdrplay_source_c::get_center_freq(size_t chan)
{
- return get_gain_range( chan );
+ return _rfHz;
}
-bool sdrplay_source_c::set_gain_mode( bool automatic, size_t chan )
+double sdrplay_source_c::set_freq_corr(double ppm, size_t chan)
{
- std::cerr << "set_gain_mode started" << std::endl;
- _auto_gain = automatic;
- std::cerr << "automatic = " << automatic << std::endl;
- if (automatic)
- {
- /* Start AGC */
- std::cerr << "AGC not yet implemented" << std::endl;
- }
+ return get_freq_corr( chan );
+}
- std::cerr << "set_gain_mode end" << std::endl;
- return get_gain_mode(chan);
+double sdrplay_source_c::get_freq_corr(size_t chan)
+{
+ return 0;
}
-bool sdrplay_source_c::get_gain_mode( size_t chan )
+std::vector<std::string> sdrplay_source_c::get_gain_names(size_t chan)
{
- return _auto_gain;
+ std::vector<std::string> gains;
+
+ gains += "LNA_ATTEN_STEP";
+ gains += "IF_ATTEN_DB";
+
+ // RSP1A and RSP2 have broadcast notch filters, and RSP1A has a DAB
+ // notch filter. Show all controls for all models, mainly because
+ // gqrx gets confused when switching between sources with different
+ // sets of gains.
+ gains += "BCAST_NOTCH";
+ gains += "DAB_NOTCH";
+
+ return gains;
}
-double sdrplay_source_c::set_gain( double gain, size_t chan )
+osmosdr::gain_range_t sdrplay_source_c::get_gain_range(size_t chan)
{
- std::cerr << "set_gain started" << std::endl;
- _dev->gain_dB = gain;
- std::cerr << "gain = " << gain << std::endl;
- if (gain < _dev->minGain)
- {
- _dev->gain_dB = _dev->minGain;
- }
- if (gain > _dev->maxGain)
- {
- _dev->gain_dB = _dev->maxGain;
- }
- _dev->gRdB = (int)(_dev->maxGain - gain);
+ osmosdr::gain_range_t range;
- if (_running)
- {
- std::cerr << "mir_sdr_SetGr started" << std::endl;
- mir_sdr_SetGr(_dev->gRdB, 1, 0);
- }
+ for (int i = 20; i <= 59; i++)
+ range += osmosdr::range_t((float)i);
-std::cerr << "set_gain end" << std::endl;
-return get_gain( chan );
+ return range;
}
-double sdrplay_source_c::set_gain( double gain, const std::string & name, size_t chan)
+osmosdr::gain_range_t sdrplay_source_c::get_gain_range(const std::string & name, size_t chan)
{
- return set_gain( gain, chan );
+ osmosdr::gain_range_t range;
+ int maxLnaState;
+
+ if (name == "LNA_ATTEN_STEP") {
+ if (_hwVer == 2)
+ maxLnaState = 8;
+ else if (_hwVer == 255)
+ maxLnaState = 9;
+ else
+ maxLnaState = 3;
+ for (int i = 0; i <= maxLnaState; i++)
+ range += osmosdr::range_t((float)i);
+ }
+ // RSP1A, RSP2
+ else if (name == "BCAST_NOTCH") {
+ range += osmosdr::range_t((float)0);
+ if (_hwVer == 2 || _hwVer == 255)
+ range += osmosdr::range_t((float)1);
+ }
+ // RSP1A
+ else if (name == "DAB_NOTCH") {
+ range += osmosdr::range_t((float)0);
+ if (_hwVer == 255)
+ range += osmosdr::range_t((float)1);
+ }
+ else {
+ for (int i = 20; i <= 59; i++)
+ range += osmosdr::range_t((float)i);
+ }
+
+ return range;
}
-double sdrplay_source_c::get_gain( size_t chan )
+bool sdrplay_source_c::set_gain_mode(bool automatic, size_t chan)
{
- if ( _running )
- {
- return _dev->gain_dB;
- }
+ _auto_gain = automatic;
+ if (_streaming) {
+ if (automatic) {
+ mir_sdr_AgcControl(mir_sdr_AGC_5HZ, -30, 0, 0, 0, 0, checkLNA(_lna));
+ }
+ else {
+ mir_sdr_AgcControl(mir_sdr_AGC_DISABLE, -30, 0, 0, 0, 0, checkLNA(_lna));
+ }
+ }
-// return 0;
- return _dev->gain_dB;
+ return _auto_gain;
}
-double sdrplay_source_c::get_gain( const std::string & name, size_t chan )
+bool sdrplay_source_c::get_gain_mode(size_t chan)
{
- return get_gain( chan );
+ return _auto_gain;
}
-std::vector< std::string > sdrplay_source_c::get_antennas( size_t chan )
+int sdrplay_source_c::checkLNA(int lna)
{
- std::vector< std::string > antennas;
+ // Clip LNA reduction step. See table in API section 5.3.
+ if (_hwVer == 1) {
+ lna = std::min(3, lna);
+ }
+ else if (_hwVer == 255) {
+ if (_rfHz < 60000000)
+ lna = std::min(6, lna);
+ else if (_rfHz >= 1000000000)
+ lna = std::min(8, lna);
+ else
+ lna = std::min(9, lna);
+ }
+ else if (_hwVer == 2) {
+ if (_rfHz >= 420000000)
+ lna = std::min(5, lna);
+ else if (_rfHz < 60000000 && _antenna == "HIGHZ")
+ lna = std::min(4, lna);
+ else
+ lna = std::min(8, lna);
+ }
+
+ return lna;
+}
+
+double sdrplay_source_c::set_gain(double gain, size_t chan)
+{
+ set_gain(gain, "IF_ATTEN_DB");
+ return get_gain("IF_ATTEN_DB");
+}
+
+double sdrplay_source_c::set_gain(double gain, const std::string & name, size_t chan)
+{
+ bool bcastNotchChanged = false;
+ bool dabNotchChanged = false;
+ bool gainChanged = false;
+
+ if (name == "LNA_ATTEN_STEP") {
+ if (gain != _lna)
+ gainChanged = true;
+ _lna = int(gain);
+ }
+ else if (name == "IF_ATTEN_DB") {
+ // Ignore out-of-bounds values, since caller knows limits. (GQRX spurious calls).
+ if (gain >= 20.0 && gain <= 59.0 && gain != _gRdB) {
+ gainChanged = true;
+ _gRdB = int(gain);
+ }
+ }
+ // RSP1A, RSP2
+ else if (name == "BCAST_NOTCH" && (_hwVer == 2 || _hwVer == 255)) {
+ if (int(gain) != _bcastNotch)
+ bcastNotchChanged = true;
+ _bcastNotch = int(gain);
+ }
+ // RSP1A
+ else if (name == "DAB_NOTCH" && _hwVer == 255) {
+ if (int(gain) != _dabNotch)
+ dabNotchChanged = true;
+ _dabNotch = int(gain);
+ }
+
+ if (_streaming) {
+ if (gainChanged)
+ mir_sdr_RSP_SetGr(_gRdB, checkLNA(_lna), 1 /*absolute*/, 0 /*immediate*/);
+
+ if (bcastNotchChanged) {
+ if (_hwVer == 255 ) {
+ mir_sdr_rsp1a_BroadcastNotch(_bcastNotch);
+ }
+ else if (_hwVer == 2) {
+ mir_sdr_RSPII_RfNotchEnable(_bcastNotch);
+ }
+ }
- antennas += get_antenna( chan );
+ if (dabNotchChanged) {
+ mir_sdr_rsp1a_DabNotch(_dabNotch);
+ }
+ }
- return antennas;
+ return get_gain(chan);
}
-std::string sdrplay_source_c::set_antenna( const std::string & antenna, size_t chan )
+double sdrplay_source_c::get_gain(size_t chan)
{
- return get_antenna( chan );
+ return get_gain("IF_ATTEN_DB");
}
-std::string sdrplay_source_c::get_antenna( size_t chan )
+double sdrplay_source_c::get_gain(const std::string & name, size_t chan)
{
- return "RX";
+ if (name == "LNA_ATTEN_STEP")
+ return _lna;
+ else if (name == "BCAST_NOTCH")
+ return _bcastNotch;
+ else if (name == "DAB_NOTCH")
+ return _dabNotch;
+ else if (name == "IF_ATTEN_DB")
+ return _gRdB;
+ else
+ return 0;
}
-void sdrplay_source_c::set_dc_offset_mode( int mode, size_t chan )
+std::vector<std::string> sdrplay_source_c::get_antennas(size_t chan)
{
- if ( osmosdr::source::DCOffsetOff == mode )
- {
- _dev->dcMode = 0;
- if (_running)
- {
- mir_sdr_SetDcMode(4, 1);
- }
- }
- else if ( osmosdr::source::DCOffsetManual == mode )
- {
- std::cerr << "Manual DC correction mode is not implemented." << std::endl;
- _dev->dcMode = 0;
- if (_running)
- {
- mir_sdr_SetDcMode(4, 1);
+ std::vector<std::string> antennas;
+
+ if (_hwVer == 2) {
+ antennas += "A";
+ antennas += "B";
+ antennas += "HIGHZ";
+ }
+ else {
+ antennas += "RX";
+ }
+
+ return antennas;
+}
+
+std::string sdrplay_source_c::set_antenna(const std::string & antenna, size_t chan)
+{
+ _antenna = antenna;
+
+ if (_streaming) {
+ if (_hwVer == 2) {
+ // HIGHZ is ANTENNA_B with AmPortSelect
+ if (antenna == "HIGHZ") {
+ mir_sdr_RSPII_AntennaControl(mir_sdr_RSPII_ANTENNA_B);
+ mir_sdr_AmPortSelect(1);
}
- }
- else if ( osmosdr::source::DCOffsetAutomatic == mode )
- {
- _dev->dcMode = 1;
- if (_running)
- {
- mir_sdr_SetDcMode(4, 1);
+ else {
+ if (antenna == "A")
+ mir_sdr_RSPII_AntennaControl(mir_sdr_RSPII_ANTENNA_A);
+ else
+ mir_sdr_RSPII_AntennaControl(mir_sdr_RSPII_ANTENNA_B);
+ mir_sdr_AmPortSelect(0);
}
- }
+
+ reinitDevice((int)mir_sdr_CHANGE_AM_PORT);
+ }
+ }
+
+ return antenna;
}
-void sdrplay_source_c::set_dc_offset( const std::complex<double> &offset, size_t chan )
+std::string sdrplay_source_c::get_antenna(size_t chan)
{
- std::cerr << "Manual DC correction mode is not implemented." << std::endl;
+ return _antenna.c_str();
}
-double sdrplay_source_c::set_bandwidth( double bandwidth, size_t chan )
+void sdrplay_source_c::set_dc_offset_mode(int mode, size_t chan)
{
- if (bandwidth <= 200e3) _dev->bwType = mir_sdr_BW_0_200;
- else if (bandwidth <= 300e3) _dev->bwType = mir_sdr_BW_0_300;
- else if (bandwidth <= 600e3) _dev->bwType = mir_sdr_BW_0_600;
- else if (bandwidth <= 1536e3) _dev->bwType = mir_sdr_BW_1_536;
- else if (bandwidth <= 5000e3) _dev->bwType = mir_sdr_BW_5_000;
- else if (bandwidth <= 6000e3) _dev->bwType = mir_sdr_BW_6_000;
- else if (bandwidth <= 7000e3) _dev->bwType = mir_sdr_BW_7_000;
- else _dev->bwType = mir_sdr_BW_8_000;
+ _dcMode = (osmosdr::source::DCOffsetAutomatic == mode);
+
+ if (_dcMode) {
+ mir_sdr_SetDcMode(4, 1);
+ mir_sdr_SetDcTrackTime(63);
+ }
+ mir_sdr_DCoffsetIQimbalanceControl(_dcMode, _iqMode);
+}
+
+void sdrplay_source_c::set_dc_offset(const std::complex<double> &offset, size_t chan)
+{
+ std::cerr << "set_dc_offset(): not implemented" << std::endl;
+}
+
+void sdrplay_source_c::set_iq_balance_mode(int mode, size_t chan)
+{
+ _iqMode = (osmosdr::source::IQBalanceAutomatic == mode);
+
+ mir_sdr_DCoffsetIQimbalanceControl(_dcMode, _iqMode);
+}
+
+double sdrplay_source_c::set_bandwidth(double bandwidth, size_t chan)
+{
+ _bwType = mir_sdr_BW_8_000;
+
+ for (double bw : bandwidths) {
+ // Skip dummy value at index 0
+ if (bw == 0)
+ continue;
+ if (bandwidth <= bw) {
+ _bwType = (mir_sdr_Bw_MHzT)(bw/1e3);
+ break;
+ }
+ }
+
+ int actual = get_bandwidth(chan);
+ std::cerr << "SDRplay bandwidth requested=" << bandwidth
+ << " actual=" << actual << std::endl;
- if (_running)
- {
- reinit_device();
- }
+ if (_streaming) {
+ reinitDevice((int)mir_sdr_CHANGE_BW_TYPE);
+ }
- return get_bandwidth( chan );
+ return actual;
}
-double sdrplay_source_c::get_bandwidth( size_t chan )
+double sdrplay_source_c::get_bandwidth(size_t chan)
{
- double tmpbw=0.0f;
- if (_dev->bwType == mir_sdr_BW_0_200) tmpbw = 200e3;
- else if (_dev->bwType == mir_sdr_BW_0_300) tmpbw = 300e3;
- else if (_dev->bwType == mir_sdr_BW_0_600) tmpbw = 600e3;
- else if (_dev->bwType == mir_sdr_BW_1_536) tmpbw = 1536e3;
- else if (_dev->bwType == mir_sdr_BW_5_000) tmpbw = 5000e3;
- else if (_dev->bwType == mir_sdr_BW_6_000) tmpbw = 6000e3;
- else if (_dev->bwType == mir_sdr_BW_7_000) tmpbw = 7000e3;
- else tmpbw = 8000e3;
-
- return (double)tmpbw;
+ return (double)_bwType * 1e3;
}
-osmosdr::freq_range_t sdrplay_source_c::get_bandwidth_range( size_t chan )
+osmosdr::freq_range_t sdrplay_source_c::get_bandwidth_range(size_t chan)
{
- osmosdr::freq_range_t range;
+ osmosdr::freq_range_t range;
- range += osmosdr::range_t( 200e3 );
- range += osmosdr::range_t( 300e3 );
- range += osmosdr::range_t( 600e3 );
- range += osmosdr::range_t( 1536e3 );
- range += osmosdr::range_t( 5000e3 );
- range += osmosdr::range_t( 6000e3 );
- range += osmosdr::range_t( 7000e3 );
- range += osmosdr::range_t( 8000e3 );
+ // bandwidths[0] is a dummy
+ for (unsigned int i=1; i<bandwidths.size(); i++)
+ range += osmosdr::range_t(bandwidths[i]);
- return range;
+ return range;
}
diff --git a/lib/sdrplay/sdrplay_source_c.h b/lib/sdrplay/sdrplay_source_c.h
index 2e4631e..7022af4 100644
--- a/lib/sdrplay/sdrplay_source_c.h
+++ b/lib/sdrplay/sdrplay_source_c.h
@@ -1,5 +1,6 @@
/* -*- c++ -*- */
/*
+ * Copyright 2018 Jeff Long <willcode4 at gmail.com>
* Copyright 2015 SDRplay Ltd <support at sdrplay.com>
* Copyright 2012 Dimitri Stolnikov <horiz0n at gmx.net>
*
@@ -22,17 +23,21 @@
#define INCLUDED_SDRPLAY_SOURCE_C_H
#include <gnuradio/sync_block.h>
-
#include <gnuradio/thread/thread.h>
-#include <boost/thread/mutex.hpp>
-#include <boost/thread/condition_variable.hpp>
#include "osmosdr/ranges.h"
#include "source_iface.h"
+#include <mirsdrapi-rsp.h>
+
class sdrplay_source_c;
-typedef struct sdrplay_dev sdrplay_dev_t;
+
+template <typename T>
+struct Range {
+ T min;
+ T max;
+};
/*
* We use boost::shared_ptr's instead of raw pointers for all access
@@ -82,6 +87,9 @@ public:
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items );
+ bool start( void );
+ bool stop( void );
+
static std::vector< std::string > get_devices();
size_t get_num_channels( void );
@@ -112,25 +120,58 @@ public:
void set_dc_offset_mode( int mode, size_t chan = 0 );
void set_dc_offset( const std::complex<double> &offset, size_t chan = 0 );
+ void set_iq_balance_mode( int mode, size_t chan = 0 );
double set_bandwidth( double bandwidth, size_t chan = 0 );
double get_bandwidth( size_t chan = 0 );
osmosdr::freq_range_t get_bandwidth_range( size_t chan = 0 );
private:
- void reinit_device(void);
- void set_gain_limits(double freq);
-
- sdrplay_dev_t *_dev;
-
- std::vector< short > _bufi;
- std::vector< short > _bufq;
- int _buf_offset;
- boost::mutex _buf_mutex;
+ void startStreaming(void);
+ void stopStreaming(void);
+ void reallocateBuffers(int size, int num);
+ void reinitDevice(int reason);
+ int checkLNA(int lna);
+ void streamCallback(short *xi, short *xq, unsigned int firstSampleNum,
+ int grChanged, int rfChanged, int fsChanged,
+ unsigned int numSamples, unsigned int reset);
+ void gainChangeCallback(unsigned int gRdB, unsigned int lnaGRdB);
+
+ static void streamCallbackWrap(short *xi, short *xq, unsigned int firstSampleNum,
+ int grChanged, int rfChanged, int fsChanged,
+ unsigned int numSamples, unsigned int reset,
+ void *cbContext);
+ static void gainChangeCallbackWrap(unsigned int gRdB, unsigned int lnaGRdB, void *cbContext);
- bool _running;
- bool _uninit;
bool _auto_gain;
+ int _gain;
+ int _gRdB;
+ int _lna;
+ int _bcastNotch;
+ int _dabNotch;
+ double _fsHz;
+ int _decim;
+ double _rfHz;
+ mir_sdr_Bw_MHzT _bwType;
+ mir_sdr_If_kHzT _ifType;
+ mir_sdr_LoModeT _loMode;
+ int _samplesPerPacket;
+ bool _dcMode;
+ bool _iqMode;
+ unsigned char _hwVer;
+ int _devIndex;
+ std::string _antenna;
+ int _biasT;
+
+ gr_complex *_buffer;
+ int _bufferOffset;
+ int _bufferSpaceRemaining;
+ boost::mutex _bufferMutex;
+ boost::condition_variable _bufferReady; // buffer is ready to move to other thread
+
+ bool _streaming;
+ bool _flowgraphRunning;
+ bool _reinit; // signal streamer to return after a reinit
};
#endif /* INCLUDED_SDRPLAY_SOURCE_C_H */