From 527b5ef2f52659b9606a207689151b012ca7e67f Mon Sep 17 00:00:00 2001 From: f4exb Date: Thu, 13 Apr 2017 18:18:15 +0200 Subject: [PATCH] LimeSDR support (6) --- devices/limesdr/devicelimesdrparam.cpp | 9 +- devices/limesdr/devicelimesdrparam.h | 147 ++++++++--------- .../limesdrinput/limesdrinput.cpp | 153 ++++++++++++++++++ .../samplesource/limesdrinput/limesdrinput.h | 58 +++++++ .../limesdrinput/limesdrinputsettings.h | 25 +++ 5 files changed, 315 insertions(+), 77 deletions(-) create mode 100644 plugins/samplesource/limesdrinput/limesdrinput.cpp create mode 100644 plugins/samplesource/limesdrinput/limesdrinput.h create mode 100644 plugins/samplesource/limesdrinput/limesdrinputsettings.h diff --git a/devices/limesdr/devicelimesdrparam.cpp b/devices/limesdr/devicelimesdrparam.cpp index 36ec4bfe0..e4f174a97 100644 --- a/devices/limesdr/devicelimesdrparam.cpp +++ b/devices/limesdr/devicelimesdrparam.cpp @@ -94,5 +94,12 @@ bool DeviceLimeSDRParams::open(lms_info_str_t deviceStr) return true; } - +void DeviceLimeSDRParams::close() +{ + if (m_dev) + { + LMS_Close(m_dev); + m_dev = 0; + } +} diff --git a/devices/limesdr/devicelimesdrparam.h b/devices/limesdr/devicelimesdrparam.h index 9ef163f69..6138b0b80 100644 --- a/devices/limesdr/devicelimesdrparam.h +++ b/devices/limesdr/devicelimesdrparam.h @@ -1,76 +1,71 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2017 Edouard Griffiths, F4EXB // -// // -// This program 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 as version 3 of the License, or // -// // -// This program 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 V3 for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program. If not, see . // -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef DEVICES_LIMESDR_DEVICELIMESDRPARAM_H_ -#define DEVICES_LIMESDR_DEVICELIMESDRPARAM_H_ - -#include "lime/LimeSuite.h" - -/** - * This structure refers to one physical device shared among parties (logical devices represented by - * the DeviceSinkAPI or DeviceSourceAPI). - * It allows storing information on the common resources in one place and is shared among participants. - * There is only one copy that is constructed by the first participant and destroyed by the last. - * A participant knows it is the first or last by checking the lists of buddies (Rx + Tx). - */ -struct DeviceLimeSDRParams -{ - lms_device_t *m_dev; //!< device handle if the party has ownership else 0 - int m_nbRxChannels; //!< number of Rx channels (normally 2, we'll see if we really use it...) - int m_nbTxChannels; //!< number of Tx channels (normally 2, we'll see if we really use it...) - lms_range_t m_lpfRangeRx; //!< Low pass filter range information (Rx side) - lms_range_t m_lpfRangeTx; //!< Low pass filter range information (Tx side) - lms_range_t m_loRangeRx; //!< LO range for Rx - lms_range_t m_loRangeTx; //!< LO range for Tx - lms_range_t m_srRangeRx; //!< ADC sample rate range - lms_range_t m_srRangeTx; //!< DAC sample rate range - float m_sampleRate; //!< ADC/DAC sample rate - int m_log2OvSRRx; //!< log2 of Rx oversampling (0..5) - int m_log2OvSRTx; //!< log2 of Tx oversampling (0..5) - float m_rxFrequency; //!< Rx frequency - float m_txFrequency; //!< Tx frequency - - DeviceLimeSDRParams() : - m_dev(0), - m_nbRxChannels(0), - m_nbTxChannels(0), - m_sampleRate(1e6), - m_log2OvSRRx(0), - m_log2OvSRTx(0), - m_rxFrequency(1e6), - m_txFrequency(1e6) - { - } - - /** - * Opens and initialize the device and obtain information (# channels, ranges, ...) - */ - bool open(lms_info_str_t deviceStr); - - ~DeviceLimeSDRParams() - { - if (m_dev) - { - LMS_Close(m_dev); - m_dev = 0; - } - } - -private: - void close(); -}; - -#endif /* DEVICES_LIMESDR_DEVICELIMESDRPARAM_H_ */ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017 Edouard Griffiths, F4EXB // +// // +// This program 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 as version 3 of the License, or // +// // +// This program 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 V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef DEVICES_LIMESDR_DEVICELIMESDRPARAM_H_ +#define DEVICES_LIMESDR_DEVICELIMESDRPARAM_H_ + +#include "lime/LimeSuite.h" + +/** + * This structure refers to one physical device shared among parties (logical devices represented by + * the DeviceSinkAPI or DeviceSourceAPI). + * It allows storing information on the common resources in one place and is shared among participants. + * There is only one copy that is constructed by the first participant and destroyed by the last. + * A participant knows it is the first or last by checking the lists of buddies (Rx + Tx). + */ +struct DeviceLimeSDRParams +{ + lms_device_t *m_dev; //!< device handle if the party has ownership else 0 + int m_channel; //!< logical device channel number (-1 if none) + int m_nbRxChannels; //!< number of Rx channels (normally 2, we'll see if we really use it...) + int m_nbTxChannels; //!< number of Tx channels (normally 2, we'll see if we really use it...) + lms_range_t m_lpfRangeRx; //!< Low pass filter range information (Rx side) + lms_range_t m_lpfRangeTx; //!< Low pass filter range information (Tx side) + lms_range_t m_loRangeRx; //!< LO range for Rx + lms_range_t m_loRangeTx; //!< LO range for Tx + lms_range_t m_srRangeRx; //!< ADC sample rate range + lms_range_t m_srRangeTx; //!< DAC sample rate range + float m_sampleRate; //!< ADC/DAC sample rate + int m_log2OvSRRx; //!< log2 of Rx oversampling (0..5) + int m_log2OvSRTx; //!< log2 of Tx oversampling (0..5) + float m_rxFrequency; //!< Rx frequency + float m_txFrequency; //!< Tx frequency + + DeviceLimeSDRParams() : + m_dev(0), + m_channel(-1), + m_nbRxChannels(0), + m_nbTxChannels(0), + m_sampleRate(1e6), + m_log2OvSRRx(0), + m_log2OvSRTx(0), + m_rxFrequency(1e6), + m_txFrequency(1e6) + { + } + + /** + * Opens and initialize the device and obtain information (# channels, ranges, ...) + */ + bool open(lms_info_str_t deviceStr); + void close(); + + ~DeviceLimeSDRParams() + { + } +}; + +#endif /* DEVICES_LIMESDR_DEVICELIMESDRPARAM_H_ */ diff --git a/plugins/samplesource/limesdrinput/limesdrinput.cpp b/plugins/samplesource/limesdrinput/limesdrinput.cpp new file mode 100644 index 000000000..65d1a9223 --- /dev/null +++ b/plugins/samplesource/limesdrinput/limesdrinput.cpp @@ -0,0 +1,153 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017 Edouard Griffiths, F4EXB // +// // +// This program 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 as version 3 of the License, or // +// // +// This program 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 V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "limesdrinput.h" + + +LimeSDRInput::LimeSDRInput(DeviceSourceAPI *deviceAPI) : + m_deviceAPI(deviceAPI), + m_settings(), + m_limeSDRInputThread(0), + m_deviceDescription(), + m_running(false) +{ + openDevice(); +} + +LimeSDRInput::~LimeSDRInput() +{ + if (m_running) stop(); + closeDevice(); +} + +bool LimeSDRInput::openDevice() +{ + // look for Rx buddies and get reference to common parameters + // 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_deviceParams = *(sourceBuddy->getBuddySharedPtr()); // copy parameters + + if (m_deviceAPI->getSourceBuddies().size() == m_deviceParams.m_nbRxChannels) + { + return false; // no more Rx channels available in device + } + // look for unused channel number + char *busyChannels = new char[m_deviceParams.m_nbRxChannels]; + memset(busyChannels, 0, m_deviceParams.m_nbRxChannels); + + for (int i = 0; i < m_deviceAPI->getSourceBuddies().size(); i++) + { + DeviceSinkAPI *buddy = m_deviceAPI->getSourceBuddies()[i]; + DeviceLimeSDRParams *buddyParms = buddy->getBuddySharedPtr(); + busyChannels[buddyParms->m_channel] = 1; + } + + int ch = 0; + + for (;ch < m_deviceParams.m_nbRxChannels; ch++) + { + if (busyChannels[ch] == 0) { + break; // first available is the good one + } + } + + m_deviceParams.m_channel = ch; + delete[] busyChannels; + } + // look for Tx buddies and get reference to common parameters + // take the first Rx channel + else if (m_deviceAPI->getSinkBuddies().size() > 0) // then sink + { + DeviceSinkAPI *sinkBuddy = m_deviceAPI->getSinkBuddies()[0]; + m_deviceParams = *(sinkBuddy->getBuddySharedPtr()); // copy parameters + m_deviceParams.m_channel = 0; // take first channel + } + // There are no buddies then create the first LimeSDR common parameters + // open the device this will also populate common fields + // take the first Rx channel + else + { + m_deviceParams.open((lms_info_str_t) qPrintable(m_deviceAPI->getSampleSourceSerial())); + m_deviceParams.m_channel = 0; // take first channel + } + + m_deviceAPI->setBuddySharedPtr(&m_deviceParams); // propagate common parameters to API + + // TODO: acquire the channel + + return true; +} + +void LimeSDRInput::closeDevice() +{ + // TODO: release the channel + + // No buddies effectively close the device + if ((m_deviceAPI->getSinkBuddies().size() == 0) && (m_deviceAPI->getSourceBuddies().size() == 0)) + { + m_deviceParams.close(); + } +} + +bool LimeSDRInput::start(int device) +{ + QMutexLocker mutexLocker(&m_mutex); + + if (!m_deviceParams.m_dev) { + return false; + } + + if (m_running) stop(); + + if ((m_limeSDRInputThread = new LimeSDRInputThread(m_deviceParams.m_dev, &m_sampleFifo)) == 0) + { + qFatal("LimeSDRInput::start: out of memory"); + stop(); + return false; + } + + m_limeSDRInputThread->setSamplerate(m_settings.m_devSampleRate); + m_limeSDRInputThread->setLog2Decimation(m_settings.m_log2Decim); + m_limeSDRInputThread->setFcPos((int) m_settings.m_fcPos); + + m_limeSDRInputThread->startWork(); + + mutexLocker.unlock(); + + applySettings(m_settings, true); + m_running = true; + + return true; +} + +void LimeSDRInput::stop() +{ + QMutexLocker mutexLocker(&m_mutex); + + if (m_limeSDRInputThread != 0) + { + m_limeSDRInputThread->stopWork(); + delete m_limeSDRInputThread; + m_limeSDRInputThread = 0; + } + + m_running = false; +} + diff --git a/plugins/samplesource/limesdrinput/limesdrinput.h b/plugins/samplesource/limesdrinput/limesdrinput.h new file mode 100644 index 000000000..647621b08 --- /dev/null +++ b/plugins/samplesource/limesdrinput/limesdrinput.h @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017 Edouard Griffiths, F4EXB // +// // +// This program 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 as version 3 of the License, or // +// // +// This program 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 V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUT_H_ +#define PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUT_H_ + +#include +#include "dsp/devicesamplesource.h" +#include "limesdr/devicelimesdrparam.h" +#include "limesdrinputsettings.h" + +class DeviceSourceAPI; +class LimeSDRInputThread; +struct DeviceLimeSDRParams; + +class LimeSDRInput : public DeviceSampleSource +{ +public: + LimeSDRInput(DeviceSourceAPI *deviceAPI); + virtual ~LimeSDRInput(); + + virtual bool start(int device); + virtual void stop(); + + virtual const QString& getDeviceDescription() const; + virtual int getSampleRate() const; + virtual quint64 getCenterFrequency() const; + + virtual bool handleMessage(const Message& message); + +private: + DeviceSourceAPI *m_deviceAPI; + QMutex m_mutex; + LimeSDRInputSettings m_settings; + LimeSDRInputThread* m_limeSDRInputThread; + QString m_deviceDescription; + bool m_running; + DeviceLimeSDRParams m_deviceParams; + + bool openDevice(); + void closeDevice(); + bool applySettings(const LimeSDRInputSettings& settings, bool force); +}; + +#endif /* PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUT_H_ */ diff --git a/plugins/samplesource/limesdrinput/limesdrinputsettings.h b/plugins/samplesource/limesdrinput/limesdrinputsettings.h new file mode 100644 index 000000000..e34956f93 --- /dev/null +++ b/plugins/samplesource/limesdrinput/limesdrinputsettings.h @@ -0,0 +1,25 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017 Edouard Griffiths, F4EXB // +// // +// This program 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 as version 3 of the License, or // +// // +// This program 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 V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUTSETTINGS_H_ +#define PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUTSETTINGS_H_ + +struct LimeSDRInputSettings +{ + +}; + +#endif /* PLUGINS_SAMPLESOURCE_LIMESDRINPUT_LIMESDRINPUTSETTINGS_H_ */