diff --git a/Readme.md b/Readme.md
index 47b980835..5277342d5 100644
--- a/Readme.md
+++ b/Readme.md
@@ -51,7 +51,7 @@ If you use your own location for libairspy install directory you need to specify
`-DLIBAIRSPY_LIBRARIES=/opt/install/libairspy/lib/libairspy.so -DLIBAIRSPY_INCLUDE_DIR=/opt/install/libairspy/include`
-Please note that if you are not using a recent version of libairspy (>= 1.0.6) the dynamic retrieval of sample rates is not supported. In this case you should modify the `plugins/samplesource/airspy/CMakeLists.txt` and change line `add_definitions(${QT_DEFINITIONS})` by `add_definitions("${QT_DEFINITIONS} -DLIBAIRSPY_OLD")`. In fact both lines are present with the former one commented out.
+Please note that if you are using a recent version of libairspy (>= 1.0.6) the dynamic retrieval of sample rates is supported. To benefit from it you should modify the `plugins/samplesource/airspy/CMakeLists.txt` and change line `add_definitions(${QT_DEFINITIONS})` by `add_definitions("${QT_DEFINITIONS} -DLIBAIRSPY_DYN_RATES")`. In fact both lines are present with the last one commented out.
BladeRF
diff --git a/plugins/samplesource/airspy/CMakeLists.txt b/plugins/samplesource/airspy/CMakeLists.txt
index bf39ea115..5eaeaa731 100644
--- a/plugins/samplesource/airspy/CMakeLists.txt
+++ b/plugins/samplesource/airspy/CMakeLists.txt
@@ -29,8 +29,8 @@ include_directories(
)
#include(${QT_USE_FILE})
-#add_definitions("${QT_DEFINITIONS} -DLIBAIRSPY_OLD")
-add_definitions(${QT_DEFINITIONS})
+#add_definitions(${QT_DEFINITIONS})
+add_definitions("${QT_DEFINITIONS} -DLIBAIRSPY_DYN_RATES")
add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_SHARED)
diff --git a/plugins/samplesource/airspy/airspygui.cpp b/plugins/samplesource/airspy/airspygui.cpp
index 2cf2e838d..bf7189371 100644
--- a/plugins/samplesource/airspy/airspygui.cpp
+++ b/plugins/samplesource/airspy/airspygui.cpp
@@ -37,6 +37,9 @@ AirspyGui::AirspyGui(PluginAPI* pluginAPI, QWidget* parent) :
displaySettings();
m_sampleSource = new AirspyInput();
+ m_rates = ((AirspyInput*) m_sampleSource)->getSampleRates();
+ displaySampleRates();
+ connect(m_sampleSource->getOutputMessageQueueToGUI(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
DSPEngine::instance()->setSource(m_sampleSource);
}
@@ -94,7 +97,9 @@ bool AirspyGui::handleMessage(const Message& message)
{
if (AirspyInput::MsgReportAirspy::match(message))
{
- displaySettings();
+ qDebug() << "AirspyGui::handleMessage: MsgReportAirspy";
+ m_rates = ((AirspyInput::MsgReportAirspy&) message).getSampleRates();
+ displaySampleRates();
return true;
}
else
@@ -103,6 +108,21 @@ bool AirspyGui::handleMessage(const Message& message)
}
}
+void AirspyGui::handleSourceMessages()
+{
+ Message* message;
+
+ while ((message = m_sampleSource->getOutputMessageQueueToGUI()->pop()) != 0)
+ {
+ qDebug("AirspyGui::HandleSourceMessages: message: %s", message->getIdentifier());
+
+ if (handleMessage(*message))
+ {
+ delete message;
+ }
+ }
+}
+
void AirspyGui::displaySettings()
{
ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000);
@@ -129,6 +149,33 @@ void AirspyGui::displaySettings()
ui->vga->setValue(m_settings.m_vgaGain);
}
+void AirspyGui::displaySampleRates()
+{
+ int savedIndex = m_settings.m_devSampleRateIndex;
+ ui->sampleRate->blockSignals(true);
+
+ if (m_rates.size() > 0)
+ {
+ ui->sampleRate->clear();
+
+ for (int i = 0; i < m_rates.size(); i++)
+ {
+ ui->sampleRate->addItem(QString("%1M").arg(QString::number(m_rates[i]/1000000.0, 'f', 3)));
+ }
+ }
+
+ ui->sampleRate->blockSignals(false);
+
+ if (savedIndex < m_rates.size())
+ {
+ ui->sampleRate->setCurrentIndex(savedIndex);
+ }
+ else
+ {
+ ui->sampleRate->setCurrentIndex((int) m_rates.size()-1);
+ }
+}
+
void AirspyGui::sendSettings()
{
if(!m_updateTimer.isActive())
@@ -188,7 +235,7 @@ void AirspyGui::on_lna_valueChanged(int value)
if ((value < 0) || (value > 14))
return;
- ui->lnaGainText->setText(tr("%1dB").arg(value*3));
+ ui->lnaGainText->setText(tr("%1dB").arg(value));
m_settings.m_lnaGain = value;
sendSettings();
}
@@ -198,7 +245,7 @@ void AirspyGui::on_mix_valueChanged(int value)
if ((value < 0) || (value > 15))
return;
- ui->mixText->setText(tr("%1dB").arg(value*3));
+ ui->mixText->setText(tr("%1dB").arg(value));
m_settings.m_lnaGain = value;
sendSettings();
}
@@ -208,7 +255,7 @@ void AirspyGui::on_vga_valueChanged(int value)
if ((value < 0) || (value > 15))
return;
- ui->vgaText->setText(tr("%1dB").arg(value*3));
+ ui->vgaText->setText(tr("%1dB").arg(value));
m_settings.m_lnaGain = value;
sendSettings();
}
diff --git a/plugins/samplesource/airspy/airspygui.h b/plugins/samplesource/airspy/airspygui.h
index 377d2d608..a65f3c9a9 100644
--- a/plugins/samplesource/airspy/airspygui.h
+++ b/plugins/samplesource/airspy/airspygui.h
@@ -60,6 +60,7 @@ private:
SampleSource* m_sampleSource;
void displaySettings();
+ void displaySampleRates();
void sendSettings();
private slots:
@@ -73,6 +74,7 @@ private slots:
void on_mix_valueChanged(int value);
void on_vga_valueChanged(int value);
void updateHardware();
+ void handleSourceMessages();
};
#endif // INCLUDE_AIRSPYGUI_H
diff --git a/plugins/samplesource/airspy/airspygui.ui b/plugins/samplesource/airspy/airspygui.ui
index 72e00564b..8a9071808 100644
--- a/plugins/samplesource/airspy/airspygui.ui
+++ b/plugins/samplesource/airspy/airspygui.ui
@@ -351,7 +351,7 @@
1
- 15
+ 5
Qt::Horizontal
@@ -410,7 +410,7 @@
1
- 9
+ 5
Qt::Horizontal
diff --git a/plugins/samplesource/airspy/airspyinput.cpp b/plugins/samplesource/airspy/airspyinput.cpp
index 79b318473..541e8fec7 100644
--- a/plugins/samplesource/airspy/airspyinput.cpp
+++ b/plugins/samplesource/airspy/airspyinput.cpp
@@ -100,6 +100,8 @@ AirspyInput::AirspyInput() :
m_airspyThread(0),
m_deviceDescription("Airspy")
{
+ m_sampleRates.push_back(10000000);
+ m_sampleRates.push_back(2500000);
}
AirspyInput::~AirspyInput()
@@ -135,16 +137,13 @@ bool AirspyInput::start(int device)
return false;
}
- if ((m_dev = open_airspy_from_sequence(device)) == 0) // TODO: fix; Open first available device as there is no proper handling for multiple devices
+ if ((m_dev = open_airspy_from_sequence(device)) == 0)
{
- qCritical("AirspyInput::start: could not open Airspy");
+ qCritical("AirspyInput::start: could not open Airspy #%d", device);
return false;
}
-#ifdef LIBAIRSPY_OLD
- m_sampleRates.push_back(2500000);
- m_sampleRates.push_back(10000000);
-#else
+#ifdef LIBAIRSPY_DYN_RATES
uint32_t nbSampleRates;
uint32_t *sampleRates;
@@ -160,14 +159,20 @@ bool AirspyInput::start(int device)
return false;
}
+ m_sampleRates.clear();
+
for (int i=0; ipush(message);
+
rc = (airspy_error) airspy_set_sample_type(m_dev, AIRSPY_SAMPLE_INT16_IQ);
if (rc != AIRSPY_SUCCESS)
@@ -176,31 +181,27 @@ bool AirspyInput::start(int device)
return false;
}
- applySettings(m_settings, true);
-
- MsgReportAirspy *message = MsgReportAirspy::create(m_sampleRates);
- getOutputMessageQueueToGUI()->push(message);
-
- if((m_airspyThread = new AirspyThread(m_dev, &m_sampleFifo)) == NULL) {
- qFatal("out of memory");
- goto failed;
+ if((m_airspyThread = new AirspyThread(m_dev, &m_sampleFifo)) == 0)
+ {
+ qFatal("AirspyInput::start: out of memory");
+ stop();
+ return false;
}
m_airspyThread->startWork();
mutexLocker.unlock();
+ applySettings(m_settings, true);
+
qDebug("AirspyInput::startInput: started");
return true;
-
-failed:
- stop();
- return false;
}
void AirspyInput::stop()
{
+ qDebug("AirspyInput::stop");
QMutexLocker mutexLocker(&m_mutex);
if(m_airspyThread != 0)
@@ -243,7 +244,9 @@ bool AirspyInput::handleMessage(const Message& message)
MsgConfigureAirspy& conf = (MsgConfigureAirspy&) message;
qDebug() << "AirspyInput::handleMessage: MsgConfigureAirspy";
- if (!applySettings(conf.getSettings(), false))
+ bool success = applySettings(conf.getSettings(), false);
+
+ if (!success)
{
qDebug("Airspy config error");
}
@@ -274,32 +277,29 @@ void AirspyInput::setCenterFrequency(quint64 freq_hz)
bool AirspyInput::applySettings(const Settings& settings, bool force)
{
- bool forwardChange = false;
- airspy_error rc;
- qint64 deviceCenterFrequency = m_settings.m_centerFrequency;
- qint64 f_img = deviceCenterFrequency;
- quint32 devSampleRate = m_sampleRates[m_settings.m_devSampleRateIndex];
-
QMutexLocker mutexLocker(&m_mutex);
- qDebug() << "AirspyInput::applySettings: m_dev: " << m_dev;
+ bool forwardChange = false;
+ airspy_error rc;
+
+ qDebug() << "AirspyInput::applySettings";
if ((m_settings.m_devSampleRateIndex != settings.m_devSampleRateIndex) || force)
{
+ forwardChange = true;
+
if (settings.m_devSampleRateIndex < m_sampleRates.size())
{
m_settings.m_devSampleRateIndex = settings.m_devSampleRateIndex;
}
else
{
- m_settings.m_devSampleRateIndex = m_sampleRates.size() - 1;
+ m_settings.m_devSampleRateIndex = m_sampleRates.size() - 1;
}
- forwardChange = true;
-
if (m_dev != 0)
{
- rc = (airspy_error) airspy_set_samplerate(m_dev, static_cast(m_sampleRates[m_settings.m_devSampleRateIndex]));
+ rc = (airspy_error) airspy_set_samplerate(m_dev, static_cast(m_settings.m_devSampleRateIndex));
if (rc != AIRSPY_SUCCESS)
{
@@ -336,6 +336,10 @@ bool AirspyInput::applySettings(const Settings& settings, bool force)
}
}
+ qint64 deviceCenterFrequency = m_settings.m_centerFrequency;
+ qint64 f_img = deviceCenterFrequency;
+ quint32 devSampleRate = m_sampleRates[m_settings.m_devSampleRateIndex];
+
if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force)
{
m_settings.m_centerFrequency = settings.m_centerFrequency;
@@ -461,12 +465,16 @@ bool AirspyInput::applySettings(const Settings& settings, bool force)
struct airspy_device *AirspyInput::open_airspy_from_sequence(int sequence)
{
- struct airspy_device *devinfo;
- int rc;
+ airspy_read_partid_serialno_t read_partid_serialno;
+ struct airspy_device *devinfo, *retdev = 0;
+ uint32_t serial_msb = 0;
+ uint32_t serial_lsb = 0;
+ airspy_error rc;
+ int i;
- for (int i=0; i < AIRSPY_MAX_DEVICE; i++)
+ for (int i = 0; i < AIRSPY_MAX_DEVICE; i++)
{
- rc = airspy_open(&devinfo);
+ rc = (airspy_error) airspy_open(&devinfo);
if (rc == AIRSPY_SUCCESS)
{
@@ -474,10 +482,14 @@ struct airspy_device *AirspyInput::open_airspy_from_sequence(int sequence)
{
return devinfo;
}
+ else
+ {
+ airspy_close(devinfo);
+ }
}
else
{
- break; // finished
+ break;
}
}
diff --git a/plugins/samplesource/airspy/airspyinput.h b/plugins/samplesource/airspy/airspyinput.h
index 863f28ebd..aa2639efd 100644
--- a/plugins/samplesource/airspy/airspyinput.h
+++ b/plugins/samplesource/airspy/airspyinput.h
@@ -98,6 +98,7 @@ public:
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual quint64 getCenterFrequency() const;
+ const std::vector& getSampleRates() const { return m_sampleRates; }
virtual bool handleMessage(const Message& message);
diff --git a/plugins/samplesource/airspy/airspyplugin.cpp b/plugins/samplesource/airspy/airspyplugin.cpp
index b0394e4c2..5651ffef8 100644
--- a/plugins/samplesource/airspy/airspyplugin.cpp
+++ b/plugins/samplesource/airspy/airspyplugin.cpp
@@ -53,8 +53,11 @@ PluginInterface::SampleSourceDevices AirspyPlugin::enumSampleSources()
{
SampleSourceDevices result;
airspy_read_partid_serialno_t read_partid_serialno;
- struct airspy_device *devinfo = 0;
+ struct airspy_device *devinfo;
+ uint32_t serial_msb = 0;
+ uint32_t serial_lsb = 0;
airspy_error rc;
+ int i;
rc = (airspy_error) airspy_init();
@@ -63,29 +66,40 @@ PluginInterface::SampleSourceDevices AirspyPlugin::enumSampleSources()
qCritical("AirspyPlugin::enumSampleSources: failed to initiate Airspy library: %s", airspy_error_name(rc));
}
- for (int i=0; i < AIRSPY_MAX_DEVICE; i++)
+ for (i=0; i < AIRSPY_MAX_DEVICE; i++)
{
rc = (airspy_error) airspy_open(&devinfo);
if (rc == AIRSPY_SUCCESS)
{
+ qDebug("AirspyPlugin::enumSampleSources: try to enumerate Airspy device #%d", i);
+
rc = (airspy_error) airspy_board_partid_serialno_read(devinfo, &read_partid_serialno);
if (rc != AIRSPY_SUCCESS)
{
qDebug("AirspyPlugin::enumSampleSources: failed to read serial no: %s", airspy_error_name(rc));
+ airspy_close(devinfo);
continue; // next
}
- QString serial_str = QString::number(read_partid_serialno.serial_no[2], 16) + QString::number(read_partid_serialno.serial_no[3], 16);
- uint64_t serial_num = (((uint64_t) read_partid_serialno.serial_no[2])<<32) + read_partid_serialno.serial_no[3];
- QString displayedName(QString("Airspy #%1 0x%2").arg(i+1).arg(serial_str));
- SimpleSerializer s(1);
- s.writeS32(1, i);
- s.writeString(2, serial_str);
- s.writeU64(3, serial_num);
+ if ((read_partid_serialno.serial_no[2] != serial_msb) && (read_partid_serialno.serial_no[3] != serial_lsb))
+ {
+ serial_msb = read_partid_serialno.serial_no[2];
+ serial_lsb = read_partid_serialno.serial_no[3];
- result.append(SampleSourceDevice(displayedName, "org.osmocom.sdr.samplesource.airspy", s.final()));
+ QString serial_str = QString::number(serial_msb, 16) + QString::number(serial_lsb, 16);
+ uint64_t serial_num = (((uint64_t) serial_msb)<<32) + serial_lsb;
+ QString displayedName(QString("Airspy #%1 0x%2").arg(i).arg(serial_str));
+ SimpleSerializer s(1);
+ s.writeS32(1, i);
+ s.writeString(2, serial_str);
+ s.writeU64(3, serial_num);
+ result.append(SampleSourceDevice(displayedName, "org.osmocom.sdr.samplesource.airspy", s.final()));
+ qDebug("AirspyPlugin::enumSampleSources: enumerated Airspy device #%d", i);
+ }
+
+ airspy_close(devinfo);
}
else
{
@@ -94,7 +108,8 @@ PluginInterface::SampleSourceDevices AirspyPlugin::enumSampleSources()
}
}
- airspy_exit();
+ rc = (airspy_error) airspy_exit();
+ qDebug("AirspyPlugin::enumSampleSources: airspy_exit: %s", airspy_error_name(rc));
return result;
}
diff --git a/plugins/samplesource/airspy/airspythread.cpp b/plugins/samplesource/airspy/airspythread.cpp
index e837cce88..c01035ecf 100644
--- a/plugins/samplesource/airspy/airspythread.cpp
+++ b/plugins/samplesource/airspy/airspythread.cpp
@@ -52,6 +52,7 @@ void AirspyThread::startWork()
void AirspyThread::stopWork()
{
+ qDebug("AirspyThread::stopWork");
m_running = false;
wait();
}
@@ -92,6 +93,17 @@ void AirspyThread::run()
}
}
+ rc = (airspy_error) airspy_stop_rx(m_dev);
+
+ if (rc == AIRSPY_SUCCESS)
+ {
+ qDebug("AirspyInput::run: stopped Airspy Rx");
+ }
+ else
+ {
+ qDebug("AirspyInput::run: failed to stop Airspy Rx: %s", airspy_error_name(rc));
+ }
+
m_running = false;
}
@@ -177,13 +189,13 @@ void AirspyThread::callback(const qint16* buf, qint32 len)
}
}
-
m_sampleFifo->write(m_convertBuffer.begin(), it);
}
int AirspyThread::rx_callback(airspy_transfer_t* transfer)
{
- qint32 bytes_to_write = transfer->sample_count * sizeof(qint16) * 2;
+ qint32 bytes_to_write = transfer->sample_count * sizeof(qint16);
m_this->callback((qint16 *) transfer->samples, bytes_to_write);
+ return 0;
}
diff --git a/plugins/samplesource/airspy/airspythread.h b/plugins/samplesource/airspy/airspythread.h
index 1e9a7b880..29097bf39 100644
--- a/plugins/samplesource/airspy/airspythread.h
+++ b/plugins/samplesource/airspy/airspythread.h
@@ -24,7 +24,7 @@
#include "dsp/samplefifo.h"
#include "dsp/decimators.h"
-#define AIRSPY_BLOCKSIZE (1<<14)
+#define AIRSPY_BLOCKSIZE (1<<17)
class AirspyThread : public QThread {
Q_OBJECT