diff --git a/devices/plutosdr/deviceplutosdrbox.h b/devices/plutosdr/deviceplutosdrbox.h index 11cdb1bfb..be0e773d4 100644 --- a/devices/plutosdr/deviceplutosdrbox.h +++ b/devices/plutosdr/deviceplutosdrbox.h @@ -17,6 +17,8 @@ #ifndef DEVICES_PLUTOSDR_DEVICEPLUTOSDRBOX_H_ #define DEVICES_PLUTOSDR_DEVICEPLUTOSDRBOX_H_ +#include +#include #include "deviceplutosdrscan.h" class DevicePlutoSDRBox diff --git a/plugins/samplesource/plutosdrinput/CMakeLists.txt b/plugins/samplesource/plutosdrinput/CMakeLists.txt index 1767b07a0..2e1ffd391 100644 --- a/plugins/samplesource/plutosdrinput/CMakeLists.txt +++ b/plugins/samplesource/plutosdrinput/CMakeLists.txt @@ -5,7 +5,7 @@ set(plutosdrinput_SOURCES plutosdrinput.cpp plutosdrinputplugin.cpp plutosdrinputsettings.cpp -# plutosdrinputthread.cpp + plutosdrinputthread.cpp ) set(plutosdrinput_HEADERS @@ -13,7 +13,7 @@ set(plutosdrinput_HEADERS plutosdrinput.h plutosdrinputplugin.h plutosdrinputsettings.h -# plutosdrinputthread.h + plutosdrinputthread.h ) set(plutosdrinput_FORMS diff --git a/plugins/samplesource/plutosdrinput/plutosdrinput.cpp b/plugins/samplesource/plutosdrinput/plutosdrinput.cpp index d27b70286..fa1c5d7b3 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinput.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinput.cpp @@ -24,6 +24,8 @@ #include "plutosdrinput.h" +#define PLUTOSDR_BLOCKSIZE (1024*1024) //complex samples per buffer + MESSAGE_CLASS_DEFINITION(PlutoSDRInput::MsgFileRecord, Message) PlutoSDRInput::PlutoSDRInput(DeviceSourceAPI *deviceAPI) : @@ -166,7 +168,7 @@ bool PlutoSDRInput::openDevice() // acquire the channel DevicePlutoSDRBox *plutoBox = m_deviceShared.m_deviceParams->getBox(); plutoBox->openRx(); - m_plutoRxBuffer = plutoBox->createRxBuffer(1024*1024, false); + m_plutoRxBuffer = plutoBox->createRxBuffer(PLUTOSDR_BLOCKSIZE, false); return true; } diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputthread.cpp b/plugins/samplesource/plutosdrinput/plutosdrinputthread.cpp new file mode 100644 index 000000000..039908bc4 --- /dev/null +++ b/plugins/samplesource/plutosdrinput/plutosdrinputthread.cpp @@ -0,0 +1,203 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 "plutosdr/deviceplutosdrbox.h" +#include "plutosdrinputsettings.h" +#include "plutosdrinputthread.h" + +PlutoSDRInputThread::PlutoSDRInputThread(uint32_t blocksize, DevicePlutoSDRBox* plutoBox, SampleSinkFifo* sampleFifo, QObject* parent) : + QThread(parent), + m_running(false), + m_plutoBox(plutoBox), + m_blockSize(blocksize), + m_convertBuffer(blocksize), + m_sampleFifo(sampleFifo), + m_log2Decim(0), + m_fcPos(PlutoSDRInputSettings::FC_POS_CENTER) +{ + m_buf = new qint16[blocksize*(sizeof(Sample)/sizeof(qint16))]; +} + +PlutoSDRInputThread::~PlutoSDRInputThread() +{ + stopWork(); + delete[] m_buf; +} + +void PlutoSDRInputThread::startWork() +{ + if (m_running) return; // return if running already + + m_startWaitMutex.lock(); + start(); + while(!m_running) + m_startWaiter.wait(&m_startWaitMutex, 100); + m_startWaitMutex.unlock(); +} + +void PlutoSDRInputThread::stopWork() +{ + if (!m_running) return; // return if not running + + m_running = false; + wait(); +} + +void PlutoSDRInputThread::setLog2Decimation(unsigned int log2_decim) +{ + m_log2Decim = log2_decim; +} + +void PlutoSDRInputThread::setFcPos(int fcPos) +{ + m_fcPos = fcPos; +} + +void PlutoSDRInputThread::run() +{ + m_running = true; + m_startWaiter.wakeAll(); + + while (m_running) + { + ssize_t nbytes_rx; + char *p_dat, *p_end; + std::ptrdiff_t p_inc; + int is; + + // Refill RX buffer + nbytes_rx = m_plutoBox->rxBufferRefill(); + if (nbytes_rx < 0) { qWarning("Error refilling buf %d\n",(int) nbytes_rx); break; } + + // READ: Get pointers to RX buf and read IQ from RX buf port 0 + p_inc = m_plutoBox->rxBufferStep(); + p_end = m_plutoBox->rxBufferEnd(); + is = 0; + + for (p_dat = m_plutoBox->rxBufferFirst(); p_dat < p_end; p_dat += p_inc) + { + m_buf[2*is] = ((int16_t*)p_dat)[0]; // Real (I) + m_buf[2*is+1] = ((int16_t*)p_dat)[1]; // Imag (Q) + + if (is == ((1< 2 + is = 0; + } + else + { + is++; + } + } + } + + m_running = false; +} + +// Decimate according to specified log2 (ex: log2=4 => decim=16) +void PlutoSDRInputThread::convert(const qint16* buf, qint32 len) +{ + SampleVector::iterator it = m_convertBuffer.begin(); + + if (m_log2Decim == 0) + { + m_decimators.decimate1(&it, buf, len); + } + else + { + if (m_fcPos == 0) // Infra + { + switch (m_log2Decim) + { + case 1: + m_decimators.decimate2_inf(&it, buf, len); + break; + case 2: + m_decimators.decimate4_inf(&it, buf, len); + break; + case 3: + m_decimators.decimate8_inf(&it, buf, len); + break; + case 4: + m_decimators.decimate16_inf(&it, buf, len); + break; + case 5: + m_decimators.decimate32_inf(&it, buf, len); + break; + case 6: + m_decimators.decimate64_inf(&it, buf, len); + break; + default: + break; + } + } + else if (m_fcPos == 1) // Supra + { + switch (m_log2Decim) + { + case 1: + m_decimators.decimate2_sup(&it, buf, len); + break; + case 2: + m_decimators.decimate4_sup(&it, buf, len); + break; + case 3: + m_decimators.decimate8_sup(&it, buf, len); + break; + case 4: + m_decimators.decimate16_sup(&it, buf, len); + break; + case 5: + m_decimators.decimate32_sup(&it, buf, len); + break; + case 6: + m_decimators.decimate64_sup(&it, buf, len); + break; + default: + break; + } + } + else if (m_fcPos == 2) // Center + { + switch (m_log2Decim) + { + case 1: + m_decimators.decimate2_cen(&it, buf, len); + break; + case 2: + m_decimators.decimate4_cen(&it, buf, len); + break; + case 3: + m_decimators.decimate8_cen(&it, buf, len); + break; + case 4: + m_decimators.decimate16_cen(&it, buf, len); + break; + case 5: + m_decimators.decimate32_cen(&it, buf, len); + break; + case 6: + m_decimators.decimate64_cen(&it, buf, len); + break; + default: + break; + } + } + } + + m_sampleFifo->write(m_convertBuffer.begin(), it); +} + diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputthread.h b/plugins/samplesource/plutosdrinput/plutosdrinputthread.h new file mode 100644 index 000000000..29d59747a --- /dev/null +++ b/plugins/samplesource/plutosdrinput/plutosdrinputthread.h @@ -0,0 +1,67 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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_PLUTOSDRINPUT_PLUTOSDRINPUTTHREAD_H_ +#define PLUGINS_SAMPLESOURCE_PLUTOSDRINPUT_PLUTOSDRINPUTTHREAD_H_ + +#include +#include +#include + +#include "dsp/samplesinkfifo.h" +#include "dsp/decimators.h" +#include "plutosdr/deviceplutosdrshared.h" + +class DevicePlutoSDRBox; + +class PlutoSDRInputThread : public QThread, public DevicePlutoSDRShared::ThreadInterface +{ + Q_OBJECT + +public: + PlutoSDRInputThread(uint32_t blocksize, DevicePlutoSDRBox* plutoBox, SampleSinkFifo* sampleFifo, QObject* parent = 0); + ~PlutoSDRInputThread(); + + virtual void startWork(); + virtual void stopWork(); + virtual void setDeviceSampleRate(int sampleRate __attribute__((unused))) {} + virtual bool isRunning() { return m_running; } + void setLog2Decimation(unsigned int log2_decim); + void setFcPos(int fcPos); + +private: + QMutex m_startWaitMutex; + QWaitCondition m_startWaiter; + bool m_running; + + DevicePlutoSDRBox *m_plutoBox; + qint16 *m_buf; // holds I+Q values of each sample + uint32_t m_blockSize; + SampleVector m_convertBuffer; + SampleSinkFifo* m_sampleFifo; + + unsigned int m_log2Decim; // soft decimation + int m_fcPos; + + Decimators m_decimators; + + void run(); + void convert(const qint16* buf, qint32 len); + +}; + + +#endif /* PLUGINS_SAMPLESOURCE_PLUTOSDRINPUT_PLUTOSDRINPUTTHREAD_H_ */