diff --git a/Readme.md b/Readme.md index 6f4578fc9..47b980835 100644 --- a/Readme.md +++ b/Readme.md @@ -43,6 +43,16 @@ Use `cmake ../ -DV4L-RTL=ON` to build the Linux kernel driver for RTL-SDR (Exper

Supported hardware

+

Airspy

+ +Airspy is supported through the libairspy library that should be installed in your system for proper build of the software and operation support. Add `libairspy-dev` to the list of dependencies to install. + +If you use your own location for libairspy install directory you need to specify library and include locations. Example with `/opt/install/libairspy` with the following defines on `cmake` command line: + +`-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. +

BladeRF

BladeRF 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. diff --git a/cmake/Modules/FindLibAIRSPY.cmake b/cmake/Modules/FindLibAIRSPY.cmake new file mode 100644 index 000000000..2402f2f74 --- /dev/null +++ b/cmake/Modules/FindLibAIRSPY.cmake @@ -0,0 +1,28 @@ +if(NOT LIBAIRSPY_FOUND) + + pkg_check_modules (LIBAIRSPY_PKG libairspy) + find_path(LIBAIRSPY_INCLUDE_DIR NAMES libairspy/airspy.h + PATHS + ${LIBAIRSPY_PKG_INCLUDE_DIRS} + /usr/include + /usr/local/include + ) + + find_library(LIBAIRSPY_LIBRARIES NAMES airspy + PATHS + ${LIBAIRSPY_PKG_LIBRARY_DIRS} + /usr/lib + /usr/local/lib + ) + + if(LIBAIRSPY_INCLUDE_DIR AND LIBAIRSPY_LIBRARIES) + set(LIBAIRSPY_FOUND TRUE CACHE INTERNAL "libairspy found") + message(STATUS "Found libairspy: ${LIBAIRSPY_INCLUDE_DIR}, ${LIBAIRSPY_LIBRARIES}") + else(LIBAIRSPY_INCLUDE_DIR AND LIBAIRSPY_LIBRARIES) + set(LIBAIRSPY_FOUND FALSE CACHE INTERNAL "libairspy found") + message(STATUS "libairspy not found.") + endif(LIBAIRSPY_INCLUDE_DIR AND LIBAIRSPY_LIBRARIES) + + mark_as_advanced(LIBAIRSPY_INCLUDE_DIR LIBAIRSPY_LIBRARIES) + +endif(NOT LIBAIRSPY_FOUND) diff --git a/plugins/samplesource/CMakeLists.txt b/plugins/samplesource/CMakeLists.txt index 150632393..ae8d2babb 100644 --- a/plugins/samplesource/CMakeLists.txt +++ b/plugins/samplesource/CMakeLists.txt @@ -32,4 +32,9 @@ if(LIBUSB_FOUND AND LIBBLADERF_FOUND) add_subdirectory(bladerf) endif(LIBUSB_FOUND AND LIBBLADERF_FOUND) +find_package(LibAIRSPY) +if(LIBUSB_FOUND AND LIBAIRSPY_FOUND) + add_subdirectory(airspy) +endif(LIBUSB_FOUND AND LIBAIRSPY_FOUND) + add_subdirectory(filesource) diff --git a/plugins/samplesource/airspy/CMakeLists.txt b/plugins/samplesource/airspy/CMakeLists.txt index d3161d347..bf39ea115 100644 --- a/plugins/samplesource/airspy/CMakeLists.txt +++ b/plugins/samplesource/airspy/CMakeLists.txt @@ -29,6 +29,7 @@ include_directories( ) #include(${QT_USE_FILE}) +#add_definitions("${QT_DEFINITIONS} -DLIBAIRSPY_OLD") add_definitions(${QT_DEFINITIONS}) add_definitions(-DQT_PLUGIN) add_definitions(-DQT_SHARED) diff --git a/plugins/samplesource/airspy/airspygui.cpp b/plugins/samplesource/airspy/airspygui.cpp index 8d5066a09..2cf2e838d 100644 --- a/plugins/samplesource/airspy/airspygui.cpp +++ b/plugins/samplesource/airspy/airspygui.cpp @@ -32,7 +32,7 @@ AirspyGui::AirspyGui(PluginAPI* pluginAPI, QWidget* parent) : { ui->setupUi(this); ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold)); - ui->centerFrequency->setValueRange(7, BLADERF_FREQUENCY_MIN_XB200/1000, BLADERF_FREQUENCY_MAX/1000); + ui->centerFrequency->setValueRange(7, 24000U, 1900000U); connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); displaySettings(); @@ -107,29 +107,26 @@ void AirspyGui::displaySettings() { ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000); - ui->samplerateText->setText(tr("%1k").arg(m_settings.m_devSampleRate / 1000)); - unsigned int sampleRateIndex = AirspySampleRates::getRateIndex(m_settings.m_devSampleRate); - ui->samplerate->setValue(sampleRateIndex); + ui->LOppm->setValue(m_settings.m_LOppmTenths); + ui->LOppmText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1))); - ui->bandwidthText->setText(tr("%1k").arg(m_settings.m_bandwidth / 1000)); - unsigned int bandwidthIndex = AirspyBandwidths::getBandwidthIndex(m_settings.m_bandwidth); - ui->bandwidth->setValue(bandwidthIndex); + ui->sampleRate->setCurrentIndex(m_settings.m_devSampleRateIndex); + + ui->biasT->setChecked(m_settings.m_biasT); ui->decimText->setText(tr("%1").arg(1<decim->setValue(m_settings.m_log2Decim); ui->fcPos->setCurrentIndex((int) m_settings.m_fcPos); - ui->lnaGainText->setText(tr("%1dB").arg(m_settings.m_lnaGain*3)); + ui->lnaGainText->setText(tr("%1dB").arg(m_settings.m_lnaGain)); ui->lna->setValue(m_settings.m_lnaGain); - ui->vga1Text->setText(tr("%1dB").arg(m_settings.m_vga1)); - ui->vga1->setValue(m_settings.m_vga1); + ui->mixText->setText(tr("%1dB").arg(m_settings.m_mixerGain)); + ui->mix->setValue(m_settings.m_mixerGain); - ui->vga2Text->setText(tr("%1dB").arg(m_settings.m_vga2)); - ui->vga2->setValue(m_settings.m_vga2); - - ui->xb200->setCurrentIndex(getXb200Index(m_settings.m_xb200, m_settings.m_xb200Path, m_settings.m_xb200Filter)); + ui->vgaText->setText(tr("%1dB").arg(m_settings.m_vgaGain)); + ui->vga->setValue(m_settings.m_vgaGain); } void AirspyGui::sendSettings() @@ -144,19 +141,22 @@ void AirspyGui::on_centerFrequency_changed(quint64 value) sendSettings(); } -void AirspyGui::on_samplerate_valueChanged(int value) +void AirspyGui::on_LOppm_valueChanged(int value) { - int newrate = AirspySampleRates::getRate(value); - ui->samplerateText->setText(tr("%1k").arg(newrate)); - m_settings.m_devSampleRate = newrate * 1000; + m_settings.m_LOppmTenths = value; + ui->LOppmText->setText(QString("%1").arg(QString::number(m_settings.m_LOppmTenths/10.0, 'f', 1))); sendSettings(); } -void AirspyGui::on_bandwidth_valueChanged(int value) +void AirspyGui::on_sampleRate_currentIndexChanged(int index) { - int newbw = AirspyBandwidths::getBandwidth(value); - ui->bandwidthText->setText(tr("%1k").arg(newbw)); - m_settings.m_bandwidth = newbw * 1000; + m_settings.m_devSampleRateIndex = index; + sendSettings(); +} + +void AirspyGui::on_biasT_stateChanged(int state) +{ + m_settings.m_biasT = (state == Qt::Checked); sendSettings(); } @@ -185,9 +185,7 @@ void AirspyGui::on_fcPos_currentIndexChanged(int index) void AirspyGui::on_lna_valueChanged(int value) { - qDebug() << "AirspyGui: LNA gain = " << value; - - if ((value < 0) || (value > 2)) + if ((value < 0) || (value > 14)) return; ui->lnaGainText->setText(tr("%1dB").arg(value*3)); @@ -195,83 +193,23 @@ void AirspyGui::on_lna_valueChanged(int value) sendSettings(); } -void AirspyGui::on_vga1_valueChanged(int value) +void AirspyGui::on_mix_valueChanged(int value) { - if ((value < BLADERF_RXVGA1_GAIN_MIN) || (value > BLADERF_RXVGA1_GAIN_MAX)) + if ((value < 0) || (value > 15)) return; - ui->vga1Text->setText(tr("%1dB").arg(value)); - m_settings.m_vga1 = value; + ui->mixText->setText(tr("%1dB").arg(value*3)); + m_settings.m_lnaGain = value; sendSettings(); } -void AirspyGui::on_vga2_valueChanged(int value) +void AirspyGui::on_vga_valueChanged(int value) { - if ((value < BLADERF_RXVGA2_GAIN_MIN) || (value > BLADERF_RXVGA2_GAIN_MAX)) + if ((value < 0) || (value > 15)) return; - ui->vga2Text->setText(tr("%1dB").arg(value)); - m_settings.m_vga2 = value; - sendSettings(); -} - -void AirspyGui::on_xb200_currentIndexChanged(int index) -{ - if (index == 1) // bypass - { - m_settings.m_xb200 = true; - m_settings.m_xb200Path = BLADERF_XB200_BYPASS; - } - else if (index == 2) // Auto 1dB - { - m_settings.m_xb200 = true; - m_settings.m_xb200Path = BLADERF_XB200_MIX; - m_settings.m_xb200Filter = BLADERF_XB200_AUTO_1DB; - } - else if (index == 3) // Auto 3dB - { - m_settings.m_xb200 = true; - m_settings.m_xb200Path = BLADERF_XB200_MIX; - m_settings.m_xb200Filter = BLADERF_XB200_AUTO_3DB; - } - else if (index == 4) // Custom - { - m_settings.m_xb200 = true; - m_settings.m_xb200Path = BLADERF_XB200_MIX; - m_settings.m_xb200Filter = BLADERF_XB200_CUSTOM; - } - else if (index == 5) // 50 MHz - { - m_settings.m_xb200 = true; - m_settings.m_xb200Path = BLADERF_XB200_MIX; - m_settings.m_xb200Filter = BLADERF_XB200_50M; - } - else if (index == 6) // 144 MHz - { - m_settings.m_xb200 = true; - m_settings.m_xb200Path = BLADERF_XB200_MIX; - m_settings.m_xb200Filter = BLADERF_XB200_144M; - } - else if (index == 7) // 222 MHz - { - m_settings.m_xb200 = true; - m_settings.m_xb200Path = BLADERF_XB200_MIX; - m_settings.m_xb200Filter = BLADERF_XB200_222M; - } - else // no xb200 - { - m_settings.m_xb200 = false; - } - - if (m_settings.m_xb200) - { - ui->centerFrequency->setValueRange(7, BLADERF_FREQUENCY_MIN_XB200/1000, BLADERF_FREQUENCY_MAX/1000); - } - else - { - ui->centerFrequency->setValueRange(7, BLADERF_FREQUENCY_MIN/1000, BLADERF_FREQUENCY_MAX/1000); - } - + ui->vgaText->setText(tr("%1dB").arg(value*3)); + m_settings.m_lnaGain = value; sendSettings(); } @@ -283,58 +221,9 @@ void AirspyGui::updateHardware() m_updateTimer.stop(); } -unsigned int AirspyGui::getXb200Index(bool xb_200, bladerf_xb200_path xb200Path, bladerf_xb200_filter xb200Filter) +uint32_t AirspyGui::getDevSampleRate(unsigned int rate_index) { - if (xb_200) - { - if (xb200Path == BLADERF_XB200_BYPASS) - { - return 1; - } - else - { - if (xb200Filter == BLADERF_XB200_AUTO_1DB) - { - return 2; - } - else if (xb200Filter == BLADERF_XB200_AUTO_3DB) - { - return 3; - } - else if (xb200Filter == BLADERF_XB200_CUSTOM) - { - return 4; - } - else if (xb200Filter == BLADERF_XB200_50M) - { - return 5; - } - else if (xb200Filter == BLADERF_XB200_144M) - { - return 6; - } - else if (xb200Filter == BLADERF_XB200_222M) - { - return 7; - } - else - { - return 0; - } - } - } - else - { - return 0; - } -} - -unsigned int AirspySampleRates::m_rates[] = {2500, 10000}; -unsigned int AirspySampleRates::m_nb_rates = 2; - -unsigned int AirspySampleRates::getRate(unsigned int rate_index) -{ - if (rate_index < m_nb_rates) + if (rate_index < m_rates.size()) { return m_rates[rate_index]; } @@ -344,43 +233,15 @@ unsigned int AirspySampleRates::getRate(unsigned int rate_index) } } -unsigned int AirspySampleRates::getRateIndex(unsigned int rate) +int AirspyGui::getDevSampleRateIndex(uint32_t sampeRate) { - for (unsigned int i=0; i < m_nb_rates; i++) + for (unsigned int i=0; i < m_rates.size(); i++) { - if (rate/1000 == m_rates[i]) + if (sampeRate == m_rates[i]) { return i; } } - return 0; -} - -unsigned int AirspyBandwidths::m_halfbw[] = {}; -unsigned int AirspyBandwidths::m_nb_halfbw = 0; - -unsigned int AirspyBandwidths::getBandwidth(unsigned int bandwidth_index) -{ - if (bandwidth_index < m_nb_halfbw) - { - return m_halfbw[bandwidth_index] * 2; - } - else - { - return m_halfbw[0] * 2; - } -} - -unsigned int AirspyBandwidths::getBandwidthIndex(unsigned int bandwidth) -{ - for (unsigned int i=0; i < m_nb_halfbw; i++) - { - if (bandwidth/2000 == m_halfbw[i]) - { - return i; - } - } - - return 0; + return -1; } diff --git a/plugins/samplesource/airspy/airspygui.h b/plugins/samplesource/airspy/airspygui.h index a39d1aeb2..377d2d608 100644 --- a/plugins/samplesource/airspy/airspygui.h +++ b/plugins/samplesource/airspy/airspygui.h @@ -47,6 +47,8 @@ public: QByteArray serialize() const; bool deserialize(const QByteArray& data); virtual bool handleMessage(const Message& message); + uint32_t getDevSampleRate(unsigned int index); + int getDevSampleRateIndex(uint32_t sampleRate); private: Ui::AirspyGui* ui; @@ -54,42 +56,23 @@ private: PluginAPI* m_pluginAPI; AirspyInput::Settings m_settings; QTimer m_updateTimer; - std::vector m_gains; + std::vector m_rates; SampleSource* m_sampleSource; void displaySettings(); void sendSettings(); - unsigned int getXb200Index(bool xb_200, bladerf_xb200_path xb200Path, bladerf_xb200_filter xb200Filter); private slots: void on_centerFrequency_changed(quint64 value); - void on_samplerate_valueChanged(int value); - void on_bandwidth_valueChanged(int value); + void on_LOppm_valueChanged(int value); + void on_sampleRate_currentIndexChanged(int index); + void on_biasT_stateChanged(int state); void on_decim_valueChanged(int value); - void on_lna_valueChanged(int value); - void on_vga1_valueChanged(int value); - void on_vga2_valueChanged(int value); - void on_xb200_currentIndexChanged(int index); void on_fcPos_currentIndexChanged(int index); + void on_lna_valueChanged(int value); + void on_mix_valueChanged(int value); + void on_vga_valueChanged(int value); void updateHardware(); }; -class AirspySampleRates { -public: - static unsigned int getRate(unsigned int rate_index); - static unsigned int getRateIndex(unsigned int rate); -private: - static unsigned int m_rates[14]; - static unsigned int m_nb_rates; -}; - -class AirspyBandwidths { -public: - static unsigned int getBandwidth(unsigned int bandwidth_index); - static unsigned int getBandwidthIndex(unsigned int bandwidth); -private: - static unsigned int m_halfbw[16]; - static unsigned int m_nb_halfbw; -}; - #endif // INCLUDE_AIRSPYGUI_H diff --git a/plugins/samplesource/airspy/airspygui.ui b/plugins/samplesource/airspy/airspygui.ui index 8659ba029..72e00564b 100644 --- a/plugins/samplesource/airspy/airspygui.ui +++ b/plugins/samplesource/airspy/airspygui.ui @@ -1,13 +1,13 @@ - BladerfGui - + AirspyGui + 0 0 198 - 239 + 214 @@ -128,7 +128,7 @@ - + 0.0 @@ -148,30 +148,15 @@ 3 - - - - Device Samplerate - - - 1 - - - 1 - - - 0 - - - 0 - - - Qt::Horizontal + + + + Bias T - + 0 @@ -183,19 +168,10 @@ - - - - - 40 - 0 - - - - --- - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + Device sample rate @@ -346,7 +322,7 @@ - 0 + 0dB Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -391,7 +367,7 @@ - 0 + 0dB Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -450,7 +426,7 @@ - 0 + 0dB Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -459,37 +435,6 @@ - - - - Qt::Horizontal - - - - - - - - - Bias Tee - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - diff --git a/plugins/samplesource/airspy/airspyinput.cpp b/plugins/samplesource/airspy/airspyinput.cpp index f1e5581bf..79b318473 100644 --- a/plugins/samplesource/airspy/airspyinput.cpp +++ b/plugins/samplesource/airspy/airspyinput.cpp @@ -30,7 +30,7 @@ MESSAGE_CLASS_DEFINITION(AirspyInput::MsgReportAirspy, Message) AirspyInput::Settings::Settings() : m_centerFrequency(435000*1000), - m_devSampleRate(2500000), + m_devSampleRateIndex(0), m_LOppmTenths(0), m_lnaGain(1), m_mixerGain(5), @@ -44,7 +44,7 @@ AirspyInput::Settings::Settings() : void AirspyInput::Settings::resetToDefaults() { m_centerFrequency = 435000*1000; - m_devSampleRate = 2500000; + m_devSampleRateIndex = 0; m_LOppmTenths = 0; m_lnaGain = 1; m_mixerGain = 5; @@ -60,9 +60,9 @@ QByteArray AirspyInput::Settings::serialize() const data.m_data.m_frequency = m_centerFrequency; data.m_LOppmTenths = m_LOppmTenths; - data.m_sampleRate = m_devSampleRate; + data.m_sampleRateIndex = m_devSampleRateIndex; data.m_log2Decim = m_log2Decim; - data.m_fcPos = m_fcPos; + data.m_fcPos = (qint32) m_fcPos; data.m_lnaGain = m_lnaGain; data.m_mixerGain = m_mixerGain; data.m_vgaGain = m_vgaGain; @@ -83,9 +83,9 @@ bool AirspyInput::Settings::deserialize(const QByteArray& serializedData) m_centerFrequency = data.m_data.m_frequency; m_LOppmTenths = data.m_LOppmTenths; - m_devSampleRate = data.m_sampleRate; + m_devSampleRateIndex = data.m_sampleRateIndex; m_log2Decim = data.m_log2Decim; - m_fcPos = data.m_fcPos; + m_fcPos = (fcPos_t) data.m_fcPos; m_lnaGain = data.m_lnaGain; m_mixerGain = data.m_mixerGain; m_vgaGain = data.m_vgaGain; @@ -117,7 +117,7 @@ bool AirspyInput::start(int device) QMutexLocker mutexLocker(&m_mutex); airspy_error rc; - rc = airspy_init(); + rc = (airspy_error) airspy_init(); if (rc != AIRSPY_SUCCESS) { @@ -143,10 +143,10 @@ bool AirspyInput::start(int device) #ifdef LIBAIRSPY_OLD m_sampleRates.push_back(2500000); - m_sampleRates.push_back(10000000) + m_sampleRates.push_back(10000000); #else uint32_t nbSampleRates; - uint32_t sampleRates[]; + uint32_t *sampleRates; airspy_get_samplerates(m_dev, &nbSampleRates, 0); @@ -154,6 +154,12 @@ bool AirspyInput::start(int device) airspy_get_samplerates(m_dev, sampleRates, nbSampleRates); + if (nbSampleRates == 0) + { + qCritical("AirspyInput::start: could not obtain Airspy sample rates"); + return false; + } + for (int i=0; ipush(message); @@ -173,11 +189,14 @@ bool AirspyInput::start(int device) m_airspyThread->startWork(); mutexLocker.unlock(); - applySettings(m_settings, true); qDebug("AirspyInput::startInput: started"); return true; + +failed: + stop(); + return false; } void AirspyInput::stop() @@ -208,7 +227,7 @@ const QString& AirspyInput::getDeviceDescription() const int AirspyInput::getSampleRate() const { - int rate = m_settings.m_devSampleRate; + int rate = m_sampleRates[m_settings.m_devSampleRateIndex]; return (rate / (1<(freq_hz)); + + if (rc != AIRSPY_SUCCESS) + { + qWarning("AirspyInput::setCenterFrequency: could not frequency to %llu Hz", freq_hz); + } + else + { + qWarning("AirspyInput::setCenterFrequency: frequency set to %llu Hz", 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; - if ((m_settings.m_lnaGain != settings.m_lnaGain) || force) + if ((m_settings.m_devSampleRateIndex != settings.m_devSampleRateIndex) || force) { - m_settings.m_lnaGain = settings.m_lnaGain; - - if (m_dev != 0) + if (settings.m_devSampleRateIndex < m_sampleRates.size()) { - rc = airspy_set_lna_gain(m_dev, m_settings.m_lnaGain); - - if(rc != AIRSPY_SUCCESS) - { - qDebug("AirspyInput::applySettings: airspy_set_lna_gain failed: %s", airspy_error_name(rc)); - } - else - { - qDebug() << "AirspyInput:applySettings: LNA gain set to " << m_settings.m_lnaGain; - } + m_settings.m_devSampleRateIndex = settings.m_devSampleRateIndex; } - } - - if ((m_settings.m_mixerGain != settings.m_mixerGain) || force) - { - m_settings.m_mixerGain = settings.m_mixerGain; - - if (m_dev != 0) + else { - rc = airspy_set_mixer_gain(m_dev, m_settings.m_mixerGain); - - if(rc != AIRSPY_SUCCESS) - { - qDebug("AirspyInput::applySettings: airspy_set_mixer_gain failed: %s", airspy_error_name(rc)); - } - else - { - qDebug() << "AirspyInput:applySettings: mixer gain set to " << m_settings.m_mixerGain; - } + m_settings.m_devSampleRateIndex = m_sampleRates.size() - 1; } - } - if ((m_settings.m_vgaGain != settings.m_vgaGain) || force) - { - m_settings.m_vgaGain = settings.m_vgaGain; - - if (m_dev != 0) - { - rc = airspy_set_vga_gain(m_dev, m_settings.m_vgaGain); - - if(rc != AIRSPY_SUCCESS) - { - qDebug("AirspyInput::applySettings: airspy_set_vga_gain failed: %s", airspy_error_name(rc)); - } - else - { - qDebug() << "AirspyInput:applySettings: VGA gain set to " << m_settings.m_vgaGain; - } - } - } - - if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || force) - { - m_settings.m_devSampleRate = settings.m_devSampleRate; forwardChange = true; if (m_dev != 0) { - unsigned int actualSamplerate; + rc = (airspy_error) airspy_set_samplerate(m_dev, static_cast(m_sampleRates[m_settings.m_devSampleRateIndex])); - if (bladerf_set_sample_rate(m_dev, BLADERF_MODULE_RX, m_settings.m_devSampleRate, &actualSamplerate) < 0) + if (rc != AIRSPY_SUCCESS) { - qCritical("could not set sample rate: %d", m_settings.m_devSampleRate); + qCritical("AirspyInput::applySettings: could not set sample rate index %u (%d S/s): %s", m_settings.m_devSampleRateIndex, m_sampleRates[m_settings.m_devSampleRateIndex], airspy_error_name(rc)); } else { - qDebug() << "bladerf_set_sample_rate(BLADERF_MODULE_RX) actual sample rate is " << actualSamplerate; - m_airspyThread->setSamplerate(m_settings.m_devSampleRate); + qDebug("AirspyInput::applySettings: sample rate set to index: %u (%d S/s)", m_settings.m_devSampleRateIndex, m_sampleRates[m_settings.m_devSampleRateIndex]); + m_airspyThread->setSamplerate(m_sampleRates[m_settings.m_devSampleRateIndex]); } } } @@ -346,63 +336,126 @@ bool AirspyInput::applySettings(const Settings& settings, bool force) } } - if (m_settings.m_centerFrequency != settings.m_centerFrequency) + if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) { + m_settings.m_centerFrequency = settings.m_centerFrequency; + + if ((m_settings.m_log2Decim == 0) || (m_settings.m_fcPos == FC_POS_CENTER)) + { + deviceCenterFrequency = m_settings.m_centerFrequency; + f_img = deviceCenterFrequency; + } + else + { + if (m_settings.m_fcPos == FC_POS_INFRA) + { + deviceCenterFrequency = m_settings.m_centerFrequency + (devSampleRate / 4); + f_img = deviceCenterFrequency + devSampleRate/2; + } + else if (m_settings.m_fcPos == FC_POS_SUPRA) + { + deviceCenterFrequency = m_settings.m_centerFrequency - (devSampleRate / 4); + f_img = deviceCenterFrequency - devSampleRate/2; + } + } + + if (m_dev != 0) + { + setCenterFrequency(deviceCenterFrequency); + + qDebug() << "AirspyInput::applySettings: center freq: " << m_settings.m_centerFrequency << " Hz" + << " device center freq: " << deviceCenterFrequency << " Hz" + << " device sample rate: " << devSampleRate << "Hz" + << " Actual sample rate: " << devSampleRate/(1<push(notif); } - qDebug() << "AirspyInput::applySettings: center freq: " << m_settings.m_centerFrequency << " Hz" - << " device center freq: " << deviceCenterFrequency << " Hz" - << " device sample rate: " << m_settings.m_devSampleRate << "Hz" - << " Actual sample rate: " << m_settings.m_devSampleRate/(1<& getSampleRates() const { return m_sampleRates; } + const std::vector& getSampleRates() const { return m_sampleRates; } - static MsgReportAirspy* create(const std::vector& sampleRates) + static MsgReportAirspy* create(const std::vector& sampleRates) { return new MsgReportAirspy(sampleRates); } protected: - std::vector m_sampleRates; + std::vector m_sampleRates; - MsgReportAirspy(const std::vector& sampleRates) : + MsgReportAirspy(const std::vector& sampleRates) : Message(), m_sampleRates(sampleRates) { } @@ -104,13 +104,14 @@ public: private: bool applySettings(const Settings& settings, bool force); struct airspy_device *open_airspy_from_sequence(int sequence); + void setCenterFrequency(quint64 freq); QMutex m_mutex; Settings m_settings; struct airspy_device* m_dev; AirspyThread* m_airspyThread; QString m_deviceDescription; - std::vector m_sampleRates; + std::vector m_sampleRates; }; #endif // INCLUDE_AIRSPYINPUT_H diff --git a/plugins/samplesource/airspy/airspyplugin.cpp b/plugins/samplesource/airspy/airspyplugin.cpp index a5cd2cf0c..e5a0eaa6a 100644 --- a/plugins/samplesource/airspy/airspyplugin.cpp +++ b/plugins/samplesource/airspy/airspyplugin.cpp @@ -56,21 +56,20 @@ PluginInterface::SampleSourceDevices AirspyPlugin::enumSampleSources() struct airspy_device *devinfo = 0; airspy_error rc; - rc = airspy_init(); + rc = (airspy_error) airspy_init(); if (rc != AIRSPY_SUCCESS) { - qCritical() << "AirspyPlugin::enumSampleSources: failed to initiate Airspy library " - << airspy_error_name(rc) << std::endl; + qCritical("AirspyPlugin::enumSampleSources: failed to initiate Airspy library: %s", airspy_error_name(rc)); } for (int i=0; i < AIRSPY_MAX_DEVICE; i++) { - rc = airspy_open(&devinfo); + rc = (airspy_error) airspy_open(&devinfo); if (rc == AIRSPY_SUCCESS) { - rc = airspy_board_partid_serialno_read(devinfo, &read_partid_serialno); + rc = (airspy_error) airspy_board_partid_serialno_read(devinfo, &read_partid_serialno); if (rc != AIRSPY_SUCCESS) { @@ -78,7 +77,7 @@ PluginInterface::SampleSourceDevices AirspyPlugin::enumSampleSources() } 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 = (read_partid_serialno.serial_no[2] << 32) + read_partid_serialno.serial_no[3]; + 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); diff --git a/plugins/samplesource/airspy/airspyserializer.cpp b/plugins/samplesource/airspy/airspyserializer.cpp index d2a54ef48..9b29d2a04 100644 --- a/plugins/samplesource/airspy/airspyserializer.cpp +++ b/plugins/samplesource/airspy/airspyserializer.cpp @@ -25,9 +25,9 @@ void AirspySerializer::writeSerializedData(const AirspyData& data, QByteArray& s s.writeBlob(1, sampleSourceSerialized); s.writeS32(2, data.m_LOppmTenths); - s.writeS32(3, data.m_sampleRate); + s.writeU32(3, data.m_sampleRateIndex); s.writeU32(4, data.m_log2Decim); - s.writeU32(5, data.m_fcPos); + s.writeS32(5, data.m_fcPos); s.writeU32(6, data.m_lnaGain); s.writeU32(7, data.m_mixerGain); s.writeU32(8, data.m_vgaGain); @@ -56,9 +56,9 @@ bool AirspySerializer::readSerializedData(const QByteArray& serializedData, Airs d.readBlob(1, &sampleSourceSerialized); d.readS32(2, &data.m_LOppmTenths, 0); - d.readS32(3, &data.m_sampleRate, 0); + d.readU32(3, &data.m_sampleRateIndex, 0); d.readU32(4, &data.m_log2Decim, 0); - d.readU32(5, &data.m_fcPos, 0); + d.readS32(5, &data.m_fcPos, 0); d.readU32(6, &data.m_lnaGain, 1); d.readU32(7, &data.m_mixerGain, 5); d.readU32(8, &data.m_vgaGain, 5); @@ -76,7 +76,7 @@ bool AirspySerializer::readSerializedData(const QByteArray& serializedData, Airs void AirspySerializer::setDefaults(AirspyData& data) { data.m_LOppmTenths = 0; - data.m_sampleRate = 0; + data.m_sampleRateIndex = 0; data.m_log2Decim = 0; data.m_fcPos = 0; data.m_lnaGain = 1; diff --git a/plugins/samplesource/airspy/airspyserializer.h b/plugins/samplesource/airspy/airspyserializer.h index 6c0580fe1..eb6c1c8a2 100644 --- a/plugins/samplesource/airspy/airspyserializer.h +++ b/plugins/samplesource/airspy/airspyserializer.h @@ -26,9 +26,9 @@ public: { SampleSourceSerializer::Data m_data; qint32 m_LOppmTenths; - qint32 m_sampleRate; + quint32 m_sampleRateIndex; quint32 m_log2Decim; - quint32 m_fcPos; + qint32 m_fcPos; quint32 m_lnaGain; quint32 m_mixerGain; quint32 m_vgaGain; diff --git a/plugins/samplesource/airspy/airspythread.cpp b/plugins/samplesource/airspy/airspythread.cpp index a8d16d4b5..396ca8be0 100644 --- a/plugins/samplesource/airspy/airspythread.cpp +++ b/plugins/samplesource/airspy/airspythread.cpp @@ -20,9 +20,9 @@ #include "airspythread.h" #include "dsp/samplefifo.h" +AirspyThread *airspyThread = 0; - -AirspyThread::AirspyThread(struct bladerf* dev, SampleFifo* sampleFifo, QObject* parent) : +AirspyThread::AirspyThread(struct airspy_device* dev, SampleFifo* sampleFifo, QObject* parent) : QThread(parent), m_running(false), m_dev(dev), @@ -32,11 +32,13 @@ AirspyThread::AirspyThread(struct bladerf* dev, SampleFifo* sampleFifo, QObject* m_log2Decim(0), m_fcPos(0) { + airspyThread = this; } AirspyThread::~AirspyThread() { stopWork(); + airspyThread = 0; } void AirspyThread::startWork() @@ -54,7 +56,7 @@ void AirspyThread::stopWork() wait(); } -void AirspyThread::setSamplerate(int samplerate) +void AirspyThread::setSamplerate(uint32_t samplerate) { m_samplerate = samplerate; } @@ -71,18 +73,23 @@ void AirspyThread::setFcPos(int fcPos) void AirspyThread::run() { - int res; + airspy_error rc; m_running = true; m_startWaiter.wakeAll(); - while(m_running) { - if((res = bladerf_sync_rx(m_dev, m_buf, AIRSPY_BLOCKSIZE, NULL, 10000)) < 0) { - qCritical("AirspyThread: sync error: %s", strerror(errno)); - break; - } + rc = (airspy_error) airspy_start_rx(m_dev, rx_callback, NULL); - callback(m_buf, 2 * AIRSPY_BLOCKSIZE); + if (rc != AIRSPY_SUCCESS) + { + qCritical("AirspyInput::run: failed to start Airspy Rx: %s", airspy_error_name(rc)); + } + else + { + while ((m_running) && (airspy_is_streaming(m_dev) == AIRSPY_TRUE)) + { + sleep(1); + } } m_running = false; @@ -173,3 +180,10 @@ 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; + airspyThread->callback((qint16 *) transfer->samples, bytes_to_write); +} diff --git a/plugins/samplesource/airspy/airspythread.h b/plugins/samplesource/airspy/airspythread.h index 8849a928e..41db97862 100644 --- a/plugins/samplesource/airspy/airspythread.h +++ b/plugins/samplesource/airspy/airspythread.h @@ -30,12 +30,12 @@ class AirspyThread : public QThread { Q_OBJECT public: - AirspyThread(struct bladerf* dev, SampleFifo* sampleFifo, QObject* parent = NULL); + AirspyThread(struct airspy_device* dev, SampleFifo* sampleFifo, QObject* parent = NULL); ~AirspyThread(); void startWork(); void stopWork(); - void setSamplerate(int samplerate); + void setSamplerate(uint32_t samplerate); void setLog2Decimation(unsigned int log2_decim); void setFcPos(int fcPos); @@ -44,7 +44,7 @@ private: QWaitCondition m_startWaiter; bool m_running; - struct bladerf* m_dev; + struct airspy_device* m_dev; qint16 m_buf[2*AIRSPY_BLOCKSIZE]; SampleVector m_convertBuffer; SampleFifo* m_sampleFifo; @@ -57,6 +57,7 @@ private: void run(); void callback(const qint16* buf, qint32 len); + static int rx_callback(airspy_transfer_t* transfer); }; #endif // INCLUDE_AIRSPYTHREAD_H