diff --git a/devices/devices.pro b/devices/devices.pro
index 5e4e063f1..ce01b7f01 100644
--- a/devices/devices.pro
+++ b/devices/devices.pro
@@ -15,7 +15,7 @@ DEFINES += USE_SSSE3=1
QMAKE_CXXFLAGS += -mssse3
DEFINES += USE_SSE4_1=1
QMAKE_CXXFLAGS += -msse4.1
-CONFIG(MINGW32):QMAKE_CXXFLAGS += -std=c++11
+QMAKE_CXXFLAGS += -std=c++11
CONFIG(MINGW32):LIBBLADERFSRC = "D:\softs\bladeRF\host\libraries\libbladeRF\include"
CONFIG(MINGW64):LIBBLADERFSRC = "D:\softs\bladeRF\host\libraries\libbladeRF\include"
diff --git a/plugins/samplesink/plutosdroutput/plutosdroutput.pro b/plugins/samplesink/plutosdroutput/plutosdroutput.pro
new file mode 100644
index 000000000..c79a94ddc
--- /dev/null
+++ b/plugins/samplesink/plutosdroutput/plutosdroutput.pro
@@ -0,0 +1,50 @@
+#--------------------------------------------------------
+#
+# Pro file for Android and Windows builds with Qt Creator
+#
+#--------------------------------------------------------
+
+TEMPLATE = lib
+CONFIG += plugin
+
+QT += core gui widgets multimedia opengl
+
+TARGET = outputplutosdr
+
+DEFINES += USE_SSE2=1
+QMAKE_CXXFLAGS += -msse2
+DEFINES += USE_SSE4_1=1
+QMAKE_CXXFLAGS += -msse4.1
+QMAKE_CXXFLAGS += -std=c++11
+
+CONFIG(MINGW32):LIBIIOSRC = "D:\softs\libiio"
+CONFIG(MINGW64):LIBIIOSRC = "D:\softs\libiio"
+
+INCLUDEPATH += $$PWD
+INCLUDEPATH += ../../../sdrbase
+INCLUDEPATH += ../../../devices
+INCLUDEPATH += ../../../libiio/includemw
+INCLUDEPATH += $$LIBIIOSRC
+
+CONFIG(Release):build_subdir = release
+CONFIG(Debug):build_subdir = debug
+
+SOURCES += plutosdroutputgui.cpp\
+ plutosdroutput.cpp\
+ plutosdroutputplugin.cpp\
+ plutosdroutputsettings.cpp\
+ plutosdroutputthread.cpp
+
+HEADERS += plutosdroutputgui.h\
+ plutosdroutput.h\
+ plutosdroutputplugin.h\
+ plutosdroutputsettings.h\
+ plutosdroutputthread.h
+
+FORMS += plutosdroutputgui.ui
+
+LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase
+LIBS += -L../../../libiio/$${build_subdir} -llibiio
+LIBS += -L../../../devices/$${build_subdir} -ldevices
+
+RESOURCES = ../../../sdrbase/resources/res.qrc
diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputgui.cpp b/plugins/samplesink/plutosdroutput/plutosdroutputgui.cpp
index 43a5b3a5d..80d1db9dd 100644
--- a/plugins/samplesink/plutosdroutput/plutosdroutputgui.cpp
+++ b/plugins/samplesink/plutosdroutput/plutosdroutputgui.cpp
@@ -241,7 +241,7 @@ void PlutoSDROutputGUI::displaySettings()
ui->lpFIRGain->setEnabled(m_settings.m_lpfFIREnable);
ui->att->setValue(m_settings.m_att);
- ui->attText->setText(QString("%1").arg(QString::number(m_settings.m_gain*0.25, 'f', 2)));
+ ui->attText->setText(QString("%1").arg(QString::number(m_settings.m_att*0.25, 'f', 2)));
ui->antenna->setCurrentIndex((int) m_settings.m_antennaPath);
@@ -280,16 +280,16 @@ void PlutoSDROutputGUI::updateStatus()
{
switch(state)
{
- case DSPDeviceSourceEngine::StNotStarted:
+ case DSPDeviceSinkEngine::StNotStarted:
ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
break;
- case DSPDeviceSourceEngine::StIdle:
+ case DSPDeviceSinkEngine::StIdle:
ui->startStop->setStyleSheet("QToolButton { background-color : blue; }");
break;
- case DSPDeviceSourceEngine::StRunning:
+ case DSPDeviceSinkEngine::StRunning:
ui->startStop->setStyleSheet("QToolButton { background-color : green; }");
break;
- case DSPDeviceSourceEngine::StError:
+ case DSPDeviceSinkEngine::StError:
ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
QMessageBox::information(this, tr("Message"), m_deviceAPI->errorMessage());
break;
diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputgui.h b/plugins/samplesink/plutosdroutput/plutosdroutputgui.h
index 6adbcd552..570a9e93e 100644
--- a/plugins/samplesink/plutosdroutput/plutosdroutputgui.h
+++ b/plugins/samplesink/plutosdroutput/plutosdroutputgui.h
@@ -14,8 +14,8 @@
// along with this program. If not, see . //
///////////////////////////////////////////////////////////////////////////////////
-#ifndef PLUGINS_SAMPLESOURCE_PLUTOSDROUTPUT_PLUTOSDRINPUTGUI_H_
-#define PLUGINS_SAMPLESOURCE_PLUTOSDROUTPUT_PLUTOSDRINPUTGUI_H_
+#ifndef PLUGINS_SAMPLESOURCE_PLUTOSDROUTPUT_PLUTOSDROUTPUTGUI_H_
+#define PLUGINS_SAMPLESOURCE_PLUTOSDROUTPUT_PLUTOSDROUTPUTGUI_H_
#include
#include
@@ -91,4 +91,4 @@ private slots:
void handleInputMessages();
};
-#endif /* PLUGINS_SAMPLESOURCE_PLUTOSDROUTPUT_PLUTOSDRINPUTGUI_H_ */
+#endif /* PLUGINS_SAMPLESOURCE_PLUTOSDROUTPUT_PLUTOSDROUTPUTGUI_H_ */
diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputgui.ui b/plugins/samplesink/plutosdroutput/plutosdroutputgui.ui
index 73ec1ca82..3a053c35d 100644
--- a/plugins/samplesink/plutosdroutput/plutosdroutputgui.ui
+++ b/plugins/samplesink/plutosdroutput/plutosdroutputgui.ui
@@ -76,7 +76,7 @@
-
-
-
+
54
@@ -255,7 +255,7 @@
2
-
-
+
Sw
@@ -265,7 +265,7 @@
-
-
+
50
@@ -538,14 +538,14 @@
-
-
+
I
-
-
+
50
@@ -648,7 +648,7 @@
-
-
+
40
@@ -774,6 +774,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputplugin.cpp b/plugins/samplesink/plutosdroutput/plutosdroutputplugin.cpp
index 2f3ecb11f..7e95aac0f 100644
--- a/plugins/samplesink/plutosdroutput/plutosdroutputplugin.cpp
+++ b/plugins/samplesink/plutosdroutput/plutosdroutputplugin.cpp
@@ -85,7 +85,7 @@ PluginInstanceUI* PlutoSDROutputPlugin::createSampleSinkPluginInstanceGUI(const
{
if(sinkId == m_deviceTypeID)
{
- PlutoSDROutputGui* gui = new PlutoSDROutputGui(deviceAPI);
+ PlutoSDROutputGUI* gui = new PlutoSDROutputGUI(deviceAPI);
*widget = gui;
return gui;
}
@@ -95,7 +95,7 @@ PluginInstanceUI* PlutoSDROutputPlugin::createSampleSinkPluginInstanceGUI(const
}
}
-DeviceSampleSink *PlutoSDROutputPlugin::createSampleSourcePluginInstanceInput(const QString& sinkId, DeviceSinkAPI *deviceAPI)
+DeviceSampleSink *PlutoSDROutputPlugin::createSampleSinkPluginInstanceOutput(const QString& sinkId, DeviceSinkAPI *deviceAPI)
{
if (sinkId == m_deviceTypeID)
{
diff --git a/plugins/samplesink/plutosdroutput/plutosdroutputthread.cpp b/plugins/samplesink/plutosdroutput/plutosdroutputthread.cpp
new file mode 100644
index 000000000..7d7b2c5e5
--- /dev/null
+++ b/plugins/samplesink/plutosdroutput/plutosdroutputthread.cpp
@@ -0,0 +1,149 @@
+///////////////////////////////////////////////////////////////////////////////////
+// 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 "plutosdr/deviceplutosdrbox.h"
+#include "plutosdroutputsettings.h"
+#include "iio.h"
+#include "plutosdroutputthread.h"
+
+PlutoSDROutputThread::PlutoSDROutputThread(uint32_t blocksizeSamples, DevicePlutoSDRBox* plutoBox, SampleSourceFifo* sampleFifo, QObject* parent) :
+ QThread(parent),
+ m_running(false),
+ m_plutoBox(plutoBox),
+ m_blockSizeSamples(blocksizeSamples),
+ m_sampleFifo(sampleFifo),
+ m_log2Interp(0)
+{
+ m_buf = new qint16[blocksizeSamples*(sizeof(Sample)/sizeof(qint16))];
+// m_bufConv = new qint16[blocksizeSamples*(sizeof(Sample)/sizeof(qint16))];
+}
+
+PlutoSDROutputThread::~PlutoSDROutputThread()
+{
+ stopWork();
+ delete[] m_buf;
+}
+
+void PlutoSDROutputThread::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 PlutoSDROutputThread::stopWork()
+{
+ if (!m_running) return; // return if not running
+
+ m_running = false;
+ wait();
+}
+
+void PlutoSDROutputThread::setLog2Interpolation(unsigned int log2_interp)
+{
+ m_log2Interp = log2_interp;
+}
+
+void PlutoSDROutputThread::run()
+{
+ m_running = true;
+ m_startWaiter.wakeAll();
+
+ while (m_running)
+ {
+ ssize_t nbytes_tx;
+ char *p_dat, *p_end;
+ std::ptrdiff_t p_inc;
+ int ihs; // half sample index (I then Q to make a sample)
+
+ convert(m_buf, 2*m_blockSizeSamples); // size given in number of int16_t (I and Q interleaved)
+
+ // WRITE: Get pointers to TX buf and write IQ to TX buf port 0
+ p_inc = m_plutoBox->txBufferStep();
+ p_end = m_plutoBox->txBufferEnd();
+ ihs = 0;
+
+ // p_inc is 2 on a char* buffer therefore each iteration processes only the I or Q sample
+ // I and Q samples are processed one after the other
+ // conversion is not needed as samples are little endian
+
+ for (p_dat = m_plutoBox->txBufferFirst(), ihs = 0; p_dat < p_end; p_dat += p_inc, ihs++)
+ {
+ *((int16_t*)p_dat) = m_buf[ihs] << 4;
+ }
+
+ // Schedule TX buffer for sending
+ nbytes_tx = m_plutoBox->txBufferPush();
+
+ if (nbytes_tx < 0)
+ {
+ printf("PlutoSDRInputThread::run: error pushing buf %d\n", (int) nbytes_tx);
+ usleep(200000);
+ continue;
+ }
+ }
+
+ m_running = false;
+}
+
+// Decimate according to specified log2 (ex: log2=4 => decim=16)
+// len is in half samples (I or Q) thus the size up to which buf is filled
+// SampleVector contains full (I, Q) samples
+void PlutoSDROutputThread::convert(qint16* buf, qint32 len)
+{
+ // pull samples from baseband generator
+ SampleVector::iterator beginRead;
+ m_sampleFifo->readAdvance(beginRead, len/(2*(1<. //
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef PLUGINS_SAMPLESOURCE_PLUTOSDROUTPUT_PLUTOSDROUTPUTTHREAD_H_
+#define PLUGINS_SAMPLESOURCE_PLUTOSDROUTPUT_PLUTOSDROUTPUTTHREAD_H_
+
+#include
+#include
+#include
+
+#include "dsp/samplesourcefifo.h"
+#include "dsp/interpolators.h"
+#include "plutosdr/deviceplutosdrshared.h"
+
+class DevicePlutoSDRBox;
+
+class PlutoSDROutputThread : public QThread, public DevicePlutoSDRShared::ThreadInterface
+{
+ Q_OBJECT
+
+public:
+ PlutoSDROutputThread(uint32_t blocksize, DevicePlutoSDRBox* plutoBox, SampleSourceFifo* sampleFifo, QObject* parent = 0);
+ ~PlutoSDROutputThread();
+
+ virtual void startWork();
+ virtual void stopWork();
+ virtual void setDeviceSampleRate(int sampleRate __attribute__((unused))) {}
+ virtual bool isRunning() { return m_running; }
+ void setLog2Interpolation(unsigned int log2_interp);
+
+private:
+ QMutex m_startWaitMutex;
+ QWaitCondition m_startWaiter;
+ bool m_running;
+
+ DevicePlutoSDRBox *m_plutoBox;
+ int16_t *m_buf; //!< holds I+Q values of each sample from devce
+ int16_t *m_bufConv; //!< holds I+Q values of each sample converted to host format via iio_channel_convert
+ uint32_t m_blockSizeSamples; //!< buffer sizes in number of (I,Q) samples
+ SampleSourceFifo* m_sampleFifo; //!< DSP sample FIFO (I,Q)
+
+ unsigned int m_log2Interp; // soft interpolation
+
+ Interpolators m_interpolators;
+
+ void run();
+ void convert(qint16* buf, qint32 len);
+
+};
+
+
+#endif /* PLUGINS_SAMPLESOURCE_PLUTOSDROUTPUT_PLUTOSDROUTPUTTHREAD_H_ */
diff --git a/sdrangel.windows.pro b/sdrangel.windows.pro
index e90f378b9..1b1a77d97 100644
--- a/sdrangel.windows.pro
+++ b/sdrangel.windows.pro
@@ -34,6 +34,7 @@ SUBDIRS += plugins/samplesink/filesink
SUBDIRS += plugins/samplesink/bladerfoutput
SUBDIRS += plugins/samplesink/hackrfoutput
SUBDIRS += plugins/samplesink/limesdroutput
+SUBDIRS += plugins/samplesink/plutosdroutput
SUBDIRS += plugins/channelrx/chanalyzer
SUBDIRS += plugins/channelrx/chanalyzerng
SUBDIRS += plugins/channelrx/demodam