diff --git a/devices/limesdr/devicelimesdrparam.h b/devices/limesdr/devicelimesdrparam.h index 6138b0b80..4f3c20c67 100644 --- a/devices/limesdr/devicelimesdrparam.h +++ b/devices/limesdr/devicelimesdrparam.h @@ -28,8 +28,7 @@ */ 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) + lms_device_t *m_dev; //!< device handle 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) @@ -46,7 +45,6 @@ struct DeviceLimeSDRParams DeviceLimeSDRParams() : m_dev(0), - m_channel(-1), m_nbRxChannels(0), m_nbTxChannels(0), m_sampleRate(1e6), @@ -62,6 +60,7 @@ struct DeviceLimeSDRParams */ bool open(lms_info_str_t deviceStr); void close(); + lms_device_t *getDevice() { return m_dev; } ~DeviceLimeSDRParams() { diff --git a/devices/limesdr/devicelimesdrshared.h b/devices/limesdr/devicelimesdrshared.h new file mode 100644 index 000000000..ae8a79ce9 --- /dev/null +++ b/devices/limesdr/devicelimesdrshared.h @@ -0,0 +1,40 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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_DEVICELIMESDRSHARED_H_ +#define DEVICES_LIMESDR_DEVICELIMESDRSHARED_H_ + +#include +#include "devicelimesdrparam.h" + +/** + * Structure shared by a buddy with other buddies + */ +struct DeviceLimeSDRShared +{ + DeviceLimeSDRParams *m_deviceParams; //!< unique hardware device parameters + std::size_t m_channel; //!< logical device channel number (-1 if none) + + DeviceLimeSDRShared() : + m_deviceParams(0), + m_channel(-1) + {} + + ~DeviceLimeSDRShared() + {} +}; + +#endif /* DEVICES_LIMESDR_DEVICELIMESDRSHARED_H_ */ diff --git a/plugins/samplesource/limesdrinput/limesdrinput.cpp b/plugins/samplesource/limesdrinput/limesdrinput.cpp index ad267588f..46ef22560 100644 --- a/plugins/samplesource/limesdrinput/limesdrinput.cpp +++ b/plugins/samplesource/limesdrinput/limesdrinput.cpp @@ -15,8 +15,12 @@ /////////////////////////////////////////////////////////////////////////////////// #include +#include #include +#include "lime/LimeSuite.h" + #include "limesdrinput.h" +#include "limesdr/devicelimesdrparam.h" LimeSDRInput::LimeSDRInput(DeviceSourceAPI *deviceAPI) : @@ -42,33 +46,40 @@ bool LimeSDRInput::openDevice() if (m_deviceAPI->getSourceBuddies().size() > 0) // look source sibling first { DeviceSinkAPI *sourceBuddy = m_deviceAPI->getSourceBuddies()[0]; - m_deviceParams = *(sourceBuddy->getBuddySharedPtr()); // copy parameters + m_deviceShared = *(sourceBuddy->getBuddySharedPtr()); // copy shared data + DeviceLimeSDRParams *deviceParams = m_deviceShared.m_deviceParams; // get device parameters - if (m_deviceAPI->getSourceBuddies().size() == m_deviceParams.m_nbRxChannels) + if (deviceParams == 0) + { + qCritical("LimeSDRInput::openDevice: cannot get device parameters from Rx buddy"); + return false; // the device params should have been created by the buddy + } + + if (m_deviceAPI->getSourceBuddies().size() == 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); + char *busyChannels = new char[deviceParams->m_nbRxChannels]; + memset(busyChannels, 0, 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; + DeviceLimeSDRShared *buddyShared = buddy->getBuddySharedPtr(); + busyChannels[buddyShared->m_channel] = 1; } - int ch = 0; + std::size_t ch = 0; - for (;ch < m_deviceParams.m_nbRxChannels; ch++) + for (;ch < deviceParams->m_nbRxChannels; ch++) { if (busyChannels[ch] == 0) { break; // first available is the good one } } - m_deviceParams.m_channel = ch; + m_deviceShared.m_channel = ch; delete[] busyChannels; } // look for Tx buddies and get reference to common parameters @@ -76,63 +87,101 @@ bool LimeSDRInput::openDevice() 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 + m_deviceShared = *(sinkBuddy->getBuddySharedPtr()); // copy parameters + + if (m_deviceShared.m_deviceParams == 0) + { + qCritical("LimeSDRInput::openDevice: cannot get device parameters from Tx buddy"); + return false; // the device params should have been created by the buddy + } + + m_deviceShared.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_deviceShared.m_deviceParams = new DeviceLimeSDRParams(); + m_deviceShared.m_deviceParams->open((lms_info_str_t) qPrintable(m_deviceAPI->getSampleSourceSerial())); + m_deviceShared.m_channel = 0; // take first channel } - m_deviceAPI->setBuddySharedPtr(&m_deviceParams); // propagate common parameters to API + m_deviceAPI->setBuddySharedPtr(&m_deviceShared); // propagate common parameters to API - // TODO: acquire the channel + // acquire the channel + + 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); + return false; + } + + // set up the stream + + m_streamId.channel = m_deviceShared.m_channel; //channel number + m_streamId.channel.fifoSize = 1024 * 1024; //fifo size in samples TODO: adjust if necessary + m_streamId.throughputVsLatency = 1.0; //optimize for max throughput + m_streamId.isTx = false; //RX channel + m_streamId.dataFmt = lms_stream_t::LMS_FMT_I12; //12-bit integers + + if (LMS_SetupStream(m_deviceShared.m_deviceParams->getDevice(), &m_streamId) != 0) + { + qCritical("LimeSDRInput::openDevice: cannot setup the stream on Rx channel %u", m_deviceShared.m_channel); + return false; + } + + // TODO: start / stop streaming is done in the thread. You will need to pass the stream Id to the thread at thread creation return true; } void LimeSDRInput::closeDevice() { - // TODO: release the channel + // destroy the stream - // No buddies effectively close the device - if ((m_deviceAPI->getSinkBuddies().size() == 0) && (m_deviceAPI->getSourceBuddies().size() == 0)) + LMS_DestroyStream(m_deviceShared.m_deviceParams->getDevice(), &m_streamId); + + // release the channel + + if (LMS_EnableChannel(m_deviceShared.m_deviceParams->getDevice(), LMS_CH_RX, m_deviceShared.m_channel, false) != 0) { - m_deviceParams.close(); + qWarning("LimeSDRInput::closeDevice: cannot disable Rx channel %u", m_deviceShared.m_channel); } - m_deviceParams.m_dev = 0; + m_deviceShared.m_channel = -1; + + // No buddies so effectively close the device + + if ((m_deviceAPI->getSinkBuddies().size() == 0) && (m_deviceAPI->getSourceBuddies().size() == 0)) + { + m_deviceShared.m_deviceParams->close(); + delete m_deviceShared.m_deviceParams; + m_deviceShared.m_deviceParams = 0; + } } bool LimeSDRInput::start() { - QMutexLocker mutexLocker(&m_mutex); - - if (!m_deviceParams.m_dev) { + if (!m_deviceShared.m_dev) { return false; } if (m_running) stop(); - if ((m_limeSDRInputThread = new LimeSDRInputThread(m_deviceParams.m_dev, &m_sampleFifo)) == 0) + if ((m_limeSDRInputThread = new LimeSDRInputThread(m_deviceShared.m_deviceParams->getDevice(), &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->setSamplerate(m_deviceShared.m_deviceParams->m_sampleRate); + m_limeSDRInputThread->setLog2Decimation(m_settings.m_log2SoftDecim); m_limeSDRInputThread->setFcPos((int) m_settings.m_fcPos); m_limeSDRInputThread->startWork(); - mutexLocker.unlock(); - applySettings(m_settings, true); m_running = true; @@ -141,8 +190,6 @@ bool LimeSDRInput::start() void LimeSDRInput::stop() { - QMutexLocker mutexLocker(&m_mutex); - if (m_limeSDRInputThread != 0) { m_limeSDRInputThread->stopWork(); diff --git a/plugins/samplesource/limesdrinput/limesdrinput.h b/plugins/samplesource/limesdrinput/limesdrinput.h index 1c779b84e..43b155437 100644 --- a/plugins/samplesource/limesdrinput/limesdrinput.h +++ b/plugins/samplesource/limesdrinput/limesdrinput.h @@ -19,7 +19,7 @@ #include #include "dsp/devicesamplesource.h" -#include "limesdr/devicelimesdrparam.h" +#include "limesdr/devicelimesdrshared.h" #include "limesdrinputsettings.h" class DeviceSourceAPI; @@ -48,7 +48,9 @@ private: LimeSDRInputThread* m_limeSDRInputThread; QString m_deviceDescription; bool m_running; - DeviceLimeSDRParams m_deviceParams; + DeviceLimeSDRShared m_deviceShared; + + lms_stream_t m_streamId; bool openDevice(); void closeDevice();