diff --git a/plugins/samplesource/CMakeLists.txt b/plugins/samplesource/CMakeLists.txt index 30b7a158d..fd11148a9 100644 --- a/plugins/samplesource/CMakeLists.txt +++ b/plugins/samplesource/CMakeLists.txt @@ -50,6 +50,11 @@ else(LIBUSB_FOUND AND LIBMIRISDR_FOUND) message(STATUS "LibMiriSDR NOT found") endif(LIBUSB_FOUND AND LIBMIRISDR_FOUND) +find_package(LimeSuite) +if(LIBUSB_FOUND AND LIMESUITE_FOUND) + add_subdirectory(limesdrinput) +endif(LIBUSB_FOUND AND LIMESUITE_FOUND) + find_package(LZ4) find_package(LibNANOMSG) if(LIBNANOMSG_FOUND AND LIBLZ4_FOUND) @@ -70,6 +75,7 @@ if (BUILD_DEBIAN) add_subdirectory(rtlsdr) add_subdirectory(bladerfinput) add_subdirectory(sdrplay) + add_subdirectory(limesdrinput) endif (BUILD_DEBIAN) add_subdirectory(filesource) diff --git a/plugins/samplesource/limesdrinput/CMakeLists.txt b/plugins/samplesource/limesdrinput/CMakeLists.txt new file mode 100644 index 000000000..ed234ab18 --- /dev/null +++ b/plugins/samplesource/limesdrinput/CMakeLists.txt @@ -0,0 +1,72 @@ +project(limesdrinput) + +set(limesdrinput_SOURCES + limesdrinputgui.cpp + limesdrinput.cpp + limesdrinputplugin.cpp + limesdrinputsettings.cpp + limesdrinputthread.cpp +) + +set(limesdrinput_HEADERS + limesdrinputgui.h + limesdrinput.h + limesdrinputplugin.h + limesdrinputsettings.h + limesdrinputthread.h +) + +set(limesdrinput_FORMS + limesdrinputgui.ui +) + +if (BUILD_DEBIAN) +include_directories( + . + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/devices + ${LIBBLADERFLIBSRC}/include + ${LIBBLADERFLIBSRC}/src +) +else (BUILD_DEBIAN) +include_directories( + . + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/devices + ${LIMESUITE_INCLUDE_DIR} +) +endif (BUILD_DEBIAN) + +#include(${QT_USE_FILE}) +add_definitions(${QT_DEFINITIONS}) +add_definitions(-DQT_PLUGIN) +add_definitions(-DQT_SHARED) + +#qt4_wrap_cpp(limesdrinput_HEADERS_MOC ${limesdrinput_HEADERS}) +qt5_wrap_ui(limesdrinput_FORMS_HEADERS ${limesdrinput_FORMS}) + +add_library(inputlimesdr SHARED + ${limesdrinput_SOURCES} + ${limesdrinput_HEADERS_MOC} + ${limesdrinput_FORMS_HEADERS} +) + +if (BUILD_DEBIAN) +target_link_libraries(inputlimesdr + ${QT_LIBRARIES} + limesdr + sdrbase + limesdrdevice +) +else (BUILD_DEBIAN) +target_link_libraries(inputlimesdr + ${QT_LIBRARIES} + ${LIMESUITE_LIBRARY} + sdrbase + limesdrdevice +) +endif (BUILD_DEBIAN) + +qt5_use_modules(inputlimesdr Core Widgets) + +install(TARGETS inputlimesdr DESTINATION lib/plugins/samplesource) diff --git a/plugins/samplesource/limesdrinput/limesdrinput.cpp b/plugins/samplesource/limesdrinput/limesdrinput.cpp index 0bf5be161..47e1c1dcf 100644 --- a/plugins/samplesource/limesdrinput/limesdrinput.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinput.cpp @@ -19,7 +19,10 @@ #include #include "lime/LimeSuite.h" +#include "device/devicesourceapi.h" +#include "device/devicesinkapi.h" #include "limesdrinput.h" +#include "limesdrinputthread.h" #include "limesdr/devicelimesdrparam.h" @@ -45,8 +48,8 @@ bool LimeSDRInput::openDevice() // if there is a channel left take the first available if (m_deviceAPI->getSourceBuddies().size() > 0) // look source sibling first { - DeviceSinkAPI *sourceBuddy = m_deviceAPI->getSourceBuddies()[0]; - m_deviceShared = *(sourceBuddy->getBuddySharedPtr()); // copy shared data + DeviceSourceAPI *sourceBuddy = m_deviceAPI->getSourceBuddies()[0]; + m_deviceShared = *((DeviceLimeSDRShared *) sourceBuddy->getBuddySharedPtr()); // copy shared data DeviceLimeSDRParams *deviceParams = m_deviceShared.m_deviceParams; // get device parameters if (deviceParams == 0) @@ -65,8 +68,8 @@ bool LimeSDRInput::openDevice() for (int i = 0; i < m_deviceAPI->getSourceBuddies().size(); i++) { - DeviceSinkAPI *buddy = m_deviceAPI->getSourceBuddies()[i]; - DeviceLimeSDRShared *buddyShared = buddy->getBuddySharedPtr(); + DeviceSourceAPI *buddy = m_deviceAPI->getSourceBuddies()[i]; + DeviceLimeSDRShared *buddyShared = (DeviceLimeSDRShared *) buddy->getBuddySharedPtr(); busyChannels[buddyShared->m_channel] = 1; } @@ -87,7 +90,7 @@ bool LimeSDRInput::openDevice() else if (m_deviceAPI->getSinkBuddies().size() > 0) // then sink { DeviceSinkAPI *sinkBuddy = m_deviceAPI->getSinkBuddies()[0]; - m_deviceShared = *(sinkBuddy->getBuddySharedPtr()); // copy parameters + m_deviceShared = *((DeviceLimeSDRShared *) sinkBuddy->getBuddySharedPtr()); // copy parameters if (m_deviceShared.m_deviceParams == 0) { @@ -103,7 +106,9 @@ bool LimeSDRInput::openDevice() else { m_deviceShared.m_deviceParams = new DeviceLimeSDRParams(); - m_deviceShared.m_deviceParams->open((lms_info_str_t) qPrintable(m_deviceAPI->getSampleSourceSerial())); + char serial[256]; + strcpy(serial, qPrintable(m_deviceAPI->getSampleSourceSerial())); + m_deviceShared.m_deviceParams->open(serial); m_deviceShared.m_channel = 0; // take first channel } @@ -113,7 +118,7 @@ bool LimeSDRInput::openDevice() if (LMS_EnableChannel(m_deviceShared.m_deviceParams->getDevice(), LMS_CH_RX, m_deviceShared.m_channel, true) != 0) { - qCritical("LimeSDRInput::openDevice: cannot enable Rx channel %u", m_deviceShared.m_channel); + qCritical("LimeSDRInput::openDevice: cannot enable Rx channel %lu", m_deviceShared.m_channel); return false; } @@ -126,7 +131,7 @@ void LimeSDRInput::closeDevice() if (LMS_EnableChannel(m_deviceShared.m_deviceParams->getDevice(), LMS_CH_RX, m_deviceShared.m_channel, false) != 0) { - qWarning("LimeSDRInput::closeDevice: cannot disable Rx channel %u", m_deviceShared.m_channel); + qWarning("LimeSDRInput::closeDevice: cannot disable Rx channel %lu", m_deviceShared.m_channel); } m_deviceShared.m_channel = -1; @@ -159,7 +164,7 @@ bool LimeSDRInput::start() if (LMS_SetupStream(m_deviceShared.m_deviceParams->getDevice(), &m_streamId) != 0) { - qCritical("LimeSDRInput::start: cannot setup the stream on Rx channel %u", m_deviceShared.m_channel); + qCritical("LimeSDRInput::start: cannot setup the stream on Rx channel %lu", m_deviceShared.m_channel); return false; } @@ -198,6 +203,11 @@ void LimeSDRInput::stop() m_running = false; } +std::size_t LimeSDRInput::getChannelIndex() +{ + return m_deviceShared.m_channel; +} + void LimeSDRInput::getLORange(float& minF, float& maxF, float& stepF) const { lms_range_t range = m_deviceShared.m_deviceParams->m_loRangeRx; @@ -222,4 +232,14 @@ void LimeSDRInput::getLPRange(float& minF, float& maxF, float& stepF) const stepF = range.step; } +int LimeSDRInput::getLPIndex(float lpfBW) const +{ + lms_range_t range = m_deviceShared.m_deviceParams->m_lpfRangeRx; + return (int) ((lpfBW - range.min) / range.step); +} + +uint32_t LimeSDRInput::getHWLog2Decim() const +{ + return m_deviceShared.m_deviceParams->m_log2OvSRRx; +} diff --git a/plugins/samplesource/limesdrinput/limesdrinput.h b/plugins/samplesource/limesdrinput/limesdrinput.h index c96977225..64e16f656 100644 --- a/plugins/samplesource/limesdrinput/limesdrinput.h +++ b/plugins/samplesource/limesdrinput/limesdrinput.h @@ -18,6 +18,8 @@ #define PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUT_H_ #include +#include + #include "dsp/devicesamplesource.h" #include "limesdr/devicelimesdrshared.h" #include "limesdrinputsettings.h" @@ -29,6 +31,26 @@ struct DeviceLimeSDRParams; class LimeSDRInput : public DeviceSampleSource { public: + class MsgConfigureLimeSDR : public Message { + MESSAGE_CLASS_DECLARATION + + public: + const LimeSDRInputSettings& getSettings() const { return m_settings; } + + static MsgConfigureLimeSDR* create(const LimeSDRInputSettings& settings) + { + return new MsgConfigureLimeSDR(settings); + } + + private: + LimeSDRInputSettings m_settings; + + MsgConfigureLimeSDR(const LimeSDRInputSettings& settings) : + Message(), + m_settings(settings) + { } + }; + LimeSDRInput(DeviceSourceAPI *deviceAPI); virtual ~LimeSDRInput(); @@ -41,9 +63,12 @@ public: virtual bool handleMessage(const Message& message); + std::size_t getChannelIndex(); void getLORange(float& minF, float& maxF, float& stepF) const; void getSRRange(float& minF, float& maxF, float& stepF) const; void getLPRange(float& minF, float& maxF, float& stepF) const; + int getLPIndex(float lpfBW) const; + uint32_t getHWLog2Decim() const; private: DeviceSourceAPI *m_deviceAPI; diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.cpp b/plugins/samplesource/limesdrinput/limesdrinputgui.cpp index fa93e9307..caa64f6ba 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.cpp @@ -29,7 +29,7 @@ LimeSDRInputGUI::LimeSDRInputGUI(DeviceSourceAPI *deviceAPI, QWidget* parent) : QWidget(parent), - ui(new Ui::BladerfInputGui), + ui(new Ui::LimeSDRInputGUI), m_deviceAPI(deviceAPI), m_settings(), m_sampleSource(0), @@ -59,6 +59,8 @@ LimeSDRInputGUI::LimeSDRInputGUI(DeviceSourceAPI *deviceAPI, QWidget* parent) : ui->lpf->setMinimum(minLP); ui->lpf->setMaximum(maxLP); + ui->channelNumberText->setText(tr("#%1").arg(m_limeSDRInput->getChannelIndex())); + connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); m_statusTimer.start(500); @@ -70,7 +72,7 @@ LimeSDRInputGUI::LimeSDRInputGUI(DeviceSourceAPI *deviceAPI, QWidget* parent) : m_fileSink = new FileRecord(std::string(recFileNameCStr)); m_deviceAPI->addSink(m_fileSink); - connect(m_deviceAPI->getDeviceOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleDSPMessages()), Qt::QueuedConnection); + connect(m_deviceAPI->getDeviceOutputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleMessagesToUI()), Qt::QueuedConnection); } LimeSDRInputGUI::~LimeSDRInputGUI() @@ -81,5 +83,148 @@ LimeSDRInputGUI::~LimeSDRInputGUI() delete ui; } +void LimeSDRInputGUI::destroy() +{ + delete this; +} +void LimeSDRInputGUI::setName(const QString& name) +{ + setObjectName(name); +} + +QString LimeSDRInputGUI::getName() const +{ + return objectName(); +} + +void LimeSDRInputGUI::resetToDefaults() +{ + m_settings.resetToDefaults(); + displaySettings(); + sendSettings(); +} + +qint64 LimeSDRInputGUI::getCenterFrequency() const +{ + return m_settings.m_centerFrequency; +} + +void LimeSDRInputGUI::setCenterFrequency(qint64 centerFrequency) +{ + m_settings.m_centerFrequency = centerFrequency; + displaySettings(); + sendSettings(); +} + +QByteArray LimeSDRInputGUI::serialize() const +{ + return m_settings.serialize(); +} + +bool LimeSDRInputGUI::deserialize(const QByteArray& data) +{ + if(m_settings.deserialize(data)) { + displaySettings(); + sendSettings(); + return true; + } else { + resetToDefaults(); + return false; + } +} + +void LimeSDRInputGUI::handleMessagesToUI() +{ + Message* message; + + while ((message = m_deviceAPI->getDeviceOutputMessageQueue()->pop()) != 0) + { + qDebug("LimeSDRInputGUI::handleDSPMessages: message: %s", message->getIdentifier()); + + if (DSPSignalNotification::match(*message)) + { + DSPSignalNotification* notif = (DSPSignalNotification*) message; + m_sampleRate = notif->getSampleRate(); + m_deviceCenterFrequency = notif->getCenterFrequency(); + qDebug("BladerfGui::handleDSPMessages: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency()); + updateSampleRateAndFrequency(); + m_fileSink->handleMessage(*notif); // forward to file sink + + delete message; + } + } +} + +void LimeSDRInputGUI::updateSampleRateAndFrequency() +{ + m_deviceAPI->getSpectrum()->setSampleRate(m_sampleRate); + m_deviceAPI->getSpectrum()->setCenterFrequency(m_deviceCenterFrequency); + ui->deviceRateLabel->setText(tr("%1k").arg(QString::number(m_sampleRate / 1000.0f, 'g', 5))); +} + +void LimeSDRInputGUI::displaySettings() +{ + ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000); + ui->sampleRate->setValue(m_settings.m_devSampleRate); + + ui->dcOffset->setChecked(m_settings.m_dcBlock); + ui->iqImbalance->setChecked(m_settings.m_iqCorrection); + + ui->hwDecim->setCurrentIndex(m_settings.m_log2HardDecim); + ui->swDecim->setCurrentIndex(m_settings.m_log2SoftDecim); + ui->fcPos->setCurrentIndex((int) m_settings.m_fcPos); + + ui->lpf->setValue(m_limeSDRInput->getLPIndex(m_settings.m_lpfFIRBW)); + ui->lpfText->setText(tr("%1k").arg(QString::number(m_settings.m_lpfFIRBW / 1000.0f, 'f', 0))); + + ui->lpFIREnable->setChecked(m_settings.m_lpfFIREnable); + ui->sampleRate->setValue(m_settings.m_lpfFIRBW); + + ui->gain->setValue(m_settings.m_gain); + ui->gainText->setText(tr("%1dB").arg(m_settings.m_gain)); +} + +void LimeSDRInputGUI::sendSettings() +{ + if(!m_updateTimer.isActive()) + m_updateTimer.start(100); +} + +void LimeSDRInputGUI::updateHardware() +{ + qDebug() << "BladerfGui::updateHardware"; + LimeSDRInput::MsgConfigureLimeSDR* message = LimeSDRInput::MsgConfigureLimeSDR::create( m_settings); + m_sampleSource->getInputMessageQueue()->push(message); + m_updateTimer.stop(); +} + +void LimeSDRInputGUI::updateStatus() +{ + int state = m_deviceAPI->state(); + + if(m_lastEngineState != state) + { + switch(state) + { + case DSPDeviceSourceEngine::StNotStarted: + ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); + break; + case DSPDeviceSourceEngine::StIdle: + ui->startStop->setStyleSheet("QToolButton { background-color : blue; }"); + break; + case DSPDeviceSourceEngine::StRunning: + ui->startStop->setStyleSheet("QToolButton { background-color : green; }"); + break; + case DSPDeviceSourceEngine::StError: + ui->startStop->setStyleSheet("QToolButton { background-color : red; }"); + QMessageBox::information(this, tr("Message"), m_deviceAPI->errorMessage()); + break; + default: + break; + } + + m_lastEngineState = state; + } +} diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.h b/plugins/samplesource/limesdrinput/limesdrinputgui.h index c8bc2a581..c067a2172 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.h +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.h @@ -18,15 +18,15 @@ #define PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUTGUI_H_ #include -#include "plugin/plugingui.h" +#include "plugin/plugingui.h" #include "limesdrinput.h" class DeviceSourceAPI; class FileRecord; namespace Ui { - class LimeSDRInputGui; + class LimeSDRInputGUI; } class LimeSDRInputGUI : public QWidget, public PluginGUI { @@ -48,7 +48,7 @@ public: virtual bool handleMessage(const Message& message); private: - Ui::LimeSDRInputGui* ui; + Ui::LimeSDRInputGUI* ui; DeviceSourceAPI* m_deviceAPI; LimeSDRInput* m_limeSDRInput; //!< Same object as above but gives easy access to LimeSDRInput methods and attributes that are used intensively @@ -66,7 +66,7 @@ private: void updateSampleRateAndFrequency(); private slots: - void handleDSPMessages(); + void handleMessagesToUI(); void on_startStop_toggled(bool checked); void on_record_toggled(bool checked); diff --git a/plugins/samplesource/limesdrinput/limesdrinputgui.ui b/plugins/samplesource/limesdrinput/limesdrinputgui.ui index bd8921974..822ef9af6 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputgui.ui +++ b/plugins/samplesource/limesdrinput/limesdrinputgui.ui @@ -1,7 +1,7 @@ - LimeSDRInputGui - + LimeSDRInputGUI + 0 @@ -168,6 +168,25 @@ + + + + + 20 + 0 + + + + Channel number + + + #0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + diff --git a/plugins/samplesource/limesdrinput/limesdrinputplugin.cpp b/plugins/samplesource/limesdrinput/limesdrinputplugin.cpp index 9c7c3043f..0c300d483 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputplugin.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputplugin.cpp @@ -95,7 +95,7 @@ PluginGUI* LimeSDRInputPlugin::createSampleSourcePluginGUI(const QString& source { if(sourceId == m_deviceTypeID) { - LimeSDRInputGui* gui = new LimeSDRInputGui(deviceAPI); + LimeSDRInputGUI* gui = new LimeSDRInputGUI(deviceAPI); *widget = gui; return gui; } diff --git a/plugins/samplesource/limesdrinput/limesdrinputsettings.cpp b/plugins/samplesource/limesdrinput/limesdrinputsettings.cpp index 4478aa664..6a8d45c7b 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputsettings.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputsettings.cpp @@ -14,6 +14,7 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// +#include "util/simpleserializer.h" #include "limesdrinputsettings.h" LimeSDRInputSettings::LimeSDRInputSettings() diff --git a/plugins/samplesource/limesdrinput/limesdrinputsettings.h b/plugins/samplesource/limesdrinput/limesdrinputsettings.h index 3b5d0b4d6..c87f84291 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputsettings.h +++ b/plugins/samplesource/limesdrinput/limesdrinputsettings.h @@ -17,6 +17,7 @@ #ifndef PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUTSETTINGS_H_ #define PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUTSETTINGS_H_ +#include #include /** @@ -32,8 +33,8 @@ struct LimeSDRInputSettings } fcPos_t; // global settings to be saved - quint64 m_centerFrequency; - qint32 m_devSampleRate; + uint64_t m_centerFrequency; + int m_devSampleRate; uint32_t m_log2HardDecim; // channel settings bool m_dcBlock; diff --git a/plugins/samplesource/limesdrinput/limesdrinputthread.cpp b/plugins/samplesource/limesdrinput/limesdrinputthread.cpp index 368cb8e79..4b8126d6c 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputthread.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinputthread.cpp @@ -14,6 +14,8 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// +#include + #include "limesdrinputthread.h" LimeSDRInputThread::LimeSDRInputThread(lms_stream_t* stream, SampleSinkFifo* sampleFifo, QObject* parent) : diff --git a/plugins/samplesource/limesdrinput/limesdrinputthread.h b/plugins/samplesource/limesdrinput/limesdrinputthread.h index 5dda4ef11..21c1b7915 100644 --- a/plugins/samplesource/limesdrinput/limesdrinputthread.h +++ b/plugins/samplesource/limesdrinput/limesdrinputthread.h @@ -21,6 +21,8 @@ #include #include +#include "lime/LimeSuite.h" + #include "dsp/samplesinkfifo.h" #include "dsp/decimators.h"