diff --git a/sdrdaemon/CMakeLists.txt b/sdrdaemon/CMakeLists.txt index b70416576..6e6966114 100644 --- a/sdrdaemon/CMakeLists.txt +++ b/sdrdaemon/CMakeLists.txt @@ -8,6 +8,7 @@ set(sdrdaemon_SOURCES channel/sdrdaemonchannelsink.cpp channel/sdrdaemonchannelsource.cpp channel/sdrdaemondataqueue.cpp + channel/sdrdaemonchannelsinkthread.cpp webapi/webapiadapterdaemon.cpp webapi/webapirequestmapper.cpp webapi/webapiserver.cpp @@ -22,6 +23,7 @@ set(sdrdaemon_HEADERS channel/sdrdaemonchannelsource.h channel/sdrdaemondataqueue.h channel/sdrdaemondatablock.h + channel/sdrdaemonchannelsinkthread.h webapi/webapiadapterdaemon.h webapi/webapirequestmapper.h webapi/webapiserver.h diff --git a/sdrdaemon/channel/sdrdaemonchannelsinkthread.cpp b/sdrdaemon/channel/sdrdaemonchannelsinkthread.cpp new file mode 100644 index 000000000..f54628698 --- /dev/null +++ b/sdrdaemon/channel/sdrdaemonchannelsinkthread.cpp @@ -0,0 +1,89 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB. // +// // +// SDRdaemon sink channel (Rx) UDP sender thread // +// // +// SDRdaemon is a detached SDR front end that handles the interface with a // +// physical device and sends or receives the I/Q samples stream to or from a // +// SDRangel instance via UDP. It is controlled via a Web REST API. // +// // +// 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 "channel/sdrdaemondataqueue.h" +#include "channel/sdrdaemondatablock.h" +#include "channel/sdrdaemonchannelsinkthread.h" + +SDRDaemonChannelSinkThread::SDRDaemonChannelSinkThread(SDRDaemonDataQueue *dataQueue, QObject* parent) : + QThread(parent), + m_running(false), + m_dataQueue(dataQueue) +{ + connect(m_dataQueue, SIGNAL(dataBlockEnqueued()), this, SLOT(handleData())); +} + +SDRDaemonChannelSinkThread::~SDRDaemonChannelSinkThread() +{ + stopWork(); +} + +void SDRDaemonChannelSinkThread::startWork() +{ + qDebug("SDRDaemonChannelSinkThread::startWork"); + m_startWaitMutex.lock(); + start(); + while(!m_running) + m_startWaiter.wait(&m_startWaitMutex, 100); + m_startWaitMutex.unlock(); +} + +void SDRDaemonChannelSinkThread::stopWork() +{ + qDebug("SDRDaemonChannelSinkThread::stopWork"); + m_running = false; + wait(); +} + +void SDRDaemonChannelSinkThread::run() +{ + qDebug("SDRDaemonChannelSinkThread::run: begin"); + m_running = true; + m_startWaiter.wakeAll(); + + while (m_running) + { + sleep(1); // Do nothing as everything is in the data handler (dequeuer) + } + + m_running = false; + qDebug("SDRDaemonChannelSinkThread::run: end"); +} + +bool SDRDaemonChannelSinkThread::handleDataBlock(SDRDaemonDataBlock& dataBlock) +{ + return true; +} + +void SDRDaemonChannelSinkThread::handleData() +{ + SDRDaemonDataBlock* dataBlock; + + while (m_running && ((dataBlock = m_dataQueue->pop()) != 0)) + { + if (handleDataBlock(*dataBlock)) + { + delete dataBlock; + } + } +} \ No newline at end of file diff --git a/sdrdaemon/channel/sdrdaemonchannelsinkthread.h b/sdrdaemon/channel/sdrdaemonchannelsinkthread.h new file mode 100644 index 000000000..67c7be3dd --- /dev/null +++ b/sdrdaemon/channel/sdrdaemonchannelsinkthread.h @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2018 Edouard Griffiths, F4EXB. // +// // +// SDRdaemon sink channel (Rx) UDP sender thread // +// // +// SDRdaemon is a detached SDR front end that handles the interface with a // +// physical device and sends or receives the I/Q samples stream to or from a // +// SDRangel instance via UDP. It is controlled via a Web REST API. // +// // +// 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 + +class SDRDaemonDataQueue; +class SDRDaemonDataBlock; + +class SDRDaemonChannelSinkThread : public QThread { + Q_OBJECT + +public: + SDRDaemonChannelSinkThread(SDRDaemonDataQueue *dataQueue, QObject* parent = 0); + ~SDRDaemonChannelSinkThread(); + + void startWork(); + void stopWork(); + +private: + QMutex m_startWaitMutex; + QWaitCondition m_startWaiter; + bool m_running; + + SDRDaemonDataQueue *m_dataQueue; + + void run(); + bool handleDataBlock(SDRDaemonDataBlock& dataBlock); + +private slots: + void handleData(); +}; \ No newline at end of file diff --git a/sdrdaemon/channel/sdrdaemondatablock.h b/sdrdaemon/channel/sdrdaemondatablock.h index 9a33e022a..3355cc0db 100644 --- a/sdrdaemon/channel/sdrdaemondatablock.h +++ b/sdrdaemon/channel/sdrdaemondatablock.h @@ -36,17 +36,22 @@ struct SDRDaemonMetaDataFEC { uint32_t m_centerFrequency; //!< 4 center frequency in kHz uint32_t m_sampleRate; //!< 8 sample rate in Hz - uint8_t m_sampleBytes; //!< 9 MSB(4): indicators, LSB(4) number of bytes per sample (2 or 3) - uint8_t m_sampleBits; //!< 10 number of effective bits per sample (8 t0 24) - uint8_t m_nbOriginalBlocks; //!< 11 number of blocks with original (protected) data - uint8_t m_nbFECBlocks; //!< 12 number of blocks carrying FEC - uint32_t m_tv_sec; //!< 16 seconds of timestamp at start time of super-frame processing - uint32_t m_tv_usec; //!< 20 microseconds of timestamp at start time of super-frame processing - uint32_t m_crc32; //!< 24 CRC32 of the above + uint8_t m_bigEndian; //!< 9 1 if encoded as big endian, 0 for little endian + uint8_t m_reserved1; //!< 10 reserved + uint8_t m_reserved2; //!< 11 reserved + uint8_t m_reserved3; //!< 12 reserved + uint8_t m_sampleBytes; //!< 13 number of bytes per sample (2 or 3) + uint8_t m_sampleBits; //!< 14 number of effective bits per sample (8 t0 24) + uint8_t m_nbOriginalBlocks; //!< 15 number of blocks with original (protected) data + uint8_t m_nbFECBlocks; //!< 16 number of blocks carrying FEC + uint32_t m_tv_sec; //!< 20 seconds of timestamp at start time of super-frame processing + uint32_t m_tv_usec; //!< 24 microseconds of timestamp at start time of super-frame processing + uint32_t m_crc32; //!< 28 CRC32 of the above + // 32 bytes bool operator==(const SDRDaemonMetaDataFEC& rhs) { - return (memcmp((const void *) this, (const void *) &rhs, 12) == 0); // Only the 12 first bytes are relevant + return (memcmp((const void *) this, (const void *) &rhs, 16) == 0); // Only the 16 first bytes are relevant } void init()