mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-09-28 15:56:33 -04:00
Rename SDRDaemonSink device plugin to RemoteOutput (1)
This commit is contained in:
parent
8ccab8acf4
commit
ad66b4af49
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB |
@ -94,7 +94,7 @@ RemoteSink::~RemoteSink()
|
|||||||
void RemoteSink::setTxDelay(int txDelay, int nbBlocksFEC)
|
void RemoteSink::setTxDelay(int txDelay, int nbBlocksFEC)
|
||||||
{
|
{
|
||||||
double txDelayRatio = txDelay / 100.0;
|
double txDelayRatio = txDelay / 100.0;
|
||||||
int samplesPerBlock = SDRDaemonNbBytesPerBlock / sizeof(Sample);
|
int samplesPerBlock = RemoteNbBytesPerBlock / sizeof(Sample);
|
||||||
double delay = m_sampleRate == 0 ? 1.0 : (127*samplesPerBlock*txDelayRatio) / m_sampleRate;
|
double delay = m_sampleRate == 0 ? 1.0 : (127*samplesPerBlock*txDelayRatio) / m_sampleRate;
|
||||||
delay /= 128 + nbBlocksFEC;
|
delay /= 128 + nbBlocksFEC;
|
||||||
m_txDelay = roundf(delay*1e6); // microseconds
|
m_txDelay = roundf(delay*1e6); // microseconds
|
||||||
@ -123,35 +123,34 @@ void RemoteSink::feed(const SampleVector::const_iterator& begin, const SampleVec
|
|||||||
if (m_txBlockIndex == 0)
|
if (m_txBlockIndex == 0)
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
SDRDaemonMetaDataFEC metaData;
|
RemoteMetaDataFEC metaData;
|
||||||
gettimeofday(&tv, 0);
|
gettimeofday(&tv, 0);
|
||||||
|
|
||||||
metaData.m_centerFrequency = m_centerFrequency;
|
metaData.m_centerFrequency = m_centerFrequency;
|
||||||
metaData.m_sampleRate = m_sampleRate;
|
metaData.m_sampleRate = m_sampleRate;
|
||||||
metaData.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
metaData.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||||
metaData.m_sampleBits = SDR_RX_SAMP_SZ;
|
metaData.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||||
metaData.m_nbOriginalBlocks = SDRDaemonNbOrginalBlocks;
|
metaData.m_nbOriginalBlocks = RemoteNbOrginalBlocks;
|
||||||
metaData.m_nbFECBlocks = m_nbBlocksFEC;
|
metaData.m_nbFECBlocks = m_nbBlocksFEC;
|
||||||
metaData.m_tv_sec = tv.tv_sec;
|
metaData.m_tv_sec = tv.tv_sec;
|
||||||
metaData.m_tv_usec = tv.tv_usec;
|
metaData.m_tv_usec = tv.tv_usec;
|
||||||
|
|
||||||
if (!m_dataBlock) { // on the very first cycle there is no data block allocated
|
if (!m_dataBlock) { // on the very first cycle there is no data block allocated
|
||||||
m_dataBlock = new SDRDaemonDataBlock();
|
m_dataBlock = new RemoteDataBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::crc_32_type crc32;
|
boost::crc_32_type crc32;
|
||||||
crc32.process_bytes(&metaData, 20);
|
crc32.process_bytes(&metaData, 20);
|
||||||
metaData.m_crc32 = crc32.checksum();
|
metaData.m_crc32 = crc32.checksum();
|
||||||
SDRDaemonSuperBlock& superBlock = m_dataBlock->m_superBlocks[0]; // first block
|
RemoteSuperBlock& superBlock = m_dataBlock->m_superBlocks[0]; // first block
|
||||||
superBlock.init();
|
superBlock.init();
|
||||||
superBlock.m_header.m_frameIndex = m_frameCount;
|
superBlock.m_header.m_frameIndex = m_frameCount;
|
||||||
superBlock.m_header.m_blockIndex = m_txBlockIndex;
|
superBlock.m_header.m_blockIndex = m_txBlockIndex;
|
||||||
superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||||
superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||||
|
|
||||||
SDRDaemonMetaDataFEC *destMeta = (SDRDaemonMetaDataFEC *) &superBlock.m_protectedBlock;
|
RemoteMetaDataFEC *destMeta = (RemoteMetaDataFEC *) &superBlock.m_protectedBlock;
|
||||||
*destMeta = metaData;
|
*destMeta = metaData;
|
||||||
//memcpy((void *) &superBlock.m_protectedBlock, (const void *) &metaData, sizeof(SDRDaemonMetaDataFEC));
|
|
||||||
|
|
||||||
if (!(metaData == m_currentMetaFEC))
|
if (!(metaData == m_currentMetaFEC))
|
||||||
{
|
{
|
||||||
@ -172,7 +171,7 @@ void RemoteSink::feed(const SampleVector::const_iterator& begin, const SampleVec
|
|||||||
} // block zero
|
} // block zero
|
||||||
|
|
||||||
// handle different sample sizes...
|
// handle different sample sizes...
|
||||||
int samplesPerBlock = SDRDaemonNbBytesPerBlock / (SDR_RX_SAMP_SZ <= 16 ? 4 : 8); // two I or Q samples
|
int samplesPerBlock = RemoteNbBytesPerBlock / (SDR_RX_SAMP_SZ <= 16 ? 4 : 8); // two I or Q samples
|
||||||
if (m_sampleIndex + inRemainingSamples < samplesPerBlock) // there is still room in the current super block
|
if (m_sampleIndex + inRemainingSamples < samplesPerBlock) // there is still room in the current super block
|
||||||
{
|
{
|
||||||
memcpy((void *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)],
|
memcpy((void *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)],
|
||||||
@ -195,7 +194,7 @@ void RemoteSink::feed(const SampleVector::const_iterator& begin, const SampleVec
|
|||||||
m_superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
m_superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||||
m_dataBlock->m_superBlocks[m_txBlockIndex] = m_superBlock;
|
m_dataBlock->m_superBlocks[m_txBlockIndex] = m_superBlock;
|
||||||
|
|
||||||
if (m_txBlockIndex == SDRDaemonNbOrginalBlocks - 1) // frame complete
|
if (m_txBlockIndex == RemoteNbOrginalBlocks - 1) // frame complete
|
||||||
{
|
{
|
||||||
m_dataBlockMutex.lock();
|
m_dataBlockMutex.lock();
|
||||||
m_dataBlock->m_txControlBlock.m_frameIndex = m_frameCount;
|
m_dataBlock->m_txControlBlock.m_frameIndex = m_frameCount;
|
||||||
@ -207,7 +206,7 @@ void RemoteSink::feed(const SampleVector::const_iterator& begin, const SampleVec
|
|||||||
m_dataBlock->m_txControlBlock.m_dataPort = m_dataPort;
|
m_dataBlock->m_txControlBlock.m_dataPort = m_dataPort;
|
||||||
|
|
||||||
emit dataBlockAvailable(m_dataBlock);
|
emit dataBlockAvailable(m_dataBlock);
|
||||||
m_dataBlock = new SDRDaemonDataBlock(); // create a new one immediately
|
m_dataBlock = new RemoteDataBlock(); // create a new one immediately
|
||||||
m_dataBlockMutex.unlock();
|
m_dataBlockMutex.unlock();
|
||||||
|
|
||||||
m_txBlockIndex = 0;
|
m_txBlockIndex = 0;
|
||||||
@ -225,7 +224,7 @@ void RemoteSink::start()
|
|||||||
{
|
{
|
||||||
qDebug("RemoteSink::start");
|
qDebug("RemoteSink::start");
|
||||||
|
|
||||||
memset((void *) &m_currentMetaFEC, 0, sizeof(SDRDaemonMetaDataFEC));
|
memset((void *) &m_currentMetaFEC, 0, sizeof(RemoteMetaDataFEC));
|
||||||
|
|
||||||
if (m_running) {
|
if (m_running) {
|
||||||
stop();
|
stop();
|
||||||
@ -233,9 +232,9 @@ void RemoteSink::start()
|
|||||||
|
|
||||||
m_sinkThread = new RemoteSinkThread();
|
m_sinkThread = new RemoteSinkThread();
|
||||||
connect(this,
|
connect(this,
|
||||||
SIGNAL(dataBlockAvailable(SDRDaemonDataBlock *)),
|
SIGNAL(dataBlockAvailable(RemoteDataBlock *)),
|
||||||
m_sinkThread,
|
m_sinkThread,
|
||||||
SLOT(processDataBlock(SDRDaemonDataBlock *)),
|
SLOT(processDataBlock(RemoteDataBlock *)),
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
m_sinkThread->startStop(true);
|
m_sinkThread->startStop(true);
|
||||||
m_running = true;
|
m_running = true;
|
||||||
|
@ -23,14 +23,13 @@
|
|||||||
#ifndef INCLUDE_REMOTESINK_H_
|
#ifndef INCLUDE_REMOTESINK_H_
|
||||||
#define INCLUDE_REMOTESINK_H_
|
#define INCLUDE_REMOTESINK_H_
|
||||||
|
|
||||||
|
#include <channel/remotedatablock.h>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
|
|
||||||
#include "dsp/basebandsamplesink.h"
|
#include "dsp/basebandsamplesink.h"
|
||||||
#include "channel/channelsinkapi.h"
|
#include "channel/channelsinkapi.h"
|
||||||
#include "channel/sdrdaemondatablock.h"
|
|
||||||
|
|
||||||
#include "../remotesink/remotesinksettings.h"
|
#include "../remotesink/remotesinksettings.h"
|
||||||
|
|
||||||
class QNetworkAccessManager;
|
class QNetworkAccessManager;
|
||||||
@ -127,7 +126,7 @@ public:
|
|||||||
static const QString m_channelId;
|
static const QString m_channelId;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dataBlockAvailable(SDRDaemonDataBlock *dataBlock);
|
void dataBlockAvailable(RemoteDataBlock *dataBlock);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DeviceSourceAPI *m_deviceAPI;
|
DeviceSourceAPI *m_deviceAPI;
|
||||||
@ -141,9 +140,9 @@ private:
|
|||||||
int m_txBlockIndex; //!< Current index in blocks to transmit in the Tx row
|
int m_txBlockIndex; //!< Current index in blocks to transmit in the Tx row
|
||||||
uint16_t m_frameCount; //!< transmission frame count
|
uint16_t m_frameCount; //!< transmission frame count
|
||||||
int m_sampleIndex; //!< Current sample index in protected block data
|
int m_sampleIndex; //!< Current sample index in protected block data
|
||||||
SDRDaemonSuperBlock m_superBlock;
|
RemoteSuperBlock m_superBlock;
|
||||||
SDRDaemonMetaDataFEC m_currentMetaFEC;
|
RemoteMetaDataFEC m_currentMetaFEC;
|
||||||
SDRDaemonDataBlock *m_dataBlock;
|
RemoteDataBlock *m_dataBlock;
|
||||||
QMutex m_dataBlockMutex;
|
QMutex m_dataBlockMutex;
|
||||||
|
|
||||||
uint64_t m_centerFrequency;
|
uint64_t m_centerFrequency;
|
||||||
|
@ -304,7 +304,7 @@ void RemoteSinkGUI::on_nbFECBlocks_valueChanged(int value)
|
|||||||
void RemoteSinkGUI::updateTxDelayTime()
|
void RemoteSinkGUI::updateTxDelayTime()
|
||||||
{
|
{
|
||||||
double txDelayRatio = m_settings.m_txDelay / 100.0;
|
double txDelayRatio = m_settings.m_txDelay / 100.0;
|
||||||
int samplesPerBlock = SDRDaemonNbBytesPerBlock / sizeof(Sample);
|
int samplesPerBlock = RemoteNbBytesPerBlock / sizeof(Sample);
|
||||||
double delay = m_sampleRate == 0 ? 0.0 : (127*samplesPerBlock*txDelayRatio) / m_sampleRate;
|
double delay = m_sampleRate == 0 ? 0.0 : (127*samplesPerBlock*txDelayRatio) / m_sampleRate;
|
||||||
delay /= 128 + m_settings.m_nbFECBlocks;
|
delay /= 128 + m_settings.m_nbFECBlocks;
|
||||||
ui->txDelayTime->setText(tr("%1µs").arg(QString::number(delay*1e6, 'f', 0)));
|
ui->txDelayTime->setText(tr("%1µs").arg(QString::number(delay*1e6, 'f', 0)));
|
||||||
|
@ -22,9 +22,9 @@
|
|||||||
|
|
||||||
#include "remotesinkthread.h"
|
#include "remotesinkthread.h"
|
||||||
|
|
||||||
|
#include <channel/remotedatablock.h>
|
||||||
#include <QUdpSocket>
|
#include <QUdpSocket>
|
||||||
|
|
||||||
#include "channel/sdrdaemondatablock.h"
|
|
||||||
#include "cm256.h"
|
#include "cm256.h"
|
||||||
|
|
||||||
MESSAGE_CLASS_DEFINITION(RemoteSinkThread::MsgStartStop, Message)
|
MESSAGE_CLASS_DEFINITION(RemoteSinkThread::MsgStartStop, Message)
|
||||||
@ -86,48 +86,48 @@ void RemoteSinkThread::run()
|
|||||||
qDebug("RemoteSinkThread::run: end");
|
qDebug("RemoteSinkThread::run: end");
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteSinkThread::processDataBlock(SDRDaemonDataBlock *dataBlock)
|
void RemoteSinkThread::processDataBlock(RemoteDataBlock *dataBlock)
|
||||||
{
|
{
|
||||||
handleDataBlock(*dataBlock);
|
handleDataBlock(*dataBlock);
|
||||||
delete dataBlock;
|
delete dataBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteSinkThread::handleDataBlock(SDRDaemonDataBlock& dataBlock)
|
void RemoteSinkThread::handleDataBlock(RemoteDataBlock& dataBlock)
|
||||||
{
|
{
|
||||||
CM256::cm256_encoder_params cm256Params; //!< Main interface with CM256 encoder
|
CM256::cm256_encoder_params cm256Params; //!< Main interface with CM256 encoder
|
||||||
CM256::cm256_block descriptorBlocks[256]; //!< Pointers to data for CM256 encoder
|
CM256::cm256_block descriptorBlocks[256]; //!< Pointers to data for CM256 encoder
|
||||||
SDRDaemonProtectedBlock fecBlocks[256]; //!< FEC data
|
RemoteProtectedBlock fecBlocks[256]; //!< FEC data
|
||||||
|
|
||||||
uint16_t frameIndex = dataBlock.m_txControlBlock.m_frameIndex;
|
uint16_t frameIndex = dataBlock.m_txControlBlock.m_frameIndex;
|
||||||
int nbBlocksFEC = dataBlock.m_txControlBlock.m_nbBlocksFEC;
|
int nbBlocksFEC = dataBlock.m_txControlBlock.m_nbBlocksFEC;
|
||||||
int txDelay = dataBlock.m_txControlBlock.m_txDelay;
|
int txDelay = dataBlock.m_txControlBlock.m_txDelay;
|
||||||
m_address.setAddress(dataBlock.m_txControlBlock.m_dataAddress);
|
m_address.setAddress(dataBlock.m_txControlBlock.m_dataAddress);
|
||||||
uint16_t dataPort = dataBlock.m_txControlBlock.m_dataPort;
|
uint16_t dataPort = dataBlock.m_txControlBlock.m_dataPort;
|
||||||
SDRDaemonSuperBlock *txBlockx = dataBlock.m_superBlocks;
|
RemoteSuperBlock *txBlockx = dataBlock.m_superBlocks;
|
||||||
|
|
||||||
if ((nbBlocksFEC == 0) || !m_cm256p) // Do not FEC encode
|
if ((nbBlocksFEC == 0) || !m_cm256p) // Do not FEC encode
|
||||||
{
|
{
|
||||||
if (m_socket)
|
if (m_socket)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < SDRDaemonNbOrginalBlocks; i++)
|
for (int i = 0; i < RemoteNbOrginalBlocks; i++)
|
||||||
{
|
{
|
||||||
// send block via UDP
|
// send block via UDP
|
||||||
m_socket->writeDatagram((const char*)&txBlockx[i], (qint64 ) SDRDaemonUdpSize, m_address, dataPort);
|
m_socket->writeDatagram((const char*)&txBlockx[i], (qint64 ) RemoteUdpSize, m_address, dataPort);
|
||||||
usleep(txDelay);
|
usleep(txDelay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cm256Params.BlockBytes = sizeof(SDRDaemonProtectedBlock);
|
cm256Params.BlockBytes = sizeof(RemoteProtectedBlock);
|
||||||
cm256Params.OriginalCount = SDRDaemonNbOrginalBlocks;
|
cm256Params.OriginalCount = RemoteNbOrginalBlocks;
|
||||||
cm256Params.RecoveryCount = nbBlocksFEC;
|
cm256Params.RecoveryCount = nbBlocksFEC;
|
||||||
|
|
||||||
// Fill pointers to data
|
// Fill pointers to data
|
||||||
for (int i = 0; i < cm256Params.OriginalCount + cm256Params.RecoveryCount; ++i)
|
for (int i = 0; i < cm256Params.OriginalCount + cm256Params.RecoveryCount; ++i)
|
||||||
{
|
{
|
||||||
if (i >= cm256Params.OriginalCount) {
|
if (i >= cm256Params.OriginalCount) {
|
||||||
memset((void *) &txBlockx[i].m_protectedBlock, 0, sizeof(SDRDaemonProtectedBlock));
|
memset((void *) &txBlockx[i].m_protectedBlock, 0, sizeof(RemoteProtectedBlock));
|
||||||
}
|
}
|
||||||
|
|
||||||
txBlockx[i].m_header.m_frameIndex = frameIndex;
|
txBlockx[i].m_header.m_frameIndex = frameIndex;
|
||||||
@ -157,7 +157,7 @@ void RemoteSinkThread::handleDataBlock(SDRDaemonDataBlock& dataBlock)
|
|||||||
for (int i = 0; i < cm256Params.OriginalCount + cm256Params.RecoveryCount; i++)
|
for (int i = 0; i < cm256Params.OriginalCount + cm256Params.RecoveryCount; i++)
|
||||||
{
|
{
|
||||||
// send block via UDP
|
// send block via UDP
|
||||||
m_socket->writeDatagram((const char*)&txBlockx[i], (qint64 ) SDRDaemonUdpSize, m_address, dataPort);
|
m_socket->writeDatagram((const char*)&txBlockx[i], (qint64 ) RemoteUdpSize, m_address, dataPort);
|
||||||
usleep(txDelay);
|
usleep(txDelay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
#include "util/message.h"
|
#include "util/message.h"
|
||||||
#include "util/messagequeue.h"
|
#include "util/messagequeue.h"
|
||||||
|
|
||||||
class SDRDaemonDataBlock;
|
class RemoteDataBlock;
|
||||||
class CM256;
|
class CM256;
|
||||||
class QUdpSocket;
|
class QUdpSocket;
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ public:
|
|||||||
void startStop(bool start);
|
void startStop(bool start);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void processDataBlock(SDRDaemonDataBlock *dataBlock);
|
void processDataBlock(RemoteDataBlock *dataBlock);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMutex m_startWaitMutex;
|
QMutex m_startWaitMutex;
|
||||||
@ -85,7 +85,7 @@ private:
|
|||||||
void stopWork();
|
void stopWork();
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
void handleDataBlock(SDRDaemonDataBlock& dataBlock);
|
void handleDataBlock(RemoteDataBlock& dataBlock);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleInputMessages();
|
void handleInputMessages();
|
||||||
|
@ -243,10 +243,10 @@ void RemoteSource::applySettings(const RemoteSourceSettings& settings, bool forc
|
|||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteSource::handleDataBlock(SDRDaemonDataBlock* dataBlock)
|
void RemoteSource::handleDataBlock(RemoteDataBlock* dataBlock)
|
||||||
{
|
{
|
||||||
(void) dataBlock;
|
(void) dataBlock;
|
||||||
if (dataBlock->m_rxControlBlock.m_blockCount < SDRDaemonNbOrginalBlocks)
|
if (dataBlock->m_rxControlBlock.m_blockCount < RemoteNbOrginalBlocks)
|
||||||
{
|
{
|
||||||
qWarning("RemoteSource::handleDataBlock: incomplete data block: not processing");
|
qWarning("RemoteSource::handleDataBlock: incomplete data block: not processing");
|
||||||
}
|
}
|
||||||
@ -270,15 +270,15 @@ void RemoteSource::handleDataBlock(SDRDaemonDataBlock* dataBlock)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//qDebug("DaemonSource::handleDataBlock: frame: %u blocks: %d", dataBlock.m_rxControlBlock.m_frameIndex, blockCount);
|
//qDebug("RemoteSource::handleDataBlock: frame: %u blocks: %d", dataBlock.m_rxControlBlock.m_frameIndex, blockCount);
|
||||||
|
|
||||||
// Need to use the CM256 recovery
|
// Need to use the CM256 recovery
|
||||||
if (m_cm256p &&(dataBlock->m_rxControlBlock.m_originalCount < SDRDaemonNbOrginalBlocks))
|
if (m_cm256p &&(dataBlock->m_rxControlBlock.m_originalCount < RemoteNbOrginalBlocks))
|
||||||
{
|
{
|
||||||
qDebug("RemoteSource::handleDataBlock: %d recovery blocks", dataBlock->m_rxControlBlock.m_recoveryCount);
|
qDebug("RemoteSource::handleDataBlock: %d recovery blocks", dataBlock->m_rxControlBlock.m_recoveryCount);
|
||||||
CM256::cm256_encoder_params paramsCM256;
|
CM256::cm256_encoder_params paramsCM256;
|
||||||
paramsCM256.BlockBytes = sizeof(SDRDaemonProtectedBlock); // never changes
|
paramsCM256.BlockBytes = sizeof(RemoteProtectedBlock); // never changes
|
||||||
paramsCM256.OriginalCount = SDRDaemonNbOrginalBlocks; // never changes
|
paramsCM256.OriginalCount = RemoteNbOrginalBlocks; // never changes
|
||||||
|
|
||||||
if (m_currentMeta.m_tv_sec == 0) {
|
if (m_currentMeta.m_tv_sec == 0) {
|
||||||
paramsCM256.RecoveryCount = dataBlock->m_rxControlBlock.m_recoveryCount;
|
paramsCM256.RecoveryCount = dataBlock->m_rxControlBlock.m_recoveryCount;
|
||||||
@ -287,8 +287,8 @@ void RemoteSource::handleDataBlock(SDRDaemonDataBlock* dataBlock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update counters
|
// update counters
|
||||||
if (dataBlock->m_rxControlBlock.m_originalCount < SDRDaemonNbOrginalBlocks - paramsCM256.RecoveryCount) {
|
if (dataBlock->m_rxControlBlock.m_originalCount < RemoteNbOrginalBlocks - paramsCM256.RecoveryCount) {
|
||||||
m_nbUncorrectableErrors += SDRDaemonNbOrginalBlocks - paramsCM256.RecoveryCount - dataBlock->m_rxControlBlock.m_originalCount;
|
m_nbUncorrectableErrors += RemoteNbOrginalBlocks - paramsCM256.RecoveryCount - dataBlock->m_rxControlBlock.m_originalCount;
|
||||||
} else {
|
} else {
|
||||||
m_nbCorrectableErrors += dataBlock->m_rxControlBlock.m_recoveryCount;
|
m_nbCorrectableErrors += dataBlock->m_rxControlBlock.m_recoveryCount;
|
||||||
}
|
}
|
||||||
@ -303,11 +303,11 @@ void RemoteSource::handleDataBlock(SDRDaemonDataBlock* dataBlock)
|
|||||||
{
|
{
|
||||||
for (int ir = 0; ir < dataBlock->m_rxControlBlock.m_recoveryCount; ir++) // restore missing blocks
|
for (int ir = 0; ir < dataBlock->m_rxControlBlock.m_recoveryCount; ir++) // restore missing blocks
|
||||||
{
|
{
|
||||||
int recoveryIndex = SDRDaemonNbOrginalBlocks - dataBlock->m_rxControlBlock.m_recoveryCount + ir;
|
int recoveryIndex = RemoteNbOrginalBlocks - dataBlock->m_rxControlBlock.m_recoveryCount + ir;
|
||||||
int blockIndex = m_cm256DescriptorBlocks[recoveryIndex].Index;
|
int blockIndex = m_cm256DescriptorBlocks[recoveryIndex].Index;
|
||||||
SDRDaemonProtectedBlock *recoveredBlock =
|
RemoteProtectedBlock *recoveredBlock =
|
||||||
(SDRDaemonProtectedBlock *) m_cm256DescriptorBlocks[recoveryIndex].Block;
|
(RemoteProtectedBlock *) m_cm256DescriptorBlocks[recoveryIndex].Block;
|
||||||
memcpy((void *) &(dataBlock->m_superBlocks[blockIndex].m_protectedBlock), recoveredBlock, sizeof(SDRDaemonProtectedBlock));
|
memcpy((void *) &(dataBlock->m_superBlocks[blockIndex].m_protectedBlock), recoveredBlock, sizeof(RemoteProtectedBlock));
|
||||||
if ((blockIndex == 0) && !dataBlock->m_rxControlBlock.m_metaRetrieved) {
|
if ((blockIndex == 0) && !dataBlock->m_rxControlBlock.m_metaRetrieved) {
|
||||||
dataBlock->m_rxControlBlock.m_metaRetrieved = true;
|
dataBlock->m_rxControlBlock.m_metaRetrieved = true;
|
||||||
}
|
}
|
||||||
@ -318,7 +318,7 @@ void RemoteSource::handleDataBlock(SDRDaemonDataBlock* dataBlock)
|
|||||||
// Validate block zero and retrieve its data
|
// Validate block zero and retrieve its data
|
||||||
if (dataBlock->m_rxControlBlock.m_metaRetrieved)
|
if (dataBlock->m_rxControlBlock.m_metaRetrieved)
|
||||||
{
|
{
|
||||||
SDRDaemonMetaDataFEC *metaData = (SDRDaemonMetaDataFEC *) &(dataBlock->m_superBlocks[0].m_protectedBlock);
|
RemoteMetaDataFEC *metaData = (RemoteMetaDataFEC *) &(dataBlock->m_superBlocks[0].m_protectedBlock);
|
||||||
boost::crc_32_type crc32;
|
boost::crc_32_type crc32;
|
||||||
crc32.process_bytes(metaData, 20);
|
crc32.process_bytes(metaData, 20);
|
||||||
|
|
||||||
@ -349,14 +349,14 @@ void RemoteSource::handleDataBlock(SDRDaemonDataBlock* dataBlock)
|
|||||||
|
|
||||||
void RemoteSource::handleData()
|
void RemoteSource::handleData()
|
||||||
{
|
{
|
||||||
SDRDaemonDataBlock* dataBlock;
|
RemoteDataBlock* dataBlock;
|
||||||
|
|
||||||
while (m_running && ((dataBlock = m_dataQueue.pop()) != 0)) {
|
while (m_running && ((dataBlock = m_dataQueue.pop()) != 0)) {
|
||||||
handleDataBlock(dataBlock);
|
handleDataBlock(dataBlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteSource::printMeta(const QString& header, SDRDaemonMetaDataFEC *metaData)
|
void RemoteSource::printMeta(const QString& header, RemoteMetaDataFEC *metaData)
|
||||||
{
|
{
|
||||||
qDebug().noquote() << header << ": "
|
qDebug().noquote() << header << ": "
|
||||||
<< "|" << metaData->m_centerFrequency
|
<< "|" << metaData->m_centerFrequency
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
#ifndef PLUGINS_CHANNELTX_REMOTESRC_REMOTESRC_H_
|
#ifndef PLUGINS_CHANNELTX_REMOTESRC_REMOTESRC_H_
|
||||||
#define PLUGINS_CHANNELTX_REMOTESRC_REMOTESRC_H_
|
#define PLUGINS_CHANNELTX_REMOTESRC_REMOTESRC_H_
|
||||||
|
|
||||||
|
#include <channel/remotedatablock.h>
|
||||||
|
#include <channel/remotedataqueue.h>
|
||||||
|
#include <channel/remotedatareadqueue.h>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
|
|
||||||
@ -26,17 +29,13 @@
|
|||||||
#include "channel/channelsourceapi.h"
|
#include "channel/channelsourceapi.h"
|
||||||
#include "util/message.h"
|
#include "util/message.h"
|
||||||
|
|
||||||
#include "channel/sdrdaemondataqueue.h"
|
|
||||||
#include "channel/sdrdaemondatablock.h"
|
|
||||||
#include "channel/sdrdaemondatareadqueue.h"
|
|
||||||
|
|
||||||
#include "../remotesource/remotesourcesettings.h"
|
#include "../remotesource/remotesourcesettings.h"
|
||||||
|
|
||||||
class ThreadedBasebandSampleSource;
|
class ThreadedBasebandSampleSource;
|
||||||
class UpChannelizer;
|
class UpChannelizer;
|
||||||
class DeviceSinkAPI;
|
class DeviceSinkAPI;
|
||||||
class RemoteSourceThread;
|
class RemoteSourceThread;
|
||||||
class SDRDaemonDataBlock;
|
class RemoteDataBlock;
|
||||||
class QNetworkAccessManager;
|
class QNetworkAccessManager;
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
|
|
||||||
@ -221,7 +220,7 @@ private:
|
|||||||
DeviceSinkAPI* m_deviceAPI;
|
DeviceSinkAPI* m_deviceAPI;
|
||||||
ThreadedBasebandSampleSource* m_threadedChannelizer;
|
ThreadedBasebandSampleSource* m_threadedChannelizer;
|
||||||
UpChannelizer* m_channelizer;
|
UpChannelizer* m_channelizer;
|
||||||
SDRDaemonDataQueue m_dataQueue;
|
RemoteDataQueue m_dataQueue;
|
||||||
RemoteSourceThread *m_sourceThread;
|
RemoteSourceThread *m_sourceThread;
|
||||||
CM256 m_cm256;
|
CM256 m_cm256;
|
||||||
CM256 *m_cm256p;
|
CM256 *m_cm256p;
|
||||||
@ -229,10 +228,10 @@ private:
|
|||||||
|
|
||||||
RemoteSourceSettings m_settings;
|
RemoteSourceSettings m_settings;
|
||||||
|
|
||||||
CM256::cm256_block m_cm256DescriptorBlocks[2*SDRDaemonNbOrginalBlocks]; //!< CM256 decoder descriptors (block addresses and block indexes)
|
CM256::cm256_block m_cm256DescriptorBlocks[2*RemoteNbOrginalBlocks]; //!< CM256 decoder descriptors (block addresses and block indexes)
|
||||||
SDRDaemonMetaDataFEC m_currentMeta;
|
RemoteMetaDataFEC m_currentMeta;
|
||||||
|
|
||||||
SDRDaemonDataReadQueue m_dataReadQueue;
|
RemoteDataReadQueue m_dataReadQueue;
|
||||||
|
|
||||||
uint32_t m_nbCorrectableErrors; //!< count of correctable errors in number of blocks
|
uint32_t m_nbCorrectableErrors; //!< count of correctable errors in number of blocks
|
||||||
uint32_t m_nbUncorrectableErrors; //!< count of uncorrectable errors in number of blocks
|
uint32_t m_nbUncorrectableErrors; //!< count of uncorrectable errors in number of blocks
|
||||||
@ -241,8 +240,8 @@ private:
|
|||||||
QNetworkRequest m_networkRequest;
|
QNetworkRequest m_networkRequest;
|
||||||
|
|
||||||
void applySettings(const RemoteSourceSettings& settings, bool force = false);
|
void applySettings(const RemoteSourceSettings& settings, bool force = false);
|
||||||
void handleDataBlock(SDRDaemonDataBlock *dataBlock);
|
void handleDataBlock(RemoteDataBlock *dataBlock);
|
||||||
void printMeta(const QString& header, SDRDaemonMetaDataFEC *metaData);
|
void printMeta(const QString& header, RemoteMetaDataFEC *metaData);
|
||||||
uint32_t calculateDataReadQueueSize(int sampleRate);
|
uint32_t calculateDataReadQueueSize(int sampleRate);
|
||||||
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const RemoteSourceSettings& settings);
|
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const RemoteSourceSettings& settings);
|
||||||
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response);
|
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response);
|
||||||
|
@ -16,26 +16,26 @@
|
|||||||
|
|
||||||
#include "remotesourcethread.h"
|
#include "remotesourcethread.h"
|
||||||
|
|
||||||
|
#include <channel/remotedatablock.h>
|
||||||
|
#include <channel/remotedataqueue.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <QUdpSocket>
|
#include <QUdpSocket>
|
||||||
#include "cm256.h"
|
#include "cm256.h"
|
||||||
|
|
||||||
#include "channel/sdrdaemondataqueue.h"
|
|
||||||
#include "channel/sdrdaemondatablock.h"
|
|
||||||
|
|
||||||
|
|
||||||
MESSAGE_CLASS_DEFINITION(RemoteSourceThread::MsgStartStop, Message)
|
MESSAGE_CLASS_DEFINITION(RemoteSourceThread::MsgStartStop, Message)
|
||||||
MESSAGE_CLASS_DEFINITION(RemoteSourceThread::MsgDataBind, Message)
|
MESSAGE_CLASS_DEFINITION(RemoteSourceThread::MsgDataBind, Message)
|
||||||
|
|
||||||
RemoteSourceThread::RemoteSourceThread(SDRDaemonDataQueue *dataQueue, QObject* parent) :
|
RemoteSourceThread::RemoteSourceThread(RemoteDataQueue *dataQueue, QObject* parent) :
|
||||||
QThread(parent),
|
QThread(parent),
|
||||||
m_running(false),
|
m_running(false),
|
||||||
m_dataQueue(dataQueue),
|
m_dataQueue(dataQueue),
|
||||||
m_address(QHostAddress::LocalHost),
|
m_address(QHostAddress::LocalHost),
|
||||||
m_socket(0)
|
m_socket(0)
|
||||||
{
|
{
|
||||||
std::fill(m_dataBlocks, m_dataBlocks+4, (SDRDaemonDataBlock *) 0);
|
std::fill(m_dataBlocks, m_dataBlocks+4, (RemoteDataBlock *) 0);
|
||||||
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
|
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ void RemoteSourceThread::handleInputMessages()
|
|||||||
|
|
||||||
void RemoteSourceThread::readPendingDatagrams()
|
void RemoteSourceThread::readPendingDatagrams()
|
||||||
{
|
{
|
||||||
SDRDaemonSuperBlock superBlock;
|
RemoteSuperBlock superBlock;
|
||||||
qint64 size;
|
qint64 size;
|
||||||
|
|
||||||
while (m_socket->hasPendingDatagrams())
|
while (m_socket->hasPendingDatagrams())
|
||||||
@ -136,15 +136,15 @@ void RemoteSourceThread::readPendingDatagrams()
|
|||||||
QHostAddress sender;
|
QHostAddress sender;
|
||||||
quint16 senderPort = 0;
|
quint16 senderPort = 0;
|
||||||
//qint64 pendingDataSize = m_socket->pendingDatagramSize();
|
//qint64 pendingDataSize = m_socket->pendingDatagramSize();
|
||||||
size = m_socket->readDatagram((char *) &superBlock, (long long int) sizeof(SDRDaemonSuperBlock), &sender, &senderPort);
|
size = m_socket->readDatagram((char *) &superBlock, (long long int) sizeof(RemoteSuperBlock), &sender, &senderPort);
|
||||||
|
|
||||||
if (size == sizeof(SDRDaemonSuperBlock))
|
if (size == sizeof(RemoteSuperBlock))
|
||||||
{
|
{
|
||||||
unsigned int dataBlockIndex = superBlock.m_header.m_frameIndex % m_nbDataBlocks;
|
unsigned int dataBlockIndex = superBlock.m_header.m_frameIndex % m_nbDataBlocks;
|
||||||
|
|
||||||
// create the first block for this index
|
// create the first block for this index
|
||||||
if (m_dataBlocks[dataBlockIndex] == 0) {
|
if (m_dataBlocks[dataBlockIndex] == 0) {
|
||||||
m_dataBlocks[dataBlockIndex] = new SDRDaemonDataBlock();
|
m_dataBlocks[dataBlockIndex] = new RemoteDataBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_dataBlocks[dataBlockIndex]->m_rxControlBlock.m_frameIndex < 0)
|
if (m_dataBlocks[dataBlockIndex]->m_rxControlBlock.m_frameIndex < 0)
|
||||||
@ -159,9 +159,9 @@ void RemoteSourceThread::readPendingDatagrams()
|
|||||||
|
|
||||||
if (superBlock.m_header.m_frameIndex != frameIndex)
|
if (superBlock.m_header.m_frameIndex != frameIndex)
|
||||||
{
|
{
|
||||||
//qDebug("DaemonSourceThread::readPendingDatagrams: push frame %u", frameIndex);
|
//qDebug("RemoteSourceThread::readPendingDatagrams: push frame %u", frameIndex);
|
||||||
m_dataQueue->push(m_dataBlocks[dataBlockIndex]);
|
m_dataQueue->push(m_dataBlocks[dataBlockIndex]);
|
||||||
m_dataBlocks[dataBlockIndex] = new SDRDaemonDataBlock();
|
m_dataBlocks[dataBlockIndex] = new RemoteDataBlock();
|
||||||
m_dataBlocks[dataBlockIndex]->m_rxControlBlock.m_frameIndex = superBlock.m_header.m_frameIndex;
|
m_dataBlocks[dataBlockIndex]->m_rxControlBlock.m_frameIndex = superBlock.m_header.m_frameIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -172,7 +172,7 @@ void RemoteSourceThread::readPendingDatagrams()
|
|||||||
m_dataBlocks[dataBlockIndex]->m_rxControlBlock.m_metaRetrieved = true;
|
m_dataBlocks[dataBlockIndex]->m_rxControlBlock.m_metaRetrieved = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (superBlock.m_header.m_blockIndex < SDRDaemonNbOrginalBlocks) {
|
if (superBlock.m_header.m_blockIndex < RemoteNbOrginalBlocks) {
|
||||||
m_dataBlocks[dataBlockIndex]->m_rxControlBlock.m_originalCount++;
|
m_dataBlocks[dataBlockIndex]->m_rxControlBlock.m_originalCount++;
|
||||||
} else {
|
} else {
|
||||||
m_dataBlocks[dataBlockIndex]->m_rxControlBlock.m_recoveryCount++;
|
m_dataBlocks[dataBlockIndex]->m_rxControlBlock.m_recoveryCount++;
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
#include "util/message.h"
|
#include "util/message.h"
|
||||||
#include "util/messagequeue.h"
|
#include "util/messagequeue.h"
|
||||||
|
|
||||||
class SDRDaemonDataQueue;
|
class RemoteDataQueue;
|
||||||
class SDRDaemonDataBlock;
|
class RemoteDataBlock;
|
||||||
class QUdpSocket;
|
class QUdpSocket;
|
||||||
|
|
||||||
class RemoteSourceThread : public QThread {
|
class RemoteSourceThread : public QThread {
|
||||||
@ -74,7 +74,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
RemoteSourceThread(SDRDaemonDataQueue *dataQueue, QObject* parent = 0);
|
RemoteSourceThread(RemoteDataQueue *dataQueue, QObject* parent = 0);
|
||||||
~RemoteSourceThread();
|
~RemoteSourceThread();
|
||||||
|
|
||||||
void startStop(bool start);
|
void startStop(bool start);
|
||||||
@ -86,13 +86,13 @@ private:
|
|||||||
volatile bool m_running;
|
volatile bool m_running;
|
||||||
|
|
||||||
MessageQueue m_inputMessageQueue;
|
MessageQueue m_inputMessageQueue;
|
||||||
SDRDaemonDataQueue *m_dataQueue;
|
RemoteDataQueue *m_dataQueue;
|
||||||
|
|
||||||
QHostAddress m_address;
|
QHostAddress m_address;
|
||||||
QUdpSocket *m_socket;
|
QUdpSocket *m_socket;
|
||||||
|
|
||||||
static const uint32_t m_nbDataBlocks = 4; //!< number of data blocks in the ring buffer
|
static const uint32_t m_nbDataBlocks = 4; //!< number of data blocks in the ring buffer
|
||||||
SDRDaemonDataBlock *m_dataBlocks[m_nbDataBlocks]; //!< ring buffer of data blocks indexed by frame affinity
|
RemoteDataBlock *m_dataBlocks[m_nbDataBlocks]; //!< ring buffer of data blocks indexed by frame affinity
|
||||||
|
|
||||||
void startWork();
|
void startWork();
|
||||||
void stopWork();
|
void stopWork();
|
||||||
|
@ -25,7 +25,7 @@ endif(LIBUSB_FOUND AND LIBIIO_FOUND)
|
|||||||
|
|
||||||
find_package(CM256cc)
|
find_package(CM256cc)
|
||||||
if(CM256CC_FOUND)
|
if(CM256CC_FOUND)
|
||||||
add_subdirectory(sdrdaemonsink)
|
add_subdirectory(remoteoutput)
|
||||||
endif(CM256CC_FOUND)
|
endif(CM256CC_FOUND)
|
||||||
|
|
||||||
find_package(SoapySDR)
|
find_package(SoapySDR)
|
||||||
@ -44,7 +44,7 @@ if (BUILD_DEBIAN)
|
|||||||
add_subdirectory(hackrfoutput)
|
add_subdirectory(hackrfoutput)
|
||||||
add_subdirectory(limesdroutput)
|
add_subdirectory(limesdroutput)
|
||||||
add_subdirectory(plutosdroutput)
|
add_subdirectory(plutosdroutput)
|
||||||
add_subdirectory(sdrdaemonsink)
|
add_subdirectory(remoteoutput)
|
||||||
add_subdirectory(soapysdroutput)
|
add_subdirectory(soapysdroutput)
|
||||||
endif (BUILD_DEBIAN)
|
endif (BUILD_DEBIAN)
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ This is the Tx filter bandwidth in kHz. Minimum and maximum values are adjusted
|
|||||||
|
|
||||||
This button opens a dialog to set the transverter mode frequency translation options:
|
This button opens a dialog to set the transverter mode frequency translation options:
|
||||||
|
|
||||||
![SDR Daemon source input stream transverter dialog](../../../doc/img/RTLSDR_plugin_xvrt.png)
|
![BladeRF2 source input stream transverter dialog](../../../doc/img/RTLSDR_plugin_xvrt.png)
|
||||||
|
|
||||||
Note that if you mouse over the button a tooltip appears that displays the translating frequency and if translation is enabled or disabled. When the frequency translation is enabled the button is lit.
|
Note that if you mouse over the button a tooltip appears that displays the translating frequency and if translation is enabled or disabled. When the frequency translation is enabled the button is lit.
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ This is the frequency shift applied when the NCO is engaged thus the actual LO f
|
|||||||
|
|
||||||
This button opens a dialog to set the transverter mode frequency translation options:
|
This button opens a dialog to set the transverter mode frequency translation options:
|
||||||
|
|
||||||
![SDR Daemon source input stream transverter dialog](../../../doc/img/RTLSDR_plugin_xvrt.png)
|
![LimeSDR source input stream transverter dialog](../../../doc/img/RTLSDR_plugin_xvrt.png)
|
||||||
|
|
||||||
Note that if you mouse over the button a tooltip appears that displays the translating frequency and if translation is enabled or disabled. When the frequency translation is enabled the button is lit.
|
Note that if you mouse over the button a tooltip appears that displays the translating frequency and if translation is enabled or disabled. When the frequency translation is enabled the button is lit.
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ Use this slider to adjust LO correction in ppm. It can be varied from -20.0 to 2
|
|||||||
|
|
||||||
This button opens a dialog to set the transverter mode frequency translation options:
|
This button opens a dialog to set the transverter mode frequency translation options:
|
||||||
|
|
||||||
![SDR Daemon source input stream transverter dialog](../../../doc/img/RTLSDR_plugin_xvrt.png)
|
![PlutoSDR source input stream transverter dialog](../../../doc/img/RTLSDR_plugin_xvrt.png)
|
||||||
|
|
||||||
Note that if you mouse over the button a tooltip appears that displays the translating frequency and if translation is enabled or disabled. When the frequency translation is enabled the button is lit.
|
Note that if you mouse over the button a tooltip appears that displays the translating frequency and if translation is enabled or disabled. When the frequency translation is enabled the button is lit.
|
||||||
|
|
||||||
|
87
plugins/samplesink/remoteoutput/CMakeLists.txt
Normal file
87
plugins/samplesink/remoteoutput/CMakeLists.txt
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
project(remoteoutput)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||||
|
|
||||||
|
if (HAS_SSSE3)
|
||||||
|
message(STATUS "RemoteFEC: use SSSE3 SIMD" )
|
||||||
|
elseif (HAS_NEON)
|
||||||
|
message(STATUS "RemoteFEC: use Neon SIMD" )
|
||||||
|
else()
|
||||||
|
message(STATUS "RemoteFEC: Unsupported architecture")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(remoteoutput_SOURCES
|
||||||
|
remoteoutputgui.cpp
|
||||||
|
remoteoutput.cpp
|
||||||
|
remoteoutputplugin.cpp
|
||||||
|
remoteoutputsettings.cpp
|
||||||
|
remoteoutputthread.cpp
|
||||||
|
udpsinkfec.cpp
|
||||||
|
udpsinkfecworker.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(remoteoutput_HEADERS
|
||||||
|
remoteoutputgui.h
|
||||||
|
remoteoutput.h
|
||||||
|
remoteoutputplugin.h
|
||||||
|
remoteoutputsettings.h
|
||||||
|
remoteoutputthreads.h
|
||||||
|
udpsinkfec.h
|
||||||
|
udpsinkfecworker.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(remoteoutput_FORMS
|
||||||
|
remoteoutputgui.ui
|
||||||
|
)
|
||||||
|
|
||||||
|
if (BUILD_DEBIAN)
|
||||||
|
include_directories(
|
||||||
|
.
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
|
||||||
|
${LIBCM256CCSRC}
|
||||||
|
)
|
||||||
|
else (BUILD_DEBIAN)
|
||||||
|
include_directories(
|
||||||
|
.
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
|
||||||
|
${CMAKE_SOURCE_DIR}/devices
|
||||||
|
${CM256CC_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
endif (BUILD_DEBIAN)
|
||||||
|
|
||||||
|
add_definitions(${QT_DEFINITIONS})
|
||||||
|
add_definitions(-DQT_PLUGIN)
|
||||||
|
add_definitions(-DQT_SHARED)
|
||||||
|
|
||||||
|
qt5_wrap_ui(remoteoutput_FORMS_HEADERS ${remoteoutput_FORMS})
|
||||||
|
|
||||||
|
add_library(outputremote SHARED
|
||||||
|
${remoteoutput_SOURCES}
|
||||||
|
${remoteoutput_HEADERS_MOC}
|
||||||
|
${remoteoutput_FORMS_HEADERS}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (BUILD_DEBIAN)
|
||||||
|
target_link_libraries(outputremote
|
||||||
|
${QT_LIBRARIES}
|
||||||
|
sdrbase
|
||||||
|
sdrgui
|
||||||
|
swagger
|
||||||
|
cm256cc
|
||||||
|
)
|
||||||
|
else (BUILD_DEBIAN)
|
||||||
|
target_link_libraries(outputremote
|
||||||
|
${QT_LIBRARIES}
|
||||||
|
sdrbase
|
||||||
|
sdrgui
|
||||||
|
swagger
|
||||||
|
${CM256CC_LIBRARIES}
|
||||||
|
)
|
||||||
|
endif (BUILD_DEBIAN)
|
||||||
|
|
||||||
|
target_link_libraries(outputremote Qt5::Core Qt5::Widgets)
|
||||||
|
|
||||||
|
install(TARGETS outputremote DESTINATION lib/plugins/samplesink)
|
@ -1,5 +1,5 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
// SDRdaemon - send I/Q samples read from a SDR device over the network via UDP. //
|
// Remote - send I/Q samples read from a SDR device over the network via UDP. //
|
||||||
// //
|
// //
|
||||||
// Copyright (C) 2015 Edouard Griffiths, F4EXB //
|
// Copyright (C) 2015 Edouard Griffiths, F4EXB //
|
||||||
// //
|
// //
|
||||||
@ -19,6 +19,7 @@
|
|||||||
// Original code is posted at: https://cppcodetips.wordpress.com/2014/01/29/udp-socket-class-in-c/
|
// Original code is posted at: https://cppcodetips.wordpress.com/2014/01/29/udp-socket-class-in-c/
|
||||||
|
|
||||||
#include "UDPSocket.h"
|
#include "UDPSocket.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
@ -1,5 +1,5 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
// SDRdaemon - send I/Q samples read from a SDR device over the network via UDP. //
|
// Remote - send I/Q samples read from a SDR device over the network via UDP. //
|
||||||
// //
|
// //
|
||||||
// Copyright (C) 2015 Edouard Griffiths, F4EXB //
|
// Copyright (C) 2015 Edouard Griffiths, F4EXB //
|
||||||
// //
|
// //
|
@ -1,14 +1,14 @@
|
|||||||
<h1>SDRdaemon sink plugin</h1>
|
<h1>Remote output plugin</h1>
|
||||||
|
|
||||||
<h2>Introduction</h2>
|
<h2>Introduction</h2>
|
||||||
|
|
||||||
This output sample sink plugin sends its samples over tbe network to a SDRangel instance's Daemon source channel using UDP connection.
|
This output sample sink plugin sends its samples over the network to a SDRangel instance's Remote source channel using UDP connection.
|
||||||
|
|
||||||
Forward Error Correction with a Cauchy MDS block erasure codec is used to prevent block loss. This can make the UDP transmission more robust particularly over WiFi links.
|
Forward Error Correction with a Cauchy MDS block erasure codec is used to prevent block loss. This can make the UDP transmission more robust particularly over WiFi links.
|
||||||
|
|
||||||
The distant SDRangel instance to which the data stream is sent is controlled via its REST API using a separate control software for example [SDRangelcli](https://github.com/f4exb/sdrangelcli)
|
The distant SDRangel instance to which the data stream is sent is controlled via its REST API using a separate control software for example [SDRangelcli](https://github.com/f4exb/sdrangelcli)
|
||||||
|
|
||||||
The sample size used in the I/Q stream is the Rx sample size of the local instance. Possible conversion takes place in the distant Daemon source channel plugin to match the Rx sample size of the distant instance. Best performace is obtained when both instances use the same sample size.
|
The sample size used in the I/Q stream is the Rx sample size of the local instance. Possible conversion takes place in the distant Remote source channel plugin to match the Rx sample size of the distant instance. Best performace is obtained when both instances use the same sample size.
|
||||||
|
|
||||||
It is present only in Linux binary releases.
|
It is present only in Linux binary releases.
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ The plugin will be built only if the [CM256cc library](https://github.com/f4exb/
|
|||||||
|
|
||||||
<h2>Interface</h2>
|
<h2>Interface</h2>
|
||||||
|
|
||||||
![SDR Daemon sink output plugin GUI](../../../doc/img/SDRdaemonSink_plugin.png)
|
![SDR Remote output plugin GUI](../../../doc/img/RemoteOutput_plugin.png)
|
||||||
|
|
||||||
<h3>1: Start/Stop</h3>
|
<h3>1: Start/Stop</h3>
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ This is the remote instance baseband sample rate. It can be a power of two multi
|
|||||||
|
|
||||||
<h3>5: Stream controls and API destination</h3>
|
<h3>5: Stream controls and API destination</h3>
|
||||||
|
|
||||||
![SDR Daemon sink output sample rate GUI](../../../doc/img/SDRdaemonSink_plugin_05.png)
|
![SDR Remote output sample rate GUI](../../../doc/img/RemoteOutput_plugin_05.png)
|
||||||
|
|
||||||
<h4>5.1: Network stream sample rate</h4>
|
<h4>5.1: Network stream sample rate</h4>
|
||||||
|
|
||||||
@ -66,11 +66,11 @@ This is the device set index in the remote instance to which the stream is conne
|
|||||||
|
|
||||||
<h4>5.4: remote instance channel index</h4>
|
<h4>5.4: remote instance channel index</h4>
|
||||||
|
|
||||||
This is the channel index of the Daemon source in the remote instance to which the stream is connected to. Use this value to properly address the API to get status.
|
This is the channel index of the Remote source in the remote instance to which the stream is connected to. Use this value to properly address the API to get status.
|
||||||
|
|
||||||
<h3>6: Forward Error Correction setting and status</h3>
|
<h3>6: Forward Error Correction setting and status</h3>
|
||||||
|
|
||||||
![SDR Daemon sink output FEC GUI](../../../doc/img/SDRdaemonSink_plugin_06.png)
|
![SDR Remote output FEC GUI](../../../doc/img/RemoteOutput_plugin_06.png)
|
||||||
|
|
||||||
<h4>6.1: Desired number of FEC blocks per frame</h4>
|
<h4>6.1: Desired number of FEC blocks per frame</h4>
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ This is the detail of the ratio shown in the gauge. Each frame block is a block
|
|||||||
|
|
||||||
<h3>9: Distant server API address and port</h3>
|
<h3>9: Distant server API address and port</h3>
|
||||||
|
|
||||||
![SDR Daemon source input stream GUI](../../../doc/img/SDRdaemonSource_plugin_05.png)
|
![SDR Remote input stream GUI](../../../doc/img/SDRdaemonSource_plugin_05.png)
|
||||||
|
|
||||||
<h4>9.1: API connection indicator</h4>
|
<h4>9.1: API connection indicator</h4>
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ When the return key is hit within the address (9.2) or port (9.3) the changes ar
|
|||||||
|
|
||||||
<h3>10: Local data address and port</h3>
|
<h3>10: Local data address and port</h3>
|
||||||
|
|
||||||
![SDR Daemon source input stream GUI](../../../doc/img/SDRdaemonSource_plugin_06.png)
|
![SDR Remote input stream GUI](../../../doc/img/SDRdaemonSource_plugin_06.png)
|
||||||
|
|
||||||
<h4>10.1: Data IP address</h4>
|
<h4>10.1: Data IP address</h4>
|
||||||
|
|
@ -34,22 +34,22 @@
|
|||||||
|
|
||||||
#include "device/devicesinkapi.h"
|
#include "device/devicesinkapi.h"
|
||||||
|
|
||||||
#include "sdrdaemonsinkoutput.h"
|
#include "remoteoutput.h"
|
||||||
#include "sdrdaemonsinkthread.h"
|
#include "remoteoutputthread.h"
|
||||||
|
|
||||||
MESSAGE_CLASS_DEFINITION(SDRdaemonSinkOutput::MsgConfigureSDRdaemonSink, Message)
|
MESSAGE_CLASS_DEFINITION(RemoteOutput::MsgConfigureRemoteOutput, Message)
|
||||||
MESSAGE_CLASS_DEFINITION(SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkWork, Message)
|
MESSAGE_CLASS_DEFINITION(RemoteOutput::MsgConfigureRemoteOutputWork, Message)
|
||||||
MESSAGE_CLASS_DEFINITION(SDRdaemonSinkOutput::MsgStartStop, Message)
|
MESSAGE_CLASS_DEFINITION(RemoteOutput::MsgStartStop, Message)
|
||||||
MESSAGE_CLASS_DEFINITION(SDRdaemonSinkOutput::MsgConfigureSDRdaemonSinkChunkCorrection, Message)
|
MESSAGE_CLASS_DEFINITION(RemoteOutput::MsgConfigureRemoteOutputChunkCorrection, Message)
|
||||||
|
|
||||||
const uint32_t SDRdaemonSinkOutput::NbSamplesForRateCorrection = 5000000;
|
const uint32_t RemoteOutput::NbSamplesForRateCorrection = 5000000;
|
||||||
|
|
||||||
SDRdaemonSinkOutput::SDRdaemonSinkOutput(DeviceSinkAPI *deviceAPI) :
|
RemoteOutput::RemoteOutput(DeviceSinkAPI *deviceAPI) :
|
||||||
m_deviceAPI(deviceAPI),
|
m_deviceAPI(deviceAPI),
|
||||||
m_settings(),
|
m_settings(),
|
||||||
m_centerFrequency(0),
|
m_centerFrequency(0),
|
||||||
m_sdrDaemonSinkThread(0),
|
m_remoteOutputThread(0),
|
||||||
m_deviceDescription("SDRdaemonSink"),
|
m_deviceDescription("RemoteOutput"),
|
||||||
m_startingTimeStamp(0),
|
m_startingTimeStamp(0),
|
||||||
m_masterTimer(deviceAPI->getMasterTimer()),
|
m_masterTimer(deviceAPI->getMasterTimer()),
|
||||||
m_tickCount(0),
|
m_tickCount(0),
|
||||||
@ -68,29 +68,29 @@ SDRdaemonSinkOutput::SDRdaemonSinkOutput(DeviceSinkAPI *deviceAPI) :
|
|||||||
connect(&m_masterTimer, SIGNAL(timeout()), this, SLOT(tick()));
|
connect(&m_masterTimer, SIGNAL(timeout()), this, SLOT(tick()));
|
||||||
}
|
}
|
||||||
|
|
||||||
SDRdaemonSinkOutput::~SDRdaemonSinkOutput()
|
RemoteOutput::~RemoteOutput()
|
||||||
{
|
{
|
||||||
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
|
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
|
||||||
stop();
|
stop();
|
||||||
delete m_networkManager;
|
delete m_networkManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkOutput::destroy()
|
void RemoteOutput::destroy()
|
||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDRdaemonSinkOutput::start()
|
bool RemoteOutput::start()
|
||||||
{
|
{
|
||||||
QMutexLocker mutexLocker(&m_mutex);
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
qDebug() << "SDRdaemonSinkOutput::start";
|
qDebug() << "RemoteOutput::start";
|
||||||
|
|
||||||
m_sdrDaemonSinkThread = new SDRdaemonSinkThread(&m_sampleSourceFifo);
|
m_remoteOutputThread = new RemoteOutputThread(&m_sampleSourceFifo);
|
||||||
m_sdrDaemonSinkThread->setDataAddress(m_settings.m_dataAddress, m_settings.m_dataPort);
|
m_remoteOutputThread->setDataAddress(m_settings.m_dataAddress, m_settings.m_dataPort);
|
||||||
m_sdrDaemonSinkThread->setSamplerate(m_settings.m_sampleRate);
|
m_remoteOutputThread->setSamplerate(m_settings.m_sampleRate);
|
||||||
m_sdrDaemonSinkThread->setNbBlocksFEC(m_settings.m_nbFECBlocks);
|
m_remoteOutputThread->setNbBlocksFEC(m_settings.m_nbFECBlocks);
|
||||||
m_sdrDaemonSinkThread->connectTimer(m_masterTimer);
|
m_remoteOutputThread->connectTimer(m_masterTimer);
|
||||||
m_sdrDaemonSinkThread->startWork();
|
m_remoteOutputThread->startWork();
|
||||||
|
|
||||||
// restart auto rate correction
|
// restart auto rate correction
|
||||||
m_lastRemoteTimestampRateCorrection = 0;
|
m_lastRemoteTimestampRateCorrection = 0;
|
||||||
@ -98,39 +98,39 @@ bool SDRdaemonSinkOutput::start()
|
|||||||
m_lastQueueLength = -2; // set first value out of bounds
|
m_lastQueueLength = -2; // set first value out of bounds
|
||||||
m_chunkSizeCorrection = 0;
|
m_chunkSizeCorrection = 0;
|
||||||
|
|
||||||
m_sdrDaemonSinkThread->setTxDelay(m_settings.m_txDelay);
|
m_remoteOutputThread->setTxDelay(m_settings.m_txDelay);
|
||||||
|
|
||||||
mutexLocker.unlock();
|
mutexLocker.unlock();
|
||||||
//applySettings(m_generalSettings, m_settings, true);
|
//applySettings(m_generalSettings, m_settings, true);
|
||||||
qDebug("SDRdaemonSinkOutput::start: started");
|
qDebug("RemoteOutput::start: started");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkOutput::init()
|
void RemoteOutput::init()
|
||||||
{
|
{
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkOutput::stop()
|
void RemoteOutput::stop()
|
||||||
{
|
{
|
||||||
qDebug() << "SDRdaemonSinkOutput::stop";
|
qDebug() << "RemoteOutput::stop";
|
||||||
QMutexLocker mutexLocker(&m_mutex);
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
|
|
||||||
if(m_sdrDaemonSinkThread != 0)
|
if(m_remoteOutputThread != 0)
|
||||||
{
|
{
|
||||||
m_sdrDaemonSinkThread->stopWork();
|
m_remoteOutputThread->stopWork();
|
||||||
delete m_sdrDaemonSinkThread;
|
delete m_remoteOutputThread;
|
||||||
m_sdrDaemonSinkThread = 0;
|
m_remoteOutputThread = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray SDRdaemonSinkOutput::serialize() const
|
QByteArray RemoteOutput::serialize() const
|
||||||
{
|
{
|
||||||
return m_settings.serialize();
|
return m_settings.serialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDRdaemonSinkOutput::deserialize(const QByteArray& data)
|
bool RemoteOutput::deserialize(const QByteArray& data)
|
||||||
{
|
{
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
||||||
@ -140,62 +140,62 @@ bool SDRdaemonSinkOutput::deserialize(const QByteArray& data)
|
|||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgConfigureSDRdaemonSink* message = MsgConfigureSDRdaemonSink::create(m_settings, true);
|
MsgConfigureRemoteOutput* message = MsgConfigureRemoteOutput::create(m_settings, true);
|
||||||
m_inputMessageQueue.push(message);
|
m_inputMessageQueue.push(message);
|
||||||
|
|
||||||
if (m_guiMessageQueue)
|
if (m_guiMessageQueue)
|
||||||
{
|
{
|
||||||
MsgConfigureSDRdaemonSink* messageToGUI = MsgConfigureSDRdaemonSink::create(m_settings, true);
|
MsgConfigureRemoteOutput* messageToGUI = MsgConfigureRemoteOutput::create(m_settings, true);
|
||||||
m_guiMessageQueue->push(messageToGUI);
|
m_guiMessageQueue->push(messageToGUI);
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString& SDRdaemonSinkOutput::getDeviceDescription() const
|
const QString& RemoteOutput::getDeviceDescription() const
|
||||||
{
|
{
|
||||||
return m_deviceDescription;
|
return m_deviceDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDRdaemonSinkOutput::getSampleRate() const
|
int RemoteOutput::getSampleRate() const
|
||||||
{
|
{
|
||||||
return m_settings.m_sampleRate;
|
return m_settings.m_sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 SDRdaemonSinkOutput::getCenterFrequency() const
|
quint64 RemoteOutput::getCenterFrequency() const
|
||||||
{
|
{
|
||||||
return m_centerFrequency;
|
return m_centerFrequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::time_t SDRdaemonSinkOutput::getStartingTimeStamp() const
|
std::time_t RemoteOutput::getStartingTimeStamp() const
|
||||||
{
|
{
|
||||||
return m_startingTimeStamp;
|
return m_startingTimeStamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDRdaemonSinkOutput::handleMessage(const Message& message)
|
bool RemoteOutput::handleMessage(const Message& message)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (MsgConfigureSDRdaemonSink::match(message))
|
if (MsgConfigureRemoteOutput::match(message))
|
||||||
{
|
{
|
||||||
qDebug() << "SDRdaemonSinkOutput::handleMessage:" << message.getIdentifier();
|
qDebug() << "RemoteOutput::handleMessage:" << message.getIdentifier();
|
||||||
MsgConfigureSDRdaemonSink& conf = (MsgConfigureSDRdaemonSink&) message;
|
MsgConfigureRemoteOutput& conf = (MsgConfigureRemoteOutput&) message;
|
||||||
applySettings(conf.getSettings(), conf.getForce());
|
applySettings(conf.getSettings(), conf.getForce());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (MsgConfigureSDRdaemonSinkWork::match(message))
|
else if (MsgConfigureRemoteOutputWork::match(message))
|
||||||
{
|
{
|
||||||
MsgConfigureSDRdaemonSinkWork& conf = (MsgConfigureSDRdaemonSinkWork&) message;
|
MsgConfigureRemoteOutputWork& conf = (MsgConfigureRemoteOutputWork&) message;
|
||||||
bool working = conf.isWorking();
|
bool working = conf.isWorking();
|
||||||
|
|
||||||
if (m_sdrDaemonSinkThread != 0)
|
if (m_remoteOutputThread != 0)
|
||||||
{
|
{
|
||||||
if (working)
|
if (working)
|
||||||
{
|
{
|
||||||
m_sdrDaemonSinkThread->startWork();
|
m_remoteOutputThread->startWork();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_sdrDaemonSinkThread->stopWork();
|
m_remoteOutputThread->stopWork();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +204,7 @@ bool SDRdaemonSinkOutput::handleMessage(const Message& message)
|
|||||||
else if (MsgStartStop::match(message))
|
else if (MsgStartStop::match(message))
|
||||||
{
|
{
|
||||||
MsgStartStop& cmd = (MsgStartStop&) message;
|
MsgStartStop& cmd = (MsgStartStop&) message;
|
||||||
qDebug() << "SDRdaemonSinkOutput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
|
qDebug() << "RemoteOutput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
|
||||||
|
|
||||||
if (cmd.getStartStop())
|
if (cmd.getStartStop())
|
||||||
{
|
{
|
||||||
@ -224,13 +224,13 @@ bool SDRdaemonSinkOutput::handleMessage(const Message& message)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (MsgConfigureSDRdaemonSinkChunkCorrection::match(message))
|
else if (MsgConfigureRemoteOutputChunkCorrection::match(message))
|
||||||
{
|
{
|
||||||
MsgConfigureSDRdaemonSinkChunkCorrection& conf = (MsgConfigureSDRdaemonSinkChunkCorrection&) message;
|
MsgConfigureRemoteOutputChunkCorrection& conf = (MsgConfigureRemoteOutputChunkCorrection&) message;
|
||||||
|
|
||||||
if (m_sdrDaemonSinkThread != 0)
|
if (m_remoteOutputThread != 0)
|
||||||
{
|
{
|
||||||
m_sdrDaemonSinkThread->setChunkCorrection(conf.getChunkCorrection());
|
m_remoteOutputThread->setChunkCorrection(conf.getChunkCorrection());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -241,7 +241,7 @@ bool SDRdaemonSinkOutput::handleMessage(const Message& message)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkOutput::applySettings(const SDRdaemonSinkSettings& settings, bool force)
|
void RemoteOutput::applySettings(const RemoteOutputSettings& settings, bool force)
|
||||||
{
|
{
|
||||||
QMutexLocker mutexLocker(&m_mutex);
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
bool forwardChange = false;
|
bool forwardChange = false;
|
||||||
@ -263,8 +263,8 @@ void SDRdaemonSinkOutput::applySettings(const SDRdaemonSinkSettings& settings, b
|
|||||||
|
|
||||||
if (force || (m_settings.m_dataAddress != settings.m_dataAddress) || (m_settings.m_dataPort != settings.m_dataPort))
|
if (force || (m_settings.m_dataAddress != settings.m_dataAddress) || (m_settings.m_dataPort != settings.m_dataPort))
|
||||||
{
|
{
|
||||||
if (m_sdrDaemonSinkThread != 0) {
|
if (m_remoteOutputThread != 0) {
|
||||||
m_sdrDaemonSinkThread->setDataAddress(settings.m_dataAddress, settings.m_dataPort);
|
m_remoteOutputThread->setDataAddress(settings.m_dataAddress, settings.m_dataPort);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,8 +272,8 @@ void SDRdaemonSinkOutput::applySettings(const SDRdaemonSinkSettings& settings, b
|
|||||||
{
|
{
|
||||||
reverseAPIKeys.append("sampleRate");
|
reverseAPIKeys.append("sampleRate");
|
||||||
|
|
||||||
if (m_sdrDaemonSinkThread != 0) {
|
if (m_remoteOutputThread != 0) {
|
||||||
m_sdrDaemonSinkThread->setSamplerate(settings.m_sampleRate);
|
m_remoteOutputThread->setSamplerate(settings.m_sampleRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_tickMultiplier = (21*NbSamplesForRateCorrection) / (2*settings.m_sampleRate); // two times per sample filling period plus small extension
|
m_tickMultiplier = (21*NbSamplesForRateCorrection) / (2*settings.m_sampleRate); // two times per sample filling period plus small extension
|
||||||
@ -287,8 +287,8 @@ void SDRdaemonSinkOutput::applySettings(const SDRdaemonSinkSettings& settings, b
|
|||||||
{
|
{
|
||||||
reverseAPIKeys.append("nbFECBlocks");
|
reverseAPIKeys.append("nbFECBlocks");
|
||||||
|
|
||||||
if (m_sdrDaemonSinkThread != 0) {
|
if (m_remoteOutputThread != 0) {
|
||||||
m_sdrDaemonSinkThread->setNbBlocksFEC(settings.m_nbFECBlocks);
|
m_remoteOutputThread->setNbBlocksFEC(settings.m_nbFECBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
changeTxDelay = true;
|
changeTxDelay = true;
|
||||||
@ -302,14 +302,14 @@ void SDRdaemonSinkOutput::applySettings(const SDRdaemonSinkSettings& settings, b
|
|||||||
|
|
||||||
if (changeTxDelay)
|
if (changeTxDelay)
|
||||||
{
|
{
|
||||||
if (m_sdrDaemonSinkThread != 0) {
|
if (m_remoteOutputThread != 0) {
|
||||||
m_sdrDaemonSinkThread->setTxDelay(settings.m_txDelay);
|
m_remoteOutputThread->setTxDelay(settings.m_txDelay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutexLocker.unlock();
|
mutexLocker.unlock();
|
||||||
|
|
||||||
qDebug() << "SDRdaemonSinkOutput::applySettings:"
|
qDebug() << "RemoteOutput::applySettings:"
|
||||||
<< " m_sampleRate: " << settings.m_sampleRate
|
<< " m_sampleRate: " << settings.m_sampleRate
|
||||||
<< " m_txDelay: " << settings.m_txDelay
|
<< " m_txDelay: " << settings.m_txDelay
|
||||||
<< " m_nbFECBlocks: " << settings.m_nbFECBlocks
|
<< " m_nbFECBlocks: " << settings.m_nbFECBlocks
|
||||||
@ -336,7 +336,7 @@ void SDRdaemonSinkOutput::applySettings(const SDRdaemonSinkSettings& settings, b
|
|||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDRdaemonSinkOutput::webapiRunGet(
|
int RemoteOutput::webapiRunGet(
|
||||||
SWGSDRangel::SWGDeviceState& response,
|
SWGSDRangel::SWGDeviceState& response,
|
||||||
QString& errorMessage)
|
QString& errorMessage)
|
||||||
{
|
{
|
||||||
@ -345,7 +345,7 @@ int SDRdaemonSinkOutput::webapiRunGet(
|
|||||||
return 200;
|
return 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDRdaemonSinkOutput::webapiRun(
|
int RemoteOutput::webapiRun(
|
||||||
bool run,
|
bool run,
|
||||||
SWGSDRangel::SWGDeviceState& response,
|
SWGSDRangel::SWGDeviceState& response,
|
||||||
QString& errorMessage)
|
QString& errorMessage)
|
||||||
@ -364,7 +364,7 @@ int SDRdaemonSinkOutput::webapiRun(
|
|||||||
return 200;
|
return 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDRdaemonSinkOutput::webapiSettingsGet(
|
int RemoteOutput::webapiSettingsGet(
|
||||||
SWGSDRangel::SWGDeviceSettings& response,
|
SWGSDRangel::SWGDeviceSettings& response,
|
||||||
QString& errorMessage)
|
QString& errorMessage)
|
||||||
{
|
{
|
||||||
@ -375,14 +375,14 @@ int SDRdaemonSinkOutput::webapiSettingsGet(
|
|||||||
return 200;
|
return 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDRdaemonSinkOutput::webapiSettingsPutPatch(
|
int RemoteOutput::webapiSettingsPutPatch(
|
||||||
bool force,
|
bool force,
|
||||||
const QStringList& deviceSettingsKeys,
|
const QStringList& deviceSettingsKeys,
|
||||||
SWGSDRangel::SWGDeviceSettings& response, // query + response
|
SWGSDRangel::SWGDeviceSettings& response, // query + response
|
||||||
QString& errorMessage)
|
QString& errorMessage)
|
||||||
{
|
{
|
||||||
(void) errorMessage;
|
(void) errorMessage;
|
||||||
SDRdaemonSinkSettings settings = m_settings;
|
RemoteOutputSettings settings = m_settings;
|
||||||
|
|
||||||
if (deviceSettingsKeys.contains("sampleRate")) {
|
if (deviceSettingsKeys.contains("sampleRate")) {
|
||||||
settings.m_sampleRate = response.getSdrDaemonSinkSettings()->getSampleRate();
|
settings.m_sampleRate = response.getSdrDaemonSinkSettings()->getSampleRate();
|
||||||
@ -424,12 +424,12 @@ int SDRdaemonSinkOutput::webapiSettingsPutPatch(
|
|||||||
settings.m_reverseAPIDeviceIndex = response.getSdrDaemonSinkSettings()->getReverseApiDeviceIndex();
|
settings.m_reverseAPIDeviceIndex = response.getSdrDaemonSinkSettings()->getReverseApiDeviceIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgConfigureSDRdaemonSink *msg = MsgConfigureSDRdaemonSink::create(settings, force);
|
MsgConfigureRemoteOutput *msg = MsgConfigureRemoteOutput::create(settings, force);
|
||||||
m_inputMessageQueue.push(msg);
|
m_inputMessageQueue.push(msg);
|
||||||
|
|
||||||
if (m_guiMessageQueue) // forward to GUI if any
|
if (m_guiMessageQueue) // forward to GUI if any
|
||||||
{
|
{
|
||||||
MsgConfigureSDRdaemonSink *msgToGUI = MsgConfigureSDRdaemonSink::create(settings, force);
|
MsgConfigureRemoteOutput *msgToGUI = MsgConfigureRemoteOutput::create(settings, force);
|
||||||
m_guiMessageQueue->push(msgToGUI);
|
m_guiMessageQueue->push(msgToGUI);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,7 +437,7 @@ int SDRdaemonSinkOutput::webapiSettingsPutPatch(
|
|||||||
return 200;
|
return 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDRdaemonSinkOutput::webapiReportGet(
|
int RemoteOutput::webapiReportGet(
|
||||||
SWGSDRangel::SWGDeviceReport& response,
|
SWGSDRangel::SWGDeviceReport& response,
|
||||||
QString& errorMessage)
|
QString& errorMessage)
|
||||||
{
|
{
|
||||||
@ -448,7 +448,7 @@ int SDRdaemonSinkOutput::webapiReportGet(
|
|||||||
return 200;
|
return 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkOutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const SDRdaemonSinkSettings& settings)
|
void RemoteOutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const RemoteOutputSettings& settings)
|
||||||
{
|
{
|
||||||
response.getSdrDaemonSinkSettings()->setCenterFrequency(m_centerFrequency);
|
response.getSdrDaemonSinkSettings()->setCenterFrequency(m_centerFrequency);
|
||||||
response.getSdrDaemonSinkSettings()->setSampleRate(settings.m_sampleRate);
|
response.getSdrDaemonSinkSettings()->setSampleRate(settings.m_sampleRate);
|
||||||
@ -472,14 +472,14 @@ void SDRdaemonSinkOutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSetti
|
|||||||
response.getSdrDaemonSinkSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex);
|
response.getSdrDaemonSinkSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkOutput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response)
|
void RemoteOutput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response)
|
||||||
{
|
{
|
||||||
uint64_t ts_usecs;
|
uint64_t ts_usecs;
|
||||||
response.getSdrDaemonSinkReport()->setBufferRwBalance(m_sampleSourceFifo.getRWBalance());
|
response.getSdrDaemonSinkReport()->setBufferRwBalance(m_sampleSourceFifo.getRWBalance());
|
||||||
response.getSdrDaemonSinkReport()->setSampleCount(m_sdrDaemonSinkThread ? (int) m_sdrDaemonSinkThread->getSamplesCount(ts_usecs) : 0);
|
response.getSdrDaemonSinkReport()->setSampleCount(m_remoteOutputThread ? (int) m_remoteOutputThread->getSamplesCount(ts_usecs) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkOutput::tick()
|
void RemoteOutput::tick()
|
||||||
{
|
{
|
||||||
if (++m_tickCount == m_tickMultiplier)
|
if (++m_tickCount == m_tickMultiplier)
|
||||||
{
|
{
|
||||||
@ -498,11 +498,11 @@ void SDRdaemonSinkOutput::tick()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkOutput::networkManagerFinished(QNetworkReply *reply)
|
void RemoteOutput::networkManagerFinished(QNetworkReply *reply)
|
||||||
{
|
{
|
||||||
if (reply->error())
|
if (reply->error())
|
||||||
{
|
{
|
||||||
qInfo("SDRdaemonSinkOutput::networkManagerFinished: error: %s", qPrintable(reply->errorString()));
|
qInfo("RemoteOutput::networkManagerFinished: error: %s", qPrintable(reply->errorString()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,24 +521,24 @@ void SDRdaemonSinkOutput::networkManagerFinished(QNetworkReply *reply)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
QString errorMsg = QString("Reply JSON error: ") + error.errorString() + QString(" at offset ") + QString::number(error.offset);
|
QString errorMsg = QString("Reply JSON error: ") + error.errorString() + QString(" at offset ") + QString::number(error.offset);
|
||||||
qInfo().noquote() << "SDRdaemonSinkOutput::networkManagerFinished" << errorMsg;
|
qInfo().noquote() << "RemoteOutput::networkManagerFinished" << errorMsg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const std::exception& ex)
|
catch (const std::exception& ex)
|
||||||
{
|
{
|
||||||
QString errorMsg = QString("Error parsing request: ") + ex.what();
|
QString errorMsg = QString("Error parsing request: ") + ex.what();
|
||||||
qInfo().noquote() << "SDRdaemonSinkOutput::networkManagerFinished" << errorMsg;
|
qInfo().noquote() << "RemoteOutput::networkManagerFinished" << errorMsg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkOutput::analyzeApiReply(const QJsonObject& jsonObject, const QString& answer)
|
void RemoteOutput::analyzeApiReply(const QJsonObject& jsonObject, const QString& answer)
|
||||||
{
|
{
|
||||||
if (jsonObject.contains("DaemonSourceReport"))
|
if (jsonObject.contains("DaemonSourceReport"))
|
||||||
{
|
{
|
||||||
QJsonObject report = jsonObject["DaemonSourceReport"].toObject();
|
QJsonObject report = jsonObject["DaemonSourceReport"].toObject();
|
||||||
m_centerFrequency = report["deviceCenterFreq"].toInt() * 1000;
|
m_centerFrequency = report["deviceCenterFreq"].toInt() * 1000;
|
||||||
|
|
||||||
if (!m_sdrDaemonSinkThread) {
|
if (!m_remoteOutputThread) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,7 +559,7 @@ void SDRdaemonSinkOutput::analyzeApiReply(const QJsonObject& jsonObject, const Q
|
|||||||
|
|
||||||
uint32_t sampleCountDelta, sampleCount;
|
uint32_t sampleCountDelta, sampleCount;
|
||||||
uint64_t timestampUs;
|
uint64_t timestampUs;
|
||||||
sampleCount = m_sdrDaemonSinkThread->getSamplesCount(timestampUs);
|
sampleCount = m_remoteOutputThread->getSamplesCount(timestampUs);
|
||||||
|
|
||||||
if (sampleCount < m_lastSampleCount) {
|
if (sampleCount < m_lastSampleCount) {
|
||||||
sampleCountDelta = (0xFFFFFFFFU - m_lastSampleCount) + sampleCount + 1;
|
sampleCountDelta = (0xFFFFFFFFU - m_lastSampleCount) + sampleCount + 1;
|
||||||
@ -580,7 +580,7 @@ void SDRdaemonSinkOutput::analyzeApiReply(const QJsonObject& jsonObject, const Q
|
|||||||
m_nbRemoteSamplesSinceRateCorrection += remoteSampleCountDelta;
|
m_nbRemoteSamplesSinceRateCorrection += remoteSampleCountDelta;
|
||||||
m_nbSamplesSinceRateCorrection += sampleCountDelta;
|
m_nbSamplesSinceRateCorrection += sampleCountDelta;
|
||||||
|
|
||||||
qDebug("SDRdaemonSinkOutput::analyzeApiReply: queueLengthPercent: %d m_nbSamplesSinceRateCorrection: %u",
|
qDebug("RemoteOutput::analyzeApiReply: queueLengthPercent: %d m_nbSamplesSinceRateCorrection: %u",
|
||||||
queueLengthPercent,
|
queueLengthPercent,
|
||||||
m_nbRemoteSamplesSinceRateCorrection);
|
m_nbRemoteSamplesSinceRateCorrection);
|
||||||
|
|
||||||
@ -603,23 +603,23 @@ void SDRdaemonSinkOutput::analyzeApiReply(const QJsonObject& jsonObject, const Q
|
|||||||
}
|
}
|
||||||
else if (jsonObject.contains("sdrDaemonSinkSettings"))
|
else if (jsonObject.contains("sdrDaemonSinkSettings"))
|
||||||
{
|
{
|
||||||
qDebug("SDRdaemonSinkOutput::analyzeApiReply: reply:\n%s", answer.toStdString().c_str());
|
qDebug("RemoteOutput::analyzeApiReply: reply:\n%s", answer.toStdString().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkOutput::sampleRateCorrection(double remoteTimeDeltaUs, double timeDeltaUs, uint32_t remoteSampleCount, uint32_t sampleCount)
|
void RemoteOutput::sampleRateCorrection(double remoteTimeDeltaUs, double timeDeltaUs, uint32_t remoteSampleCount, uint32_t sampleCount)
|
||||||
{
|
{
|
||||||
double deltaSR = (remoteSampleCount/remoteTimeDeltaUs) - (sampleCount/timeDeltaUs);
|
double deltaSR = (remoteSampleCount/remoteTimeDeltaUs) - (sampleCount/timeDeltaUs);
|
||||||
double chunkCorr = 50000 * deltaSR; // for 50ms chunk intervals (50000us)
|
double chunkCorr = 50000 * deltaSR; // for 50ms chunk intervals (50000us)
|
||||||
m_chunkSizeCorrection += roundf(chunkCorr);
|
m_chunkSizeCorrection += roundf(chunkCorr);
|
||||||
|
|
||||||
qDebug("SDRdaemonSinkOutput::sampleRateCorrection: %d (%f) samples", m_chunkSizeCorrection, chunkCorr);
|
qDebug("RemoteOutput::sampleRateCorrection: %d (%f) samples", m_chunkSizeCorrection, chunkCorr);
|
||||||
|
|
||||||
MsgConfigureSDRdaemonSinkChunkCorrection* message = MsgConfigureSDRdaemonSinkChunkCorrection::create(m_chunkSizeCorrection);
|
MsgConfigureRemoteOutputChunkCorrection* message = MsgConfigureRemoteOutputChunkCorrection::create(m_chunkSizeCorrection);
|
||||||
getInputMessageQueue()->push(message);
|
getInputMessageQueue()->push(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkOutput::webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const SDRdaemonSinkSettings& settings, bool force)
|
void RemoteOutput::webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const RemoteOutputSettings& settings, bool force)
|
||||||
{
|
{
|
||||||
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
|
||||||
swgDeviceSettings->setTx(1);
|
swgDeviceSettings->setTx(1);
|
||||||
@ -675,7 +675,7 @@ void SDRdaemonSinkOutput::webapiReverseSendSettings(QList<QString>& deviceSettin
|
|||||||
delete swgDeviceSettings;
|
delete swgDeviceSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkOutput::webapiReverseSendStartStop(bool start)
|
void RemoteOutput::webapiReverseSendStartStop(bool start)
|
||||||
{
|
{
|
||||||
QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/run")
|
QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/run")
|
||||||
.arg(m_settings.m_reverseAPIAddress)
|
.arg(m_settings.m_reverseAPIAddress)
|
@ -14,8 +14,8 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef INCLUDE_SDRDAEMONSINKOUTPUT_H
|
#ifndef INCLUDE_REMOTEOUTPUT_H
|
||||||
#define INCLUDE_SDRDAEMONSINKOUTPUT_H
|
#define INCLUDE_REMOTEOUTPUT_H
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -28,55 +28,55 @@
|
|||||||
|
|
||||||
#include "dsp/devicesamplesink.h"
|
#include "dsp/devicesamplesink.h"
|
||||||
|
|
||||||
#include "sdrdaemonsinksettings.h"
|
#include "remoteoutputsettings.h"
|
||||||
|
|
||||||
class SDRdaemonSinkThread;
|
class RemoteOutputThread;
|
||||||
class DeviceSinkAPI;
|
class DeviceSinkAPI;
|
||||||
class QNetworkAccessManager;
|
class QNetworkAccessManager;
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
class QJsonObject;
|
class QJsonObject;
|
||||||
|
|
||||||
class SDRdaemonSinkOutput : public DeviceSampleSink {
|
class RemoteOutput : public DeviceSampleSink {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
class MsgConfigureSDRdaemonSink : public Message {
|
class MsgConfigureRemoteOutput : public Message {
|
||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const SDRdaemonSinkSettings& getSettings() const { return m_settings; }
|
const RemoteOutputSettings& getSettings() const { return m_settings; }
|
||||||
bool getForce() const { return m_force; }
|
bool getForce() const { return m_force; }
|
||||||
|
|
||||||
static MsgConfigureSDRdaemonSink* create(const SDRdaemonSinkSettings& settings, bool force = false)
|
static MsgConfigureRemoteOutput* create(const RemoteOutputSettings& settings, bool force = false)
|
||||||
{
|
{
|
||||||
return new MsgConfigureSDRdaemonSink(settings, force);
|
return new MsgConfigureRemoteOutput(settings, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SDRdaemonSinkSettings m_settings;
|
RemoteOutputSettings m_settings;
|
||||||
bool m_force;
|
bool m_force;
|
||||||
|
|
||||||
MsgConfigureSDRdaemonSink(const SDRdaemonSinkSettings& settings, bool force) :
|
MsgConfigureRemoteOutput(const RemoteOutputSettings& settings, bool force) :
|
||||||
Message(),
|
Message(),
|
||||||
m_settings(settings),
|
m_settings(settings),
|
||||||
m_force(force)
|
m_force(force)
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
class MsgConfigureSDRdaemonSinkWork : public Message {
|
class MsgConfigureRemoteOutputWork : public Message {
|
||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool isWorking() const { return m_working; }
|
bool isWorking() const { return m_working; }
|
||||||
|
|
||||||
static MsgConfigureSDRdaemonSinkWork* create(bool working)
|
static MsgConfigureRemoteOutputWork* create(bool working)
|
||||||
{
|
{
|
||||||
return new MsgConfigureSDRdaemonSinkWork(working);
|
return new MsgConfigureRemoteOutputWork(working);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_working;
|
bool m_working;
|
||||||
|
|
||||||
MsgConfigureSDRdaemonSinkWork(bool working) :
|
MsgConfigureRemoteOutputWork(bool working) :
|
||||||
Message(),
|
Message(),
|
||||||
m_working(working)
|
m_working(working)
|
||||||
{ }
|
{ }
|
||||||
@ -101,28 +101,28 @@ public:
|
|||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
class MsgConfigureSDRdaemonSinkChunkCorrection : public Message {
|
class MsgConfigureRemoteOutputChunkCorrection : public Message {
|
||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int getChunkCorrection() const { return m_chunkCorrection; }
|
int getChunkCorrection() const { return m_chunkCorrection; }
|
||||||
|
|
||||||
static MsgConfigureSDRdaemonSinkChunkCorrection* create(int chunkCorrection)
|
static MsgConfigureRemoteOutputChunkCorrection* create(int chunkCorrection)
|
||||||
{
|
{
|
||||||
return new MsgConfigureSDRdaemonSinkChunkCorrection(chunkCorrection);
|
return new MsgConfigureRemoteOutputChunkCorrection(chunkCorrection);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_chunkCorrection;
|
int m_chunkCorrection;
|
||||||
|
|
||||||
MsgConfigureSDRdaemonSinkChunkCorrection(int chunkCorrection) :
|
MsgConfigureRemoteOutputChunkCorrection(int chunkCorrection) :
|
||||||
Message(),
|
Message(),
|
||||||
m_chunkCorrection(chunkCorrection)
|
m_chunkCorrection(chunkCorrection)
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
SDRdaemonSinkOutput(DeviceSinkAPI *deviceAPI);
|
RemoteOutput(DeviceSinkAPI *deviceAPI);
|
||||||
virtual ~SDRdaemonSinkOutput();
|
virtual ~RemoteOutput();
|
||||||
virtual void destroy();
|
virtual void destroy();
|
||||||
|
|
||||||
virtual void init();
|
virtual void init();
|
||||||
@ -167,9 +167,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
DeviceSinkAPI *m_deviceAPI;
|
DeviceSinkAPI *m_deviceAPI;
|
||||||
QMutex m_mutex;
|
QMutex m_mutex;
|
||||||
SDRdaemonSinkSettings m_settings;
|
RemoteOutputSettings m_settings;
|
||||||
uint64_t m_centerFrequency;
|
uint64_t m_centerFrequency;
|
||||||
SDRdaemonSinkThread* m_sdrDaemonSinkThread;
|
RemoteOutputThread* m_remoteOutputThread;
|
||||||
QString m_deviceDescription;
|
QString m_deviceDescription;
|
||||||
std::time_t m_startingTimeStamp;
|
std::time_t m_startingTimeStamp;
|
||||||
const QTimer& m_masterTimer;
|
const QTimer& m_masterTimer;
|
||||||
@ -189,13 +189,13 @@ private:
|
|||||||
int m_chunkSizeCorrection;
|
int m_chunkSizeCorrection;
|
||||||
static const uint32_t NbSamplesForRateCorrection;
|
static const uint32_t NbSamplesForRateCorrection;
|
||||||
|
|
||||||
void applySettings(const SDRdaemonSinkSettings& settings, bool force = false);
|
void applySettings(const RemoteOutputSettings& settings, bool force = false);
|
||||||
void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const SDRdaemonSinkSettings& settings);
|
void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const RemoteOutputSettings& settings);
|
||||||
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
|
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
|
||||||
|
|
||||||
void analyzeApiReply(const QJsonObject& jsonObject, const QString& answer);
|
void analyzeApiReply(const QJsonObject& jsonObject, const QString& answer);
|
||||||
void sampleRateCorrection(double remoteTimeDeltaUs, double timeDeltaUs, uint32_t remoteSampleCount, uint32_t sampleCount);
|
void sampleRateCorrection(double remoteTimeDeltaUs, double timeDeltaUs, uint32_t remoteSampleCount, uint32_t sampleCount);
|
||||||
void webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const SDRdaemonSinkSettings& settings, bool force);
|
void webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const RemoteOutputSettings& settings, bool force);
|
||||||
void webapiReverseSendStartStop(bool start);
|
void webapiReverseSendStartStop(bool start);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
@ -203,4 +203,4 @@ private slots:
|
|||||||
void networkManagerFinished(QNetworkReply *reply);
|
void networkManagerFinished(QNetworkReply *reply);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDE_SDRDAEMONSINKOUTPUT_H
|
#endif // INCLUDE_REMOTEOUTPUT_H
|
@ -9,7 +9,7 @@ CONFIG += plugin
|
|||||||
|
|
||||||
QT += core gui widgets multimedia network opengl
|
QT += core gui widgets multimedia network opengl
|
||||||
|
|
||||||
TARGET = outputsdrdaemonsink
|
TARGET = remoteoutput
|
||||||
|
|
||||||
CONFIG(MINGW32):LIBCM256CCSRC = "C:\softs\cm256cc"
|
CONFIG(MINGW32):LIBCM256CCSRC = "C:\softs\cm256cc"
|
||||||
CONFIG(MSVC):LIBCM256CCSRC = "C:\softs\cm256cc"
|
CONFIG(MSVC):LIBCM256CCSRC = "C:\softs\cm256cc"
|
||||||
@ -38,23 +38,23 @@ CONFIG(MINGW32):INCLUDEPATH += "C:\softs\boost_1_66_0"
|
|||||||
CONFIG(MSVC):INCLUDEPATH += "C:\softs\boost_1_66_0"
|
CONFIG(MSVC):INCLUDEPATH += "C:\softs\boost_1_66_0"
|
||||||
CONFIG(macx):INCLUDEPATH += "../../../boost_1_69_0"
|
CONFIG(macx):INCLUDEPATH += "../../../boost_1_69_0"
|
||||||
|
|
||||||
SOURCES += sdrdaemonsinkthread.cpp\
|
SOURCES += remoteoutputthread.cpp\
|
||||||
sdrdaemonsinkgui.cpp\
|
remoteoutputgui.cpp\
|
||||||
sdrdaemonsinkoutput.cpp\
|
remtoeoutput.cpp\
|
||||||
sdrdaemonsinksettings.cpp\
|
remtoeoutputsettings.cpp\
|
||||||
sdrdaemonsinkplugin.cpp\
|
remoteoutputplugin.cpp\
|
||||||
udpsinkfec.cpp\
|
udpsinkfec.cpp\
|
||||||
udpsinkfecworker.cpp
|
udpsinkfecworker.cpp
|
||||||
|
|
||||||
HEADERS += sdrdaemonsinkthread.h\
|
HEADERS += remoteoutputthread.h\
|
||||||
sdrdaemonsinkgui.h\
|
remoteoutputgui.h\
|
||||||
sdrdaemonsinkoutput.h\
|
remtoeoutput.h\
|
||||||
sdrdaemonsinksettings.h\
|
remtoeoutputsettings.h\
|
||||||
sdrdaemonsinkplugin.h\
|
remoteoutputplugin.h\
|
||||||
udpsinkfec.h\
|
udpsinkfec.h\
|
||||||
udpsinkfecworker.h
|
udpsinkfecworker.h
|
||||||
|
|
||||||
FORMS += sdrdaemonsinkgui.ui
|
FORMS += remoteoutputgui.ui
|
||||||
|
|
||||||
LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase
|
LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase
|
||||||
LIBS += -L../../../sdrgui/$${build_subdir} -lsdrgui
|
LIBS += -L../../../sdrgui/$${build_subdir} -lsdrgui
|
@ -26,7 +26,7 @@
|
|||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
#include "ui_sdrdaemonsinkgui.h"
|
#include "ui_remoteoutputgui.h"
|
||||||
#include "plugin/pluginapi.h"
|
#include "plugin/pluginapi.h"
|
||||||
#include "gui/colormapper.h"
|
#include "gui/colormapper.h"
|
||||||
#include "gui/glspectrum.h"
|
#include "gui/glspectrum.h"
|
||||||
@ -39,13 +39,15 @@
|
|||||||
|
|
||||||
#include "device/devicesinkapi.h"
|
#include "device/devicesinkapi.h"
|
||||||
#include "device/deviceuiset.h"
|
#include "device/deviceuiset.h"
|
||||||
#include "channel/sdrdaemondatablock.h"
|
#include "remoteoutputgui.h"
|
||||||
#include "udpsinkfec.h"
|
|
||||||
#include "sdrdaemonsinkgui.h"
|
|
||||||
|
|
||||||
SDRdaemonSinkGui::SDRdaemonSinkGui(DeviceUISet *deviceUISet, QWidget* parent) :
|
#include <channel/remotedatablock.h>
|
||||||
|
|
||||||
|
#include "udpsinkfec.h"
|
||||||
|
|
||||||
|
RemoteOutputSinkGui::RemoteOutputSinkGui(DeviceUISet *deviceUISet, QWidget* parent) :
|
||||||
QWidget(parent),
|
QWidget(parent),
|
||||||
ui(new Ui::SDRdaemonSinkGui),
|
ui(new Ui::RemoteOutputGui),
|
||||||
m_deviceUISet(deviceUISet),
|
m_deviceUISet(deviceUISet),
|
||||||
m_settings(),
|
m_settings(),
|
||||||
m_deviceSampleSink(0),
|
m_deviceSampleSink(0),
|
||||||
@ -83,7 +85,7 @@ SDRdaemonSinkGui::SDRdaemonSinkGui(DeviceUISet *deviceUISet, QWidget* parent) :
|
|||||||
connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
|
connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
|
||||||
m_statusTimer.start(500);
|
m_statusTimer.start(500);
|
||||||
|
|
||||||
m_deviceSampleSink = (SDRdaemonSinkOutput*) m_deviceUISet->m_deviceSinkAPI->getSampleSink();
|
m_deviceSampleSink = (RemoteOutput*) m_deviceUISet->m_deviceSinkAPI->getSampleSink();
|
||||||
|
|
||||||
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
|
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
|
||||||
|
|
||||||
@ -103,34 +105,34 @@ SDRdaemonSinkGui::SDRdaemonSinkGui(DeviceUISet *deviceUISet, QWidget* parent) :
|
|||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
SDRdaemonSinkGui::~SDRdaemonSinkGui()
|
RemoteOutputSinkGui::~RemoteOutputSinkGui()
|
||||||
{
|
{
|
||||||
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
|
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
|
||||||
delete m_networkManager;
|
delete m_networkManager;
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::blockApplySettings(bool block)
|
void RemoteOutputSinkGui::blockApplySettings(bool block)
|
||||||
{
|
{
|
||||||
m_doApplySettings = !block;
|
m_doApplySettings = !block;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::destroy()
|
void RemoteOutputSinkGui::destroy()
|
||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::setName(const QString& name)
|
void RemoteOutputSinkGui::setName(const QString& name)
|
||||||
{
|
{
|
||||||
setObjectName(name);
|
setObjectName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SDRdaemonSinkGui::getName() const
|
QString RemoteOutputSinkGui::getName() const
|
||||||
{
|
{
|
||||||
return objectName();
|
return objectName();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::resetToDefaults()
|
void RemoteOutputSinkGui::resetToDefaults()
|
||||||
{
|
{
|
||||||
blockApplySettings(true);
|
blockApplySettings(true);
|
||||||
m_settings.resetToDefaults();
|
m_settings.resetToDefaults();
|
||||||
@ -139,12 +141,12 @@ void SDRdaemonSinkGui::resetToDefaults()
|
|||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray SDRdaemonSinkGui::serialize() const
|
QByteArray RemoteOutputSinkGui::serialize() const
|
||||||
{
|
{
|
||||||
return m_settings.serialize();
|
return m_settings.serialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDRdaemonSinkGui::deserialize(const QByteArray& data)
|
bool RemoteOutputSinkGui::deserialize(const QByteArray& data)
|
||||||
{
|
{
|
||||||
blockApplySettings(true);
|
blockApplySettings(true);
|
||||||
|
|
||||||
@ -163,20 +165,20 @@ bool SDRdaemonSinkGui::deserialize(const QByteArray& data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDRdaemonSinkGui::handleMessage(const Message& message)
|
bool RemoteOutputSinkGui::handleMessage(const Message& message)
|
||||||
{
|
{
|
||||||
if (SDRdaemonSinkOutput::MsgConfigureSDRdaemonSink::match(message))
|
if (RemoteOutput::MsgConfigureRemoteOutput::match(message))
|
||||||
{
|
{
|
||||||
const SDRdaemonSinkOutput::MsgConfigureSDRdaemonSink& cfg = (SDRdaemonSinkOutput::MsgConfigureSDRdaemonSink&) message;
|
const RemoteOutput::MsgConfigureRemoteOutput& cfg = (RemoteOutput::MsgConfigureRemoteOutput&) message;
|
||||||
m_settings = cfg.getSettings();
|
m_settings = cfg.getSettings();
|
||||||
blockApplySettings(true);
|
blockApplySettings(true);
|
||||||
displaySettings();
|
displaySettings();
|
||||||
blockApplySettings(false);
|
blockApplySettings(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (SDRdaemonSinkOutput::MsgStartStop::match(message))
|
else if (RemoteOutput::MsgStartStop::match(message))
|
||||||
{
|
{
|
||||||
SDRdaemonSinkOutput::MsgStartStop& notif = (SDRdaemonSinkOutput::MsgStartStop&) message;
|
RemoteOutput::MsgStartStop& notif = (RemoteOutput::MsgStartStop&) message;
|
||||||
blockApplySettings(true);
|
blockApplySettings(true);
|
||||||
ui->startStop->setChecked(notif.getStartStop());
|
ui->startStop->setChecked(notif.getStartStop());
|
||||||
blockApplySettings(false);
|
blockApplySettings(false);
|
||||||
@ -188,7 +190,7 @@ bool SDRdaemonSinkGui::handleMessage(const Message& message)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::handleInputMessages()
|
void RemoteOutputSinkGui::handleInputMessages()
|
||||||
{
|
{
|
||||||
Message* message;
|
Message* message;
|
||||||
|
|
||||||
@ -198,7 +200,7 @@ void SDRdaemonSinkGui::handleInputMessages()
|
|||||||
{
|
{
|
||||||
DSPSignalNotification* notif = (DSPSignalNotification*) message;
|
DSPSignalNotification* notif = (DSPSignalNotification*) message;
|
||||||
m_sampleRate = notif->getSampleRate();
|
m_sampleRate = notif->getSampleRate();
|
||||||
qDebug("SDRdaemonSinkGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency());
|
qDebug("RemoteOutputSinkGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency());
|
||||||
updateSampleRate();
|
updateSampleRate();
|
||||||
|
|
||||||
delete message;
|
delete message;
|
||||||
@ -212,20 +214,20 @@ void SDRdaemonSinkGui::handleInputMessages()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::updateSampleRate()
|
void RemoteOutputSinkGui::updateSampleRate()
|
||||||
{
|
{
|
||||||
m_deviceUISet->getSpectrum()->setSampleRate(m_sampleRate);
|
m_deviceUISet->getSpectrum()->setSampleRate(m_sampleRate);
|
||||||
ui->deviceRateText->setText(tr("%1k").arg((float)(m_sampleRate) / 1000));
|
ui->deviceRateText->setText(tr("%1k").arg((float)(m_sampleRate) / 1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::updateTxDelayTooltip()
|
void RemoteOutputSinkGui::updateTxDelayTooltip()
|
||||||
{
|
{
|
||||||
int samplesPerBlock = SDRDaemonNbBytesPerBlock / (SDR_RX_SAMP_SZ <= 16 ? 4 : 8);
|
int samplesPerBlock = RemoteNbBytesPerBlock / (SDR_RX_SAMP_SZ <= 16 ? 4 : 8);
|
||||||
double delay = ((127*samplesPerBlock*m_settings.m_txDelay) / m_settings.m_sampleRate)/(128 + m_settings.m_nbFECBlocks);
|
double delay = ((127*samplesPerBlock*m_settings.m_txDelay) / m_settings.m_sampleRate)/(128 + m_settings.m_nbFECBlocks);
|
||||||
ui->txDelayText->setToolTip(tr("%1 us").arg(QString::number(delay*1e6, 'f', 0)));
|
ui->txDelayText->setToolTip(tr("%1 us").arg(QString::number(delay*1e6, 'f', 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::displaySettings()
|
void RemoteOutputSinkGui::displaySettings()
|
||||||
{
|
{
|
||||||
blockApplySettings(true);
|
blockApplySettings(true);
|
||||||
ui->centerFrequency->setValue(m_deviceCenterFrequency / 1000);
|
ui->centerFrequency->setValue(m_deviceCenterFrequency / 1000);
|
||||||
@ -247,23 +249,23 @@ void SDRdaemonSinkGui::displaySettings()
|
|||||||
blockApplySettings(false);
|
blockApplySettings(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::sendSettings()
|
void RemoteOutputSinkGui::sendSettings()
|
||||||
{
|
{
|
||||||
if(!m_updateTimer.isActive())
|
if(!m_updateTimer.isActive())
|
||||||
m_updateTimer.start(100);
|
m_updateTimer.start(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SDRdaemonSinkGui::updateHardware()
|
void RemoteOutputSinkGui::updateHardware()
|
||||||
{
|
{
|
||||||
qDebug() << "SDRdaemonSinkGui::updateHardware";
|
qDebug() << "RemoteOutputSinkGui::updateHardware";
|
||||||
SDRdaemonSinkOutput::MsgConfigureSDRdaemonSink* message = SDRdaemonSinkOutput::MsgConfigureSDRdaemonSink::create(m_settings, m_forceSettings);
|
RemoteOutput::MsgConfigureRemoteOutput* message = RemoteOutput::MsgConfigureRemoteOutput::create(m_settings, m_forceSettings);
|
||||||
m_deviceSampleSink->getInputMessageQueue()->push(message);
|
m_deviceSampleSink->getInputMessageQueue()->push(message);
|
||||||
m_forceSettings = false;
|
m_forceSettings = false;
|
||||||
m_updateTimer.stop();
|
m_updateTimer.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::updateStatus()
|
void RemoteOutputSinkGui::updateStatus()
|
||||||
{
|
{
|
||||||
int state = m_deviceUISet->m_deviceSinkAPI->state();
|
int state = m_deviceUISet->m_deviceSinkAPI->state();
|
||||||
|
|
||||||
@ -292,14 +294,14 @@ void SDRdaemonSinkGui::updateStatus()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::on_sampleRate_changed(quint64 value)
|
void RemoteOutputSinkGui::on_sampleRate_changed(quint64 value)
|
||||||
{
|
{
|
||||||
m_settings.m_sampleRate = value;
|
m_settings.m_sampleRate = value;
|
||||||
updateTxDelayTooltip();
|
updateTxDelayTooltip();
|
||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::on_txDelay_valueChanged(int value)
|
void RemoteOutputSinkGui::on_txDelay_valueChanged(int value)
|
||||||
{
|
{
|
||||||
m_settings.m_txDelay = value / 100.0;
|
m_settings.m_txDelay = value / 100.0;
|
||||||
ui->txDelayText->setText(tr("%1").arg(value));
|
ui->txDelayText->setText(tr("%1").arg(value));
|
||||||
@ -307,7 +309,7 @@ void SDRdaemonSinkGui::on_txDelay_valueChanged(int value)
|
|||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::on_nbFECBlocks_valueChanged(int value)
|
void RemoteOutputSinkGui::on_nbFECBlocks_valueChanged(int value)
|
||||||
{
|
{
|
||||||
m_settings.m_nbFECBlocks = value;
|
m_settings.m_nbFECBlocks = value;
|
||||||
int nbOriginalBlocks = 128;
|
int nbOriginalBlocks = 128;
|
||||||
@ -319,7 +321,7 @@ void SDRdaemonSinkGui::on_nbFECBlocks_valueChanged(int value)
|
|||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::on_deviceIndex_returnPressed()
|
void RemoteOutputSinkGui::on_deviceIndex_returnPressed()
|
||||||
{
|
{
|
||||||
bool dataOk;
|
bool dataOk;
|
||||||
int deviceIndex = ui->deviceIndex->text().toInt(&dataOk);
|
int deviceIndex = ui->deviceIndex->text().toInt(&dataOk);
|
||||||
@ -333,7 +335,7 @@ void SDRdaemonSinkGui::on_deviceIndex_returnPressed()
|
|||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::on_channelIndex_returnPressed()
|
void RemoteOutputSinkGui::on_channelIndex_returnPressed()
|
||||||
{
|
{
|
||||||
bool dataOk;
|
bool dataOk;
|
||||||
int channelIndex = ui->channelIndex->text().toInt(&dataOk);
|
int channelIndex = ui->channelIndex->text().toInt(&dataOk);
|
||||||
@ -347,7 +349,7 @@ void SDRdaemonSinkGui::on_channelIndex_returnPressed()
|
|||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::on_apiAddress_returnPressed()
|
void RemoteOutputSinkGui::on_apiAddress_returnPressed()
|
||||||
{
|
{
|
||||||
m_settings.m_apiAddress = ui->apiAddress->text();
|
m_settings.m_apiAddress = ui->apiAddress->text();
|
||||||
sendSettings();
|
sendSettings();
|
||||||
@ -357,7 +359,7 @@ void SDRdaemonSinkGui::on_apiAddress_returnPressed()
|
|||||||
m_networkManager->get(m_networkRequest);
|
m_networkManager->get(m_networkRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::on_apiPort_returnPressed()
|
void RemoteOutputSinkGui::on_apiPort_returnPressed()
|
||||||
{
|
{
|
||||||
bool dataOk;
|
bool dataOk;
|
||||||
int apiPort = ui->apiPort->text().toInt(&dataOk);
|
int apiPort = ui->apiPort->text().toInt(&dataOk);
|
||||||
@ -375,13 +377,13 @@ void SDRdaemonSinkGui::on_apiPort_returnPressed()
|
|||||||
m_networkManager->get(m_networkRequest);
|
m_networkManager->get(m_networkRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::on_dataAddress_returnPressed()
|
void RemoteOutputSinkGui::on_dataAddress_returnPressed()
|
||||||
{
|
{
|
||||||
m_settings.m_dataAddress = ui->dataAddress->text();
|
m_settings.m_dataAddress = ui->dataAddress->text();
|
||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::on_dataPort_returnPressed()
|
void RemoteOutputSinkGui::on_dataPort_returnPressed()
|
||||||
{
|
{
|
||||||
bool dataOk;
|
bool dataOk;
|
||||||
int dataPort = ui->dataPort->text().toInt(&dataOk);
|
int dataPort = ui->dataPort->text().toInt(&dataOk);
|
||||||
@ -395,7 +397,7 @@ void SDRdaemonSinkGui::on_dataPort_returnPressed()
|
|||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::on_apiApplyButton_clicked(bool checked)
|
void RemoteOutputSinkGui::on_apiApplyButton_clicked(bool checked)
|
||||||
{
|
{
|
||||||
(void) checked;
|
(void) checked;
|
||||||
m_settings.m_apiAddress = ui->apiAddress->text();
|
m_settings.m_apiAddress = ui->apiAddress->text();
|
||||||
@ -415,7 +417,7 @@ void SDRdaemonSinkGui::on_apiApplyButton_clicked(bool checked)
|
|||||||
m_networkManager->get(m_networkRequest);
|
m_networkManager->get(m_networkRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::on_dataApplyButton_clicked(bool checked)
|
void RemoteOutputSinkGui::on_dataApplyButton_clicked(bool checked)
|
||||||
{
|
{
|
||||||
(void) checked;
|
(void) checked;
|
||||||
m_settings.m_dataAddress = ui->dataAddress->text();
|
m_settings.m_dataAddress = ui->dataAddress->text();
|
||||||
@ -431,16 +433,16 @@ void SDRdaemonSinkGui::on_dataApplyButton_clicked(bool checked)
|
|||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::on_startStop_toggled(bool checked)
|
void RemoteOutputSinkGui::on_startStop_toggled(bool checked)
|
||||||
{
|
{
|
||||||
if (m_doApplySettings)
|
if (m_doApplySettings)
|
||||||
{
|
{
|
||||||
SDRdaemonSinkOutput::MsgStartStop *message = SDRdaemonSinkOutput::MsgStartStop::create(checked);
|
RemoteOutput::MsgStartStop *message = RemoteOutput::MsgStartStop::create(checked);
|
||||||
m_deviceSampleSink->getInputMessageQueue()->push(message);
|
m_deviceSampleSink->getInputMessageQueue()->push(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::on_eventCountsReset_clicked(bool checked)
|
void RemoteOutputSinkGui::on_eventCountsReset_clicked(bool checked)
|
||||||
{
|
{
|
||||||
(void) checked;
|
(void) checked;
|
||||||
m_countUnrecoverable = 0;
|
m_countUnrecoverable = 0;
|
||||||
@ -450,7 +452,7 @@ void SDRdaemonSinkGui::on_eventCountsReset_clicked(bool checked)
|
|||||||
displayEventTimer();
|
displayEventTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::displayEventCounts()
|
void RemoteOutputSinkGui::displayEventCounts()
|
||||||
{
|
{
|
||||||
QString nstr = QString("%1").arg(m_countUnrecoverable, 3, 10, QChar('0'));
|
QString nstr = QString("%1").arg(m_countUnrecoverable, 3, 10, QChar('0'));
|
||||||
ui->eventUnrecText->setText(nstr);
|
ui->eventUnrecText->setText(nstr);
|
||||||
@ -458,7 +460,7 @@ void SDRdaemonSinkGui::displayEventCounts()
|
|||||||
ui->eventRecText->setText(nstr);
|
ui->eventRecText->setText(nstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::displayEventStatus(int recoverableCount, int unrecoverableCount)
|
void RemoteOutputSinkGui::displayEventStatus(int recoverableCount, int unrecoverableCount)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (unrecoverableCount == 0)
|
if (unrecoverableCount == 0)
|
||||||
@ -475,7 +477,7 @@ void SDRdaemonSinkGui::displayEventStatus(int recoverableCount, int unrecoverabl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::displayEventTimer()
|
void RemoteOutputSinkGui::displayEventTimer()
|
||||||
{
|
{
|
||||||
int elapsedTimeMillis = m_time.elapsed();
|
int elapsedTimeMillis = m_time.elapsed();
|
||||||
QTime recordLength(0, 0, 0, 0);
|
QTime recordLength(0, 0, 0, 0);
|
||||||
@ -484,7 +486,7 @@ void SDRdaemonSinkGui::displayEventTimer()
|
|||||||
ui->eventCountsTimeText->setText(s_time);
|
ui->eventCountsTimeText->setText(s_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::tick()
|
void RemoteOutputSinkGui::tick()
|
||||||
{
|
{
|
||||||
if (++m_tickCount == 20) // once per second
|
if (++m_tickCount == 20) // once per second
|
||||||
{
|
{
|
||||||
@ -504,7 +506,7 @@ void SDRdaemonSinkGui::tick()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::networkManagerFinished(QNetworkReply *reply)
|
void RemoteOutputSinkGui::networkManagerFinished(QNetworkReply *reply)
|
||||||
{
|
{
|
||||||
if (reply->error())
|
if (reply->error())
|
||||||
{
|
{
|
||||||
@ -532,7 +534,7 @@ void SDRdaemonSinkGui::networkManagerFinished(QNetworkReply *reply)
|
|||||||
ui->apiAddressLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }");
|
ui->apiAddressLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }");
|
||||||
QString errorMsg = QString("Reply JSON error: ") + error.errorString() + QString(" at offset ") + QString::number(error.offset);
|
QString errorMsg = QString("Reply JSON error: ") + error.errorString() + QString(" at offset ") + QString::number(error.offset);
|
||||||
ui->statusText->setText(QString("JSON error. See log"));
|
ui->statusText->setText(QString("JSON error. See log"));
|
||||||
qInfo().noquote() << "SDRdaemonSinkGui::networkManagerFinished" << errorMsg;
|
qInfo().noquote() << "RemoteOutputSinkGui::networkManagerFinished" << errorMsg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const std::exception& ex)
|
catch (const std::exception& ex)
|
||||||
@ -540,11 +542,11 @@ void SDRdaemonSinkGui::networkManagerFinished(QNetworkReply *reply)
|
|||||||
ui->apiAddressLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }");
|
ui->apiAddressLabel->setStyleSheet("QLabel { background:rgb(79,79,79); }");
|
||||||
QString errorMsg = QString("Error parsing request: ") + ex.what();
|
QString errorMsg = QString("Error parsing request: ") + ex.what();
|
||||||
ui->statusText->setText("Error parsing request. See log for details");
|
ui->statusText->setText("Error parsing request. See log for details");
|
||||||
qInfo().noquote() << "SDRdaemonSinkGui::networkManagerFinished" << errorMsg;
|
qInfo().noquote() << "RemoteOutputSinkGui::networkManagerFinished" << errorMsg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::analyzeApiReply(const QJsonObject& jsonObject)
|
void RemoteOutputSinkGui::analyzeApiReply(const QJsonObject& jsonObject)
|
||||||
{
|
{
|
||||||
QString infoLine;
|
QString infoLine;
|
||||||
|
|
||||||
@ -629,7 +631,7 @@ void SDRdaemonSinkGui::analyzeApiReply(const QJsonObject& jsonObject)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkGui::openDeviceSettingsDialog(const QPoint& p)
|
void RemoteOutputSinkGui::openDeviceSettingsDialog(const QPoint& p)
|
||||||
{
|
{
|
||||||
BasicDeviceSettingsDialog dialog(this);
|
BasicDeviceSettingsDialog dialog(this);
|
||||||
dialog.setUseReverseAPI(m_settings.m_useReverseAPI);
|
dialog.setUseReverseAPI(m_settings.m_useReverseAPI);
|
@ -14,8 +14,8 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef INCLUDE_SDRDAEMONSINKGUI_H
|
#ifndef INCLUDE_REMOTEOUTPUTGUI_H
|
||||||
#define INCLUDE_SDRDAEMONSINKGUI_H
|
#define INCLUDE_REMOTEOUTPUTGUI_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -28,8 +28,8 @@
|
|||||||
#include "util/messagequeue.h"
|
#include "util/messagequeue.h"
|
||||||
#include "util/limitedcounter.h"
|
#include "util/limitedcounter.h"
|
||||||
|
|
||||||
#include "sdrdaemonsinksettings.h"
|
#include "remoteoutput.h"
|
||||||
#include "sdrdaemonsinkoutput.h"
|
#include "remoteoutputsettings.h"
|
||||||
|
|
||||||
class QNetworkAccessManager;
|
class QNetworkAccessManager;
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
@ -38,12 +38,12 @@ class DeviceSampleSink;
|
|||||||
class DeviceUISet;
|
class DeviceUISet;
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class SDRdaemonSinkGui;
|
class RemoteOutputGui;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SDRdaemonSinkExpAvg {
|
class RemoteOutputExpAvg {
|
||||||
public:
|
public:
|
||||||
SDRdaemonSinkExpAvg(float alpha) :
|
RemoteOutputExpAvg(float alpha) :
|
||||||
m_alpha(alpha),
|
m_alpha(alpha),
|
||||||
m_start(true),
|
m_start(true),
|
||||||
m_s(0)
|
m_s(0)
|
||||||
@ -68,12 +68,12 @@ private:
|
|||||||
float m_s;
|
float m_s;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SDRdaemonSinkGui : public QWidget, public PluginInstanceGUI {
|
class RemoteOutputSinkGui : public QWidget, public PluginInstanceGUI {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SDRdaemonSinkGui(DeviceUISet *deviceUISet, QWidget* parent = 0);
|
explicit RemoteOutputSinkGui(DeviceUISet *deviceUISet, QWidget* parent = 0);
|
||||||
virtual ~SDRdaemonSinkGui();
|
virtual ~RemoteOutputSinkGui();
|
||||||
virtual void destroy();
|
virtual void destroy();
|
||||||
|
|
||||||
void setName(const QString& name);
|
void setName(const QString& name);
|
||||||
@ -88,11 +88,11 @@ public:
|
|||||||
virtual bool handleMessage(const Message& message);
|
virtual bool handleMessage(const Message& message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::SDRdaemonSinkGui* ui;
|
Ui::RemoteOutputGui* ui;
|
||||||
|
|
||||||
DeviceUISet* m_deviceUISet;
|
DeviceUISet* m_deviceUISet;
|
||||||
SDRdaemonSinkSettings m_settings; //!< current settings
|
RemoteOutputSettings m_settings; //!< current settings
|
||||||
SDRdaemonSinkSettings m_controlSettings; //!< settings last sent to device via control port
|
RemoteOutputSettings m_controlSettings; //!< settings last sent to device via control port
|
||||||
QTimer m_updateTimer;
|
QTimer m_updateTimer;
|
||||||
QTimer m_statusTimer;
|
QTimer m_statusTimer;
|
||||||
DeviceSampleSink* m_deviceSampleSink;
|
DeviceSampleSink* m_deviceSampleSink;
|
||||||
@ -157,4 +157,4 @@ private slots:
|
|||||||
void openDeviceSettingsDialog(const QPoint& p);
|
void openDeviceSettingsDialog(const QPoint& p);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDE_FILESINKGUI_H
|
#endif // INCLUDE_REMOTEOUTPUTGUI_H
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<class>SDRdaemonSinkGui</class>
|
<class>RemoteOutputGui</class>
|
||||||
<widget class="QWidget" name="SDRdaemonSinkGui">
|
<widget class="QWidget" name="RemoteOutputGui">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
@ -32,7 +32,7 @@
|
|||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>SDRdaemon Sink</string>
|
<string>Remote Output</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
@ -21,45 +21,45 @@
|
|||||||
#include "device/devicesinkapi.h"
|
#include "device/devicesinkapi.h"
|
||||||
|
|
||||||
#ifdef SERVER_MODE
|
#ifdef SERVER_MODE
|
||||||
#include "sdrdaemonsinkoutput.h"
|
#include "remoteoutput.h"
|
||||||
#else
|
#else
|
||||||
#include "sdrdaemonsinkgui.h"
|
#include "remoteoutputgui.h"
|
||||||
#endif
|
#endif
|
||||||
#include "sdrdaemonsinkplugin.h"
|
#include "remoteoutputplugin.h"
|
||||||
|
|
||||||
const PluginDescriptor SDRdaemonSinkPlugin::m_pluginDescriptor = {
|
const PluginDescriptor RemoteOutputPlugin::m_pluginDescriptor = {
|
||||||
QString("SDRdaemon sink output"),
|
QString("Remote output"),
|
||||||
QString("4.4.1"),
|
QString("4.4.3"),
|
||||||
QString("(c) Edouard Griffiths, F4EXB"),
|
QString("(c) Edouard Griffiths, F4EXB"),
|
||||||
QString("https://github.com/f4exb/sdrangel"),
|
QString("https://github.com/f4exb/sdrangel"),
|
||||||
true,
|
true,
|
||||||
QString("https://github.com/f4exb/sdrangel")
|
QString("https://github.com/f4exb/sdrangel")
|
||||||
};
|
};
|
||||||
|
|
||||||
const QString SDRdaemonSinkPlugin::m_hardwareID = "SDRdaemonSink";
|
const QString RemoteOutputPlugin::m_hardwareID = "RemoteOutput";
|
||||||
const QString SDRdaemonSinkPlugin::m_deviceTypeID = SDRDAEMONSINK_DEVICE_TYPE_ID;
|
const QString RemoteOutputPlugin::m_deviceTypeID = REMOTEOUTPUT_DEVICE_TYPE_ID;
|
||||||
|
|
||||||
SDRdaemonSinkPlugin::SDRdaemonSinkPlugin(QObject* parent) :
|
RemoteOutputPlugin::RemoteOutputPlugin(QObject* parent) :
|
||||||
QObject(parent)
|
QObject(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const PluginDescriptor& SDRdaemonSinkPlugin::getPluginDescriptor() const
|
const PluginDescriptor& RemoteOutputPlugin::getPluginDescriptor() const
|
||||||
{
|
{
|
||||||
return m_pluginDescriptor;
|
return m_pluginDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkPlugin::initPlugin(PluginAPI* pluginAPI)
|
void RemoteOutputPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||||
{
|
{
|
||||||
pluginAPI->registerSampleSink(m_deviceTypeID, this);
|
pluginAPI->registerSampleSink(m_deviceTypeID, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginInterface::SamplingDevices SDRdaemonSinkPlugin::enumSampleSinks()
|
PluginInterface::SamplingDevices RemoteOutputPlugin::enumSampleSinks()
|
||||||
{
|
{
|
||||||
SamplingDevices result;
|
SamplingDevices result;
|
||||||
|
|
||||||
result.append(SamplingDevice(
|
result.append(SamplingDevice(
|
||||||
"SDRdaemonSink",
|
"RemoteOutput",
|
||||||
m_hardwareID,
|
m_hardwareID,
|
||||||
m_deviceTypeID,
|
m_deviceTypeID,
|
||||||
QString::null,
|
QString::null,
|
||||||
@ -73,7 +73,7 @@ PluginInterface::SamplingDevices SDRdaemonSinkPlugin::enumSampleSinks()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SERVER_MODE
|
#ifdef SERVER_MODE
|
||||||
PluginInstanceGUI* SDRdaemonSinkPlugin::createSampleSinkPluginInstanceGUI(
|
PluginInstanceGUI* RemoteOutputPlugin::createSampleSinkPluginInstanceGUI(
|
||||||
const QString& sinkId __attribute((unused)),
|
const QString& sinkId __attribute((unused)),
|
||||||
QWidget **widget __attribute((unused)),
|
QWidget **widget __attribute((unused)),
|
||||||
DeviceUISet *deviceUISet __attribute((unused)))
|
DeviceUISet *deviceUISet __attribute((unused)))
|
||||||
@ -81,14 +81,14 @@ PluginInstanceGUI* SDRdaemonSinkPlugin::createSampleSinkPluginInstanceGUI(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
PluginInstanceGUI* SDRdaemonSinkPlugin::createSampleSinkPluginInstanceGUI(
|
PluginInstanceGUI* RemoteOutputPlugin::createSampleSinkPluginInstanceGUI(
|
||||||
const QString& sinkId,
|
const QString& sinkId,
|
||||||
QWidget **widget,
|
QWidget **widget,
|
||||||
DeviceUISet *deviceUISet)
|
DeviceUISet *deviceUISet)
|
||||||
{
|
{
|
||||||
if(sinkId == m_deviceTypeID)
|
if(sinkId == m_deviceTypeID)
|
||||||
{
|
{
|
||||||
SDRdaemonSinkGui* gui = new SDRdaemonSinkGui(deviceUISet);
|
RemoteOutputSinkGui* gui = new RemoteOutputSinkGui(deviceUISet);
|
||||||
*widget = gui;
|
*widget = gui;
|
||||||
return gui;
|
return gui;
|
||||||
}
|
}
|
||||||
@ -99,11 +99,11 @@ PluginInstanceGUI* SDRdaemonSinkPlugin::createSampleSinkPluginInstanceGUI(
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DeviceSampleSink* SDRdaemonSinkPlugin::createSampleSinkPluginInstanceOutput(const QString& sinkId, DeviceSinkAPI *deviceAPI)
|
DeviceSampleSink* RemoteOutputPlugin::createSampleSinkPluginInstanceOutput(const QString& sinkId, DeviceSinkAPI *deviceAPI)
|
||||||
{
|
{
|
||||||
if(sinkId == m_deviceTypeID)
|
if(sinkId == m_deviceTypeID)
|
||||||
{
|
{
|
||||||
SDRdaemonSinkOutput* output = new SDRdaemonSinkOutput(deviceAPI);
|
RemoteOutput* output = new RemoteOutput(deviceAPI);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
else
|
else
|
@ -14,24 +14,24 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef INCLUDE_SDRDAEMONSINKPLUGIN_H
|
#ifndef INCLUDE_REMOTEOUTPUTPLUGIN_H
|
||||||
#define INCLUDE_SDRDAEMONSINKPLUGIN_H
|
#define INCLUDE_REMOTEOUTPUTPLUGIN_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include "plugin/plugininterface.h"
|
#include "plugin/plugininterface.h"
|
||||||
|
|
||||||
#define SDRDAEMONSINK_DEVICE_TYPE_ID "sdrangel.samplesink.sdrdaemonsink"
|
#define REMOTEOUTPUT_DEVICE_TYPE_ID "sdrangel.samplesink.remoteoutput"
|
||||||
|
|
||||||
class PluginAPI;
|
class PluginAPI;
|
||||||
class DeviceSinkAPI;
|
class DeviceSinkAPI;
|
||||||
|
|
||||||
class SDRdaemonSinkPlugin : public QObject, public PluginInterface {
|
class RemoteOutputPlugin : public QObject, public PluginInterface {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_INTERFACES(PluginInterface)
|
Q_INTERFACES(PluginInterface)
|
||||||
Q_PLUGIN_METADATA(IID SDRDAEMONSINK_DEVICE_TYPE_ID)
|
Q_PLUGIN_METADATA(IID REMOTEOUTPUT_DEVICE_TYPE_ID)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SDRdaemonSinkPlugin(QObject* parent = NULL);
|
explicit RemoteOutputPlugin(QObject* parent = NULL);
|
||||||
|
|
||||||
const PluginDescriptor& getPluginDescriptor() const;
|
const PluginDescriptor& getPluginDescriptor() const;
|
||||||
void initPlugin(PluginAPI* pluginAPI);
|
void initPlugin(PluginAPI* pluginAPI);
|
||||||
@ -50,4 +50,4 @@ private:
|
|||||||
static const PluginDescriptor m_pluginDescriptor;
|
static const PluginDescriptor m_pluginDescriptor;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDE_SDRDAEMONSINKPLUGIN_H
|
#endif // INCLUDE_REMOTEOUTPUTPLUGIN_H
|
@ -15,14 +15,14 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "util/simpleserializer.h"
|
#include "util/simpleserializer.h"
|
||||||
#include "sdrdaemonsinksettings.h"
|
#include "remoteoutputsettings.h"
|
||||||
|
|
||||||
SDRdaemonSinkSettings::SDRdaemonSinkSettings()
|
RemoteOutputSettings::RemoteOutputSettings()
|
||||||
{
|
{
|
||||||
resetToDefaults();
|
resetToDefaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkSettings::resetToDefaults()
|
void RemoteOutputSettings::resetToDefaults()
|
||||||
{
|
{
|
||||||
m_centerFrequency = 435000*1000;
|
m_centerFrequency = 435000*1000;
|
||||||
m_sampleRate = 48000;
|
m_sampleRate = 48000;
|
||||||
@ -40,7 +40,7 @@ void SDRdaemonSinkSettings::resetToDefaults()
|
|||||||
m_reverseAPIDeviceIndex = 0;
|
m_reverseAPIDeviceIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray SDRdaemonSinkSettings::serialize() const
|
QByteArray RemoteOutputSettings::serialize() const
|
||||||
{
|
{
|
||||||
SimpleSerializer s(1);
|
SimpleSerializer s(1);
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ QByteArray SDRdaemonSinkSettings::serialize() const
|
|||||||
return s.final();
|
return s.final();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDRdaemonSinkSettings::deserialize(const QByteArray& data)
|
bool RemoteOutputSettings::deserialize(const QByteArray& data)
|
||||||
{
|
{
|
||||||
SimpleDeserializer d(data);
|
SimpleDeserializer d(data);
|
||||||
|
|
@ -14,12 +14,13 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef PLUGINS_SAMPLESINK_SDRDAEMONSINK_SDRDAEMONSINKSETTINGS_H_
|
#ifndef PLUGINS_REMOTEOUTPUT_REMOTEOUTPUTSETTINGS_H_
|
||||||
#define PLUGINS_SAMPLESINK_SDRDAEMONSINK_SDRDAEMONSINKSETTINGS_H_
|
#define PLUGINS_REMOTEOUTPUT_REMOTEOUTPUTSETTINGS_H_
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
struct SDRdaemonSinkSettings {
|
struct RemoteOutputSettings {
|
||||||
quint64 m_centerFrequency;
|
quint64 m_centerFrequency;
|
||||||
quint32 m_sampleRate;
|
quint32 m_sampleRate;
|
||||||
float m_txDelay;
|
float m_txDelay;
|
||||||
@ -35,10 +36,10 @@ struct SDRdaemonSinkSettings {
|
|||||||
uint16_t m_reverseAPIPort;
|
uint16_t m_reverseAPIPort;
|
||||||
uint16_t m_reverseAPIDeviceIndex;
|
uint16_t m_reverseAPIDeviceIndex;
|
||||||
|
|
||||||
SDRdaemonSinkSettings();
|
RemoteOutputSettings();
|
||||||
void resetToDefaults();
|
void resetToDefaults();
|
||||||
QByteArray serialize() const;
|
QByteArray serialize() const;
|
||||||
bool deserialize(const QByteArray& data);
|
bool deserialize(const QByteArray& data);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PLUGINS_SAMPLESINK_SDRDAEMONSINK_SDRDAEMONSINKSETTINGS_H_ */
|
#endif /* PLUGINS_REMOTEOUTPUT_REMOTEOUTPUTSETTINGS_H_ */
|
@ -22,9 +22,9 @@
|
|||||||
|
|
||||||
#include "dsp/samplesourcefifo.h"
|
#include "dsp/samplesourcefifo.h"
|
||||||
#include "util/timeutil.h"
|
#include "util/timeutil.h"
|
||||||
#include "sdrdaemonsinkthread.h"
|
#include "remoteoutputthread.h"
|
||||||
|
|
||||||
SDRdaemonSinkThread::SDRdaemonSinkThread(SampleSourceFifo* sampleFifo, QObject* parent) :
|
RemoteOutputThread::RemoteOutputThread(SampleSourceFifo* sampleFifo, QObject* parent) :
|
||||||
QThread(parent),
|
QThread(parent),
|
||||||
m_running(false),
|
m_running(false),
|
||||||
m_samplesChunkSize(0),
|
m_samplesChunkSize(0),
|
||||||
@ -32,22 +32,22 @@ SDRdaemonSinkThread::SDRdaemonSinkThread(SampleSourceFifo* sampleFifo, QObject*
|
|||||||
m_samplesCount(0),
|
m_samplesCount(0),
|
||||||
m_chunkCorrection(0),
|
m_chunkCorrection(0),
|
||||||
m_samplerate(0),
|
m_samplerate(0),
|
||||||
m_throttlems(SDRDAEMONSINK_THROTTLE_MS),
|
m_throttlems(REMOTEOUTPUT_THROTTLE_MS),
|
||||||
m_maxThrottlems(50),
|
m_maxThrottlems(50),
|
||||||
m_throttleToggle(false)
|
m_throttleToggle(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SDRdaemonSinkThread::~SDRdaemonSinkThread()
|
RemoteOutputThread::~RemoteOutputThread()
|
||||||
{
|
{
|
||||||
if (m_running) {
|
if (m_running) {
|
||||||
stopWork();
|
stopWork();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkThread::startWork()
|
void RemoteOutputThread::startWork()
|
||||||
{
|
{
|
||||||
qDebug() << "SDRdaemonSinkThread::startWork: ";
|
qDebug() << "RemoteOutputThread::startWork: ";
|
||||||
m_udpSinkFEC.start();
|
m_udpSinkFEC.start();
|
||||||
m_maxThrottlems = 0;
|
m_maxThrottlems = 0;
|
||||||
m_startWaitMutex.lock();
|
m_startWaitMutex.lock();
|
||||||
@ -58,19 +58,19 @@ void SDRdaemonSinkThread::startWork()
|
|||||||
m_startWaitMutex.unlock();
|
m_startWaitMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkThread::stopWork()
|
void RemoteOutputThread::stopWork()
|
||||||
{
|
{
|
||||||
qDebug() << "SDRdaemonSinkThread::stopWork";
|
qDebug() << "RemoteOutputThread::stopWork";
|
||||||
m_running = false;
|
m_running = false;
|
||||||
wait();
|
wait();
|
||||||
m_udpSinkFEC.stop();
|
m_udpSinkFEC.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkThread::setSamplerate(int samplerate)
|
void RemoteOutputThread::setSamplerate(int samplerate)
|
||||||
{
|
{
|
||||||
if (samplerate != m_samplerate)
|
if (samplerate != m_samplerate)
|
||||||
{
|
{
|
||||||
qDebug() << "SDRdaemonSinkThread::setSamplerate:"
|
qDebug() << "RemoteOutputThread::setSamplerate:"
|
||||||
<< " new:" << samplerate
|
<< " new:" << samplerate
|
||||||
<< " old:" << m_samplerate;
|
<< " old:" << m_samplerate;
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ void SDRdaemonSinkThread::setSamplerate(int samplerate)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkThread::run()
|
void RemoteOutputThread::run()
|
||||||
{
|
{
|
||||||
m_running = true;
|
m_running = true;
|
||||||
m_startWaiter.wakeAll();
|
m_startWaiter.wakeAll();
|
||||||
@ -110,13 +110,13 @@ void SDRdaemonSinkThread::run()
|
|||||||
m_running = false;
|
m_running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkThread::connectTimer(const QTimer& timer)
|
void RemoteOutputThread::connectTimer(const QTimer& timer)
|
||||||
{
|
{
|
||||||
qDebug() << "SDRdaemonSinkThread::connectTimer";
|
qDebug() << "RemoteOutputThread::connectTimer";
|
||||||
connect(&timer, SIGNAL(timeout()), this, SLOT(tick()));
|
connect(&timer, SIGNAL(timeout()), this, SLOT(tick()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSinkThread::tick()
|
void RemoteOutputThread::tick()
|
||||||
{
|
{
|
||||||
if (m_running)
|
if (m_running)
|
||||||
{
|
{
|
||||||
@ -140,7 +140,7 @@ void SDRdaemonSinkThread::tick()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t SDRdaemonSinkThread::getSamplesCount(uint64_t& ts_usecs) const
|
uint32_t RemoteOutputThread::getSamplesCount(uint64_t& ts_usecs) const
|
||||||
{
|
{
|
||||||
ts_usecs = TimeUtil::nowus();
|
ts_usecs = TimeUtil::nowus();
|
||||||
return m_samplesCount;
|
return m_samplesCount;
|
@ -14,8 +14,8 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef INCLUDE_SDRDAEMONSINKTHREAD_H
|
#ifndef INCLUDE_REMOTEOUTPUTTHREAD_H
|
||||||
#define INCLUDE_SDRDAEMONSINKTHREAD_H
|
#define INCLUDE_REMOTEOUTPUTTHREAD_H
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -33,17 +33,17 @@
|
|||||||
|
|
||||||
#include "udpsinkfec.h"
|
#include "udpsinkfec.h"
|
||||||
|
|
||||||
#define SDRDAEMONSINK_THROTTLE_MS 50
|
#define REMOTEOUTPUT_THROTTLE_MS 50
|
||||||
|
|
||||||
class SampleSourceFifo;
|
class SampleSourceFifo;
|
||||||
struct timeval;
|
struct timeval;
|
||||||
|
|
||||||
class SDRdaemonSinkThread : public QThread {
|
class RemoteOutputThread : public QThread {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SDRdaemonSinkThread(SampleSourceFifo* sampleFifo, QObject* parent = 0);
|
RemoteOutputThread(SampleSourceFifo* sampleFifo, QObject* parent = 0);
|
||||||
~SDRdaemonSinkThread();
|
~RemoteOutputThread();
|
||||||
|
|
||||||
void startWork();
|
void startWork();
|
||||||
void stopWork();
|
void stopWork();
|
||||||
@ -85,4 +85,4 @@ private slots:
|
|||||||
void tick();
|
void tick();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDE_SDRDAEMONSINKTHREAD_H
|
#endif // INCLUDE_REMOTEOUTPUTTHREAD_H
|
@ -14,13 +14,15 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "udpsinkfec.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include <boost/crc.hpp>
|
#include <boost/crc.hpp>
|
||||||
#include <boost/cstdint.hpp>
|
#include <boost/cstdint.hpp>
|
||||||
|
|
||||||
#include "util/timeutil.h"
|
#include "util/timeutil.h"
|
||||||
#include "udpsinkfec.h"
|
|
||||||
#include "udpsinkfecworker.h"
|
#include "udpsinkfecworker.h"
|
||||||
|
|
||||||
|
|
||||||
@ -38,8 +40,8 @@ UDPSinkFEC::UDPSinkFEC() :
|
|||||||
m_remoteAddress("127.0.0.1"),
|
m_remoteAddress("127.0.0.1"),
|
||||||
m_remotePort(9090)
|
m_remotePort(9090)
|
||||||
{
|
{
|
||||||
memset((char *) m_txBlocks, 0, 4*256*sizeof(SDRDaemonSuperBlock));
|
memset((char *) m_txBlocks, 0, 4*256*sizeof(RemoteSuperBlock));
|
||||||
memset((char *) &m_superBlock, 0, sizeof(SDRDaemonSuperBlock));
|
memset((char *) &m_superBlock, 0, sizeof(RemoteSuperBlock));
|
||||||
m_currentMetaFEC.init();
|
m_currentMetaFEC.init();
|
||||||
m_bufMeta = new uint8_t[m_udpSize];
|
m_bufMeta = new uint8_t[m_udpSize];
|
||||||
m_buf = new uint8_t[m_udpSize];
|
m_buf = new uint8_t[m_udpSize];
|
||||||
@ -75,7 +77,7 @@ void UDPSinkFEC::setTxDelay(float txDelayRatio)
|
|||||||
// divided by sample rate gives the frame process time
|
// divided by sample rate gives the frame process time
|
||||||
// divided by the number of actual blocks including FEC blocks gives the block (i.e. UDP block) process time
|
// divided by the number of actual blocks including FEC blocks gives the block (i.e. UDP block) process time
|
||||||
m_txDelayRatio = txDelayRatio;
|
m_txDelayRatio = txDelayRatio;
|
||||||
int samplesPerBlock = SDRDaemonNbBytesPerBlock / (SDR_RX_SAMP_SZ <= 16 ? 4 : 8);
|
int samplesPerBlock = RemoteNbBytesPerBlock / (SDR_RX_SAMP_SZ <= 16 ? 4 : 8);
|
||||||
double delay = ((127*samplesPerBlock*txDelayRatio) / m_sampleRate)/(128 + m_nbBlocksFEC);
|
double delay = ((127*samplesPerBlock*txDelayRatio) / m_sampleRate)/(128 + m_nbBlocksFEC);
|
||||||
m_txDelay = delay * 1e6;
|
m_txDelay = delay * 1e6;
|
||||||
qDebug() << "UDPSinkFEC::setTxDelay: txDelay: " << txDelayRatio << " m_txDelay: " << m_txDelay << " us";
|
qDebug() << "UDPSinkFEC::setTxDelay: txDelay: " << txDelayRatio << " m_txDelay: " << m_txDelay << " us";
|
||||||
@ -117,7 +119,7 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk
|
|||||||
|
|
||||||
if (m_txBlockIndex == 0) // Tx block index 0 is a block with only meta data
|
if (m_txBlockIndex == 0) // Tx block index 0 is a block with only meta data
|
||||||
{
|
{
|
||||||
SDRDaemonMetaDataFEC metaData;
|
RemoteMetaDataFEC metaData;
|
||||||
|
|
||||||
uint64_t ts_usecs = TimeUtil::nowus();
|
uint64_t ts_usecs = TimeUtil::nowus();
|
||||||
|
|
||||||
@ -142,9 +144,8 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk
|
|||||||
m_superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
m_superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||||
m_superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
m_superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||||
|
|
||||||
SDRDaemonMetaDataFEC *destMeta = (SDRDaemonMetaDataFEC *) &m_superBlock.m_protectedBlock;
|
RemoteMetaDataFEC *destMeta = (RemoteMetaDataFEC *) &m_superBlock.m_protectedBlock;
|
||||||
*destMeta = metaData;
|
*destMeta = metaData;
|
||||||
//memcpy((char *) &m_superBlock.m_protectedBlock, (const char *) &metaData, sizeof(SDRDaemonMetaDataFEC));
|
|
||||||
|
|
||||||
if (!(metaData == m_currentMetaFEC))
|
if (!(metaData == m_currentMetaFEC))
|
||||||
{
|
{
|
||||||
@ -166,7 +167,7 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk
|
|||||||
m_txBlockIndex = 1; // next Tx block with data
|
m_txBlockIndex = 1; // next Tx block with data
|
||||||
}
|
}
|
||||||
|
|
||||||
int samplesPerBlock = SDRDaemonNbBytesPerBlock / (SDR_RX_SAMP_SZ <= 16 ? 4 : 8); // two I or Q samples
|
int samplesPerBlock = RemoteNbBytesPerBlock / (SDR_RX_SAMP_SZ <= 16 ? 4 : 8); // two I or Q samples
|
||||||
|
|
||||||
if (m_sampleIndex + inRemainingSamples < samplesPerBlock) // there is still room in the current super block
|
if (m_sampleIndex + inRemainingSamples < samplesPerBlock) // there is still room in the current super block
|
||||||
{
|
{
|
@ -14,9 +14,10 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef PLUGINS_SAMPLESINK_SDRDAEMONSINK_UDPSINKFEC_H_
|
#ifndef PLUGINS_SAMPLESINK_REMOTEOUTPUT_UDPSINKFEC_H_
|
||||||
#define PLUGINS_SAMPLESINK_SDRDAEMONSINK_UDPSINKFEC_H_
|
#define PLUGINS_SAMPLESINK_REMOTEOUTPUT_UDPSINKFEC_H_
|
||||||
|
|
||||||
|
#include <channel/remotedatablock.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
@ -26,7 +27,6 @@
|
|||||||
|
|
||||||
#include "dsp/dsptypes.h"
|
#include "dsp/dsptypes.h"
|
||||||
#include "util/CRC64.h"
|
#include "util/CRC64.h"
|
||||||
#include "channel/sdrdaemondatablock.h"
|
|
||||||
|
|
||||||
class UDPSinkFECWorker;
|
class UDPSinkFECWorker;
|
||||||
|
|
||||||
@ -86,12 +86,12 @@ private:
|
|||||||
uint8_t* m_bufMeta;
|
uint8_t* m_bufMeta;
|
||||||
uint8_t* m_buf;
|
uint8_t* m_buf;
|
||||||
|
|
||||||
SDRDaemonMetaDataFEC m_currentMetaFEC; //!< Meta data for current frame
|
RemoteMetaDataFEC m_currentMetaFEC; //!< Meta data for current frame
|
||||||
uint32_t m_nbBlocksFEC; //!< Variable number of FEC blocks
|
uint32_t m_nbBlocksFEC; //!< Variable number of FEC blocks
|
||||||
float m_txDelayRatio; //!< Delay in ratio of nominal frame period
|
float m_txDelayRatio; //!< Delay in ratio of nominal frame period
|
||||||
uint32_t m_txDelay; //!< Delay in microseconds (usleep) between each sending of an UDP datagram
|
uint32_t m_txDelay; //!< Delay in microseconds (usleep) between each sending of an UDP datagram
|
||||||
SDRDaemonSuperBlock m_txBlocks[4][256]; //!< UDP blocks to send with original data + FEC
|
RemoteSuperBlock m_txBlocks[4][256]; //!< UDP blocks to send with original data + FEC
|
||||||
SDRDaemonSuperBlock m_superBlock; //!< current super block being built
|
RemoteSuperBlock m_superBlock; //!< current super block being built
|
||||||
int m_txBlockIndex; //!< Current index in blocks to transmit in the Tx row
|
int m_txBlockIndex; //!< Current index in blocks to transmit in the Tx row
|
||||||
int m_txBlocksIndex; //!< Current index of Tx blocks row
|
int m_txBlocksIndex; //!< Current index of Tx blocks row
|
||||||
uint16_t m_frameCount; //!< transmission frame count
|
uint16_t m_frameCount; //!< transmission frame count
|
||||||
@ -102,4 +102,4 @@ private:
|
|||||||
uint16_t m_remotePort;
|
uint16_t m_remotePort;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PLUGINS_SAMPLESINK_SDRDAEMONSINK_UDPSINKFEC_H_ */
|
#endif /* PLUGINS_SAMPLESINK_REMOTEOUTPUT_UDPSINKFEC_H_ */
|
@ -14,9 +14,10 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "udpsinkfecworker.h"
|
||||||
|
|
||||||
#include <QUdpSocket>
|
#include <QUdpSocket>
|
||||||
|
|
||||||
#include "udpsinkfecworker.h"
|
|
||||||
|
|
||||||
MESSAGE_CLASS_DEFINITION(UDPSinkFECWorker::MsgUDPFECEncodeAndSend, Message)
|
MESSAGE_CLASS_DEFINITION(UDPSinkFECWorker::MsgUDPFECEncodeAndSend, Message)
|
||||||
MESSAGE_CLASS_DEFINITION(UDPSinkFECWorker::MsgConfigureRemoteAddress, Message)
|
MESSAGE_CLASS_DEFINITION(UDPSinkFECWorker::MsgConfigureRemoteAddress, Message)
|
||||||
@ -81,7 +82,7 @@ void UDPSinkFECWorker::run()
|
|||||||
qDebug("UDPSinkFECWorker::process: stopped");
|
qDebug("UDPSinkFECWorker::process: stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDPSinkFECWorker::pushTxFrame(SDRDaemonSuperBlock *txBlocks,
|
void UDPSinkFECWorker::pushTxFrame(RemoteSuperBlock *txBlocks,
|
||||||
uint32_t nbBlocksFEC,
|
uint32_t nbBlocksFEC,
|
||||||
uint32_t txDelay,
|
uint32_t txDelay,
|
||||||
uint16_t frameIndex)
|
uint16_t frameIndex)
|
||||||
@ -117,7 +118,7 @@ void UDPSinkFECWorker::handleInputMessages()
|
|||||||
else if (MsgStartStop::match(*message))
|
else if (MsgStartStop::match(*message))
|
||||||
{
|
{
|
||||||
MsgStartStop* notif = (MsgStartStop*) message;
|
MsgStartStop* notif = (MsgStartStop*) message;
|
||||||
qDebug("DaemonSinkThread::handleInputMessages: MsgStartStop: %s", notif->getStartStop() ? "start" : "stop");
|
qDebug("UDPSinkFECWorker::handleInputMessages: MsgStartStop: %s", notif->getStartStop() ? "start" : "stop");
|
||||||
|
|
||||||
if (notif->getStartStop()) {
|
if (notif->getStartStop()) {
|
||||||
startWork();
|
startWork();
|
||||||
@ -130,28 +131,27 @@ void UDPSinkFECWorker::handleInputMessages()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDPSinkFECWorker::encodeAndTransmit(SDRDaemonSuperBlock *txBlockx, uint16_t frameIndex, uint32_t nbBlocksFEC, uint32_t txDelay)
|
void UDPSinkFECWorker::encodeAndTransmit(RemoteSuperBlock *txBlockx, uint16_t frameIndex, uint32_t nbBlocksFEC, uint32_t txDelay)
|
||||||
{
|
{
|
||||||
CM256::cm256_encoder_params cm256Params; //!< Main interface with CM256 encoder
|
CM256::cm256_encoder_params cm256Params; //!< Main interface with CM256 encoder
|
||||||
CM256::cm256_block descriptorBlocks[256]; //!< Pointers to data for CM256 encoder
|
CM256::cm256_block descriptorBlocks[256]; //!< Pointers to data for CM256 encoder
|
||||||
SDRDaemonProtectedBlock fecBlocks[256]; //!< FEC data
|
RemoteProtectedBlock fecBlocks[256]; //!< FEC data
|
||||||
|
|
||||||
if ((nbBlocksFEC == 0) || !m_cm256Valid)
|
if ((nbBlocksFEC == 0) || !m_cm256Valid)
|
||||||
{
|
{
|
||||||
if (m_udpSocket)
|
if (m_udpSocket)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < SDRDaemonNbOrginalBlocks; i++)
|
for (unsigned int i = 0; i < RemoteNbOrginalBlocks; i++)
|
||||||
{
|
{
|
||||||
//m_socket.SendDataGram((const void *) &txBlockx[i], SDRDaemonUdpSize, m_remoteAddress.toStdString(), (uint32_t) m_remotePort);
|
m_udpSocket->writeDatagram((const char *) &txBlockx[i], RemoteUdpSize, m_remoteHostAddress, m_remotePort);
|
||||||
m_udpSocket->writeDatagram((const char *) &txBlockx[i], SDRDaemonUdpSize, m_remoteHostAddress, m_remotePort);
|
|
||||||
usleep(txDelay);
|
usleep(txDelay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cm256Params.BlockBytes = sizeof(SDRDaemonProtectedBlock);
|
cm256Params.BlockBytes = sizeof(RemoteProtectedBlock);
|
||||||
cm256Params.OriginalCount = SDRDaemonNbOrginalBlocks;
|
cm256Params.OriginalCount = RemoteNbOrginalBlocks;
|
||||||
cm256Params.RecoveryCount = nbBlocksFEC;
|
cm256Params.RecoveryCount = nbBlocksFEC;
|
||||||
|
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ void UDPSinkFECWorker::encodeAndTransmit(SDRDaemonSuperBlock *txBlockx, uint16_t
|
|||||||
for (int i = 0; i < cm256Params.OriginalCount + cm256Params.RecoveryCount; ++i)
|
for (int i = 0; i < cm256Params.OriginalCount + cm256Params.RecoveryCount; ++i)
|
||||||
{
|
{
|
||||||
if (i >= cm256Params.OriginalCount) {
|
if (i >= cm256Params.OriginalCount) {
|
||||||
memset((char *) &txBlockx[i].m_protectedBlock, 0, sizeof(SDRDaemonProtectedBlock));
|
memset((char *) &txBlockx[i].m_protectedBlock, 0, sizeof(RemoteProtectedBlock));
|
||||||
}
|
}
|
||||||
|
|
||||||
txBlockx[i].m_header.m_frameIndex = frameIndex;
|
txBlockx[i].m_header.m_frameIndex = frameIndex;
|
||||||
@ -188,13 +188,13 @@ void UDPSinkFECWorker::encodeAndTransmit(SDRDaemonSuperBlock *txBlockx, uint16_t
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < cm256Params.OriginalCount + cm256Params.RecoveryCount; i++)
|
for (int i = 0; i < cm256Params.OriginalCount + cm256Params.RecoveryCount; i++)
|
||||||
{
|
{
|
||||||
#ifdef SDRDAEMON_PUNCTURE
|
#ifdef REMOTE_PUNCTURE
|
||||||
if (i == SDRDAEMON_PUNCTURE) {
|
if (i == REMOTE_PUNCTURE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_udpSocket->writeDatagram((const char *) &txBlockx[i], SDRDaemonUdpSize, m_remoteHostAddress, m_remotePort);
|
m_udpSocket->writeDatagram((const char *) &txBlockx[i], RemoteUdpSize, m_remoteHostAddress, m_remotePort);
|
||||||
usleep(txDelay);
|
usleep(txDelay);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,9 +14,10 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef PLUGINS_SAMPLESINK_SDRDAEMONSINK_UDPSINKFECWORKER_H_
|
#ifndef PLUGINS_SAMPLESINK_REMOTEOUTPUT_UDPSINKFECWORKER_H_
|
||||||
#define PLUGINS_SAMPLESINK_SDRDAEMONSINK_UDPSINKFECWORKER_H_
|
#define PLUGINS_SAMPLESINK_REMOTEOUTPUT_UDPSINKFECWORKER_H_
|
||||||
|
|
||||||
|
#include <channel/remotedatablock.h>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QWaitCondition>
|
#include <QWaitCondition>
|
||||||
@ -26,7 +27,6 @@
|
|||||||
|
|
||||||
#include "util/messagequeue.h"
|
#include "util/messagequeue.h"
|
||||||
#include "util/message.h"
|
#include "util/message.h"
|
||||||
#include "channel/sdrdaemondatablock.h"
|
|
||||||
|
|
||||||
class QUdpSocket;
|
class QUdpSocket;
|
||||||
|
|
||||||
@ -38,13 +38,13 @@ public:
|
|||||||
{
|
{
|
||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
public:
|
public:
|
||||||
SDRDaemonSuperBlock *getTxBlocks() const { return m_txBlockx; }
|
RemoteSuperBlock *getTxBlocks() const { return m_txBlockx; }
|
||||||
uint32_t getNbBlocsFEC() const { return m_nbBlocksFEC; }
|
uint32_t getNbBlocsFEC() const { return m_nbBlocksFEC; }
|
||||||
uint32_t getTxDelay() const { return m_txDelay; }
|
uint32_t getTxDelay() const { return m_txDelay; }
|
||||||
uint16_t getFrameIndex() const { return m_frameIndex; }
|
uint16_t getFrameIndex() const { return m_frameIndex; }
|
||||||
|
|
||||||
static MsgUDPFECEncodeAndSend* create(
|
static MsgUDPFECEncodeAndSend* create(
|
||||||
SDRDaemonSuperBlock *txBlocks,
|
RemoteSuperBlock *txBlocks,
|
||||||
uint32_t nbBlocksFEC,
|
uint32_t nbBlocksFEC,
|
||||||
uint32_t txDelay,
|
uint32_t txDelay,
|
||||||
uint16_t frameIndex)
|
uint16_t frameIndex)
|
||||||
@ -53,13 +53,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SDRDaemonSuperBlock *m_txBlockx;
|
RemoteSuperBlock *m_txBlockx;
|
||||||
uint32_t m_nbBlocksFEC;
|
uint32_t m_nbBlocksFEC;
|
||||||
uint32_t m_txDelay;
|
uint32_t m_txDelay;
|
||||||
uint16_t m_frameIndex;
|
uint16_t m_frameIndex;
|
||||||
|
|
||||||
MsgUDPFECEncodeAndSend(
|
MsgUDPFECEncodeAndSend(
|
||||||
SDRDaemonSuperBlock *txBlocks,
|
RemoteSuperBlock *txBlocks,
|
||||||
uint32_t nbBlocksFEC,
|
uint32_t nbBlocksFEC,
|
||||||
uint32_t txDelay,
|
uint32_t txDelay,
|
||||||
uint16_t frameIndex) :
|
uint16_t frameIndex) :
|
||||||
@ -116,7 +116,7 @@ public:
|
|||||||
|
|
||||||
void startStop(bool start);
|
void startStop(bool start);
|
||||||
|
|
||||||
void pushTxFrame(SDRDaemonSuperBlock *txBlocks,
|
void pushTxFrame(RemoteSuperBlock *txBlocks,
|
||||||
uint32_t nbBlocksFEC,
|
uint32_t nbBlocksFEC,
|
||||||
uint32_t txDelay,
|
uint32_t txDelay,
|
||||||
uint16_t frameIndex);
|
uint16_t frameIndex);
|
||||||
@ -131,7 +131,7 @@ private:
|
|||||||
void startWork();
|
void startWork();
|
||||||
void stopWork();
|
void stopWork();
|
||||||
void run();
|
void run();
|
||||||
void encodeAndTransmit(SDRDaemonSuperBlock *txBlockx, uint16_t frameIndex, uint32_t nbBlocksFEC, uint32_t txDelay);
|
void encodeAndTransmit(RemoteSuperBlock *txBlockx, uint16_t frameIndex, uint32_t nbBlocksFEC, uint32_t txDelay);
|
||||||
|
|
||||||
QMutex m_startWaitMutex;
|
QMutex m_startWaitMutex;
|
||||||
QWaitCondition m_startWaiter;
|
QWaitCondition m_startWaiter;
|
||||||
@ -144,4 +144,4 @@ private:
|
|||||||
QHostAddress m_remoteHostAddress;
|
QHostAddress m_remoteHostAddress;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PLUGINS_SAMPLESINK_SDRDAEMONSINK_UDPSINKFECWORKER_H_ */
|
#endif /* PLUGINS_SAMPLESINK_REMOTEOUTPUT_UDPSINKFECWORKER_H_ */
|
@ -1,87 +0,0 @@
|
|||||||
project(sdrdaemonsink)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
|
||||||
|
|
||||||
if (HAS_SSSE3)
|
|
||||||
message(STATUS "SDRdaemonFEC: use SSSE3 SIMD" )
|
|
||||||
elseif (HAS_NEON)
|
|
||||||
message(STATUS "SDRdaemonFEC: use Neon SIMD" )
|
|
||||||
else()
|
|
||||||
message(STATUS "SDRdaemonFEC: Unsupported architecture")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(sdrdaemonsink_SOURCES
|
|
||||||
sdrdaemonsinkgui.cpp
|
|
||||||
sdrdaemonsinkoutput.cpp
|
|
||||||
sdrdaemonsinkplugin.cpp
|
|
||||||
sdrdaemonsinksettings.cpp
|
|
||||||
sdrdaemonsinkthread.cpp
|
|
||||||
udpsinkfec.cpp
|
|
||||||
udpsinkfecworker.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
set(sdrdaemonsink_HEADERS
|
|
||||||
sdrdaemonsinkgui.h
|
|
||||||
sdrdaemonsinkoutput.h
|
|
||||||
sdrdaemonsinkplugin.h
|
|
||||||
sdrdaemonsinksettings.h
|
|
||||||
sdrdaemonsinkthread.h
|
|
||||||
udpsinkfec.h
|
|
||||||
udpsinkfecworker.h
|
|
||||||
)
|
|
||||||
|
|
||||||
set(sdrdaemonsink_FORMS
|
|
||||||
sdrdaemonsinkgui.ui
|
|
||||||
)
|
|
||||||
|
|
||||||
if (BUILD_DEBIAN)
|
|
||||||
include_directories(
|
|
||||||
.
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
|
|
||||||
${LIBCM256CCSRC}
|
|
||||||
)
|
|
||||||
else (BUILD_DEBIAN)
|
|
||||||
include_directories(
|
|
||||||
.
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
|
|
||||||
${CMAKE_SOURCE_DIR}/devices
|
|
||||||
${CM256CC_INCLUDE_DIR}
|
|
||||||
)
|
|
||||||
endif (BUILD_DEBIAN)
|
|
||||||
|
|
||||||
add_definitions(${QT_DEFINITIONS})
|
|
||||||
add_definitions(-DQT_PLUGIN)
|
|
||||||
add_definitions(-DQT_SHARED)
|
|
||||||
|
|
||||||
qt5_wrap_ui(sdrdaemonsink_FORMS_HEADERS ${sdrdaemonsink_FORMS})
|
|
||||||
|
|
||||||
add_library(outputsdrdaemonsink SHARED
|
|
||||||
${sdrdaemonsink_SOURCES}
|
|
||||||
${sdrdaemonsink_HEADERS_MOC}
|
|
||||||
${sdrdaemonsink_FORMS_HEADERS}
|
|
||||||
)
|
|
||||||
|
|
||||||
if (BUILD_DEBIAN)
|
|
||||||
target_link_libraries(outputsdrdaemonsink
|
|
||||||
${QT_LIBRARIES}
|
|
||||||
sdrbase
|
|
||||||
sdrgui
|
|
||||||
swagger
|
|
||||||
cm256cc
|
|
||||||
)
|
|
||||||
else (BUILD_DEBIAN)
|
|
||||||
target_link_libraries(outputsdrdaemonsink
|
|
||||||
${QT_LIBRARIES}
|
|
||||||
sdrbase
|
|
||||||
sdrgui
|
|
||||||
swagger
|
|
||||||
${CM256CC_LIBRARIES}
|
|
||||||
)
|
|
||||||
endif (BUILD_DEBIAN)
|
|
||||||
|
|
||||||
target_link_libraries(outputsdrdaemonsink Qt5::Core Qt5::Widgets)
|
|
||||||
|
|
||||||
install(TARGETS outputsdrdaemonsink DESTINATION lib/plugins/samplesink)
|
|
@ -50,8 +50,8 @@ SDRdaemonSourceBuffer::SDRdaemonSourceBuffer() :
|
|||||||
m_tvOut_sec = 0;
|
m_tvOut_sec = 0;
|
||||||
m_tvOut_usec = 0;
|
m_tvOut_usec = 0;
|
||||||
m_readNbBytes = 1;
|
m_readNbBytes = 1;
|
||||||
m_paramsCM256.BlockBytes = sizeof(SDRDaemonProtectedBlock); // never changes
|
m_paramsCM256.BlockBytes = sizeof(RemoteProtectedBlock); // never changes
|
||||||
m_paramsCM256.OriginalCount = SDRDaemonNbOrginalBlocks; // never changes
|
m_paramsCM256.OriginalCount = RemoteNbOrginalBlocks; // never changes
|
||||||
|
|
||||||
if (!m_cm256.isInitialized()) {
|
if (!m_cm256.isInitialized()) {
|
||||||
m_cm256_OK = false;
|
m_cm256_OK = false;
|
||||||
@ -81,7 +81,7 @@ void SDRdaemonSourceBuffer::initDecodeAllSlots()
|
|||||||
m_decoderSlots[i].m_decoded = false;
|
m_decoderSlots[i].m_decoded = false;
|
||||||
m_decoderSlots[i].m_metaRetrieved = false;
|
m_decoderSlots[i].m_metaRetrieved = false;
|
||||||
resetOriginalBlocks(i);
|
resetOriginalBlocks(i);
|
||||||
memset((void *) m_decoderSlots[i].m_recoveryBlocks, 0, SDRDaemonNbOrginalBlocks * sizeof(SDRDaemonProtectedBlock));
|
memset((void *) m_decoderSlots[i].m_recoveryBlocks, 0, RemoteNbOrginalBlocks * sizeof(RemoteProtectedBlock));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ void SDRdaemonSourceBuffer::initDecodeSlot(int slotIndex)
|
|||||||
m_decoderSlots[slotIndex].m_metaRetrieved = false;
|
m_decoderSlots[slotIndex].m_metaRetrieved = false;
|
||||||
|
|
||||||
resetOriginalBlocks(slotIndex);
|
resetOriginalBlocks(slotIndex);
|
||||||
memset((void *) m_decoderSlots[slotIndex].m_recoveryBlocks, 0, SDRDaemonNbOrginalBlocks * sizeof(SDRDaemonProtectedBlock));
|
memset((void *) m_decoderSlots[slotIndex].m_recoveryBlocks, 0, RemoteNbOrginalBlocks * sizeof(RemoteProtectedBlock));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSourceBuffer::initReadIndex()
|
void SDRdaemonSourceBuffer::initReadIndex()
|
||||||
@ -190,7 +190,7 @@ void SDRdaemonSourceBuffer::checkSlotData(int slotIndex)
|
|||||||
|
|
||||||
void SDRdaemonSourceBuffer::writeData(char *array)
|
void SDRdaemonSourceBuffer::writeData(char *array)
|
||||||
{
|
{
|
||||||
SDRDaemonSuperBlock *superBlock = (SDRDaemonSuperBlock *) array;
|
RemoteSuperBlock *superBlock = (RemoteSuperBlock *) array;
|
||||||
int frameIndex = superBlock->m_header.m_frameIndex;
|
int frameIndex = superBlock->m_header.m_frameIndex;
|
||||||
int decoderIndex = frameIndex % nbDecoderSlots;
|
int decoderIndex = frameIndex % nbDecoderSlots;
|
||||||
|
|
||||||
@ -214,7 +214,7 @@ void SDRdaemonSourceBuffer::writeData(char *array)
|
|||||||
|
|
||||||
// Block processing
|
// Block processing
|
||||||
|
|
||||||
if (m_decoderSlots[decoderIndex].m_blockCount < SDRDaemonNbOrginalBlocks) // not enough blocks to decode -> store data
|
if (m_decoderSlots[decoderIndex].m_blockCount < RemoteNbOrginalBlocks) // not enough blocks to decode -> store data
|
||||||
{
|
{
|
||||||
int blockIndex = superBlock->m_header.m_blockIndex;
|
int blockIndex = superBlock->m_header.m_blockIndex;
|
||||||
int blockCount = m_decoderSlots[decoderIndex].m_blockCount;
|
int blockCount = m_decoderSlots[decoderIndex].m_blockCount;
|
||||||
@ -226,7 +226,7 @@ void SDRdaemonSourceBuffer::writeData(char *array)
|
|||||||
m_decoderSlots[decoderIndex].m_metaRetrieved = true;
|
m_decoderSlots[decoderIndex].m_metaRetrieved = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockIndex < SDRDaemonNbOrginalBlocks) // original data
|
if (blockIndex < RemoteNbOrginalBlocks) // original data
|
||||||
{
|
{
|
||||||
m_decoderSlots[decoderIndex].m_cm256DescriptorBlocks[blockCount].Block = (void *) storeOriginalBlock(decoderIndex, blockIndex, superBlock->m_protectedBlock);
|
m_decoderSlots[decoderIndex].m_cm256DescriptorBlocks[blockCount].Block = (void *) storeOriginalBlock(decoderIndex, blockIndex, superBlock->m_protectedBlock);
|
||||||
m_decoderSlots[decoderIndex].m_originalCount++;
|
m_decoderSlots[decoderIndex].m_originalCount++;
|
||||||
@ -241,14 +241,14 @@ void SDRdaemonSourceBuffer::writeData(char *array)
|
|||||||
|
|
||||||
m_decoderSlots[decoderIndex].m_blockCount++;
|
m_decoderSlots[decoderIndex].m_blockCount++;
|
||||||
|
|
||||||
if (m_decoderSlots[decoderIndex].m_blockCount == SDRDaemonNbOrginalBlocks) // ready to decode
|
if (m_decoderSlots[decoderIndex].m_blockCount == RemoteNbOrginalBlocks) // ready to decode
|
||||||
{
|
{
|
||||||
m_decoderSlots[decoderIndex].m_decoded = true;
|
m_decoderSlots[decoderIndex].m_decoded = true;
|
||||||
|
|
||||||
if (m_cm256_OK && (m_decoderSlots[decoderIndex].m_recoveryCount > 0)) // recovery data used => need to decode FEC
|
if (m_cm256_OK && (m_decoderSlots[decoderIndex].m_recoveryCount > 0)) // recovery data used => need to decode FEC
|
||||||
{
|
{
|
||||||
m_paramsCM256.BlockBytes = sizeof(SDRDaemonProtectedBlock); // never changes
|
m_paramsCM256.BlockBytes = sizeof(RemoteProtectedBlock); // never changes
|
||||||
m_paramsCM256.OriginalCount = SDRDaemonNbOrginalBlocks; // never changes
|
m_paramsCM256.OriginalCount = RemoteNbOrginalBlocks; // never changes
|
||||||
|
|
||||||
if (m_decoderSlots[decoderIndex].m_metaRetrieved) {
|
if (m_decoderSlots[decoderIndex].m_metaRetrieved) {
|
||||||
m_paramsCM256.RecoveryCount = m_currentMeta.m_nbFECBlocks;
|
m_paramsCM256.RecoveryCount = m_currentMeta.m_nbFECBlocks;
|
||||||
@ -274,13 +274,13 @@ void SDRdaemonSourceBuffer::writeData(char *array)
|
|||||||
|
|
||||||
for (int ir = 0; ir < m_decoderSlots[decoderIndex].m_recoveryCount; ir++) // restore missing blocks
|
for (int ir = 0; ir < m_decoderSlots[decoderIndex].m_recoveryCount; ir++) // restore missing blocks
|
||||||
{
|
{
|
||||||
int recoveryIndex = SDRDaemonNbOrginalBlocks - m_decoderSlots[decoderIndex].m_recoveryCount + ir;
|
int recoveryIndex = RemoteNbOrginalBlocks - m_decoderSlots[decoderIndex].m_recoveryCount + ir;
|
||||||
int blockIndex = m_decoderSlots[decoderIndex].m_cm256DescriptorBlocks[recoveryIndex].Index;
|
int blockIndex = m_decoderSlots[decoderIndex].m_cm256DescriptorBlocks[recoveryIndex].Index;
|
||||||
SDRDaemonProtectedBlock *recoveredBlock = (SDRDaemonProtectedBlock *) m_decoderSlots[decoderIndex].m_cm256DescriptorBlocks[recoveryIndex].Block;
|
RemoteProtectedBlock *recoveredBlock = (RemoteProtectedBlock *) m_decoderSlots[decoderIndex].m_cm256DescriptorBlocks[recoveryIndex].Block;
|
||||||
|
|
||||||
if (blockIndex == 0) // first block with meta
|
if (blockIndex == 0) // first block with meta
|
||||||
{
|
{
|
||||||
SDRDaemonMetaDataFEC *metaData = (SDRDaemonMetaDataFEC *) recoveredBlock;
|
RemoteMetaDataFEC *metaData = (RemoteMetaDataFEC *) recoveredBlock;
|
||||||
|
|
||||||
boost::crc_32_type crc32;
|
boost::crc_32_type crc32;
|
||||||
crc32.process_bytes(metaData, 20);
|
crc32.process_bytes(metaData, 20);
|
||||||
@ -305,7 +305,7 @@ void SDRdaemonSourceBuffer::writeData(char *array)
|
|||||||
|
|
||||||
if (m_decoderSlots[decoderIndex].m_metaRetrieved) // block zero with its meta data has been received
|
if (m_decoderSlots[decoderIndex].m_metaRetrieved) // block zero with its meta data has been received
|
||||||
{
|
{
|
||||||
SDRDaemonMetaDataFEC *metaData = getMetaData(decoderIndex);
|
RemoteMetaDataFEC *metaData = getMetaData(decoderIndex);
|
||||||
|
|
||||||
if (!(*metaData == m_currentMeta))
|
if (!(*metaData == m_currentMeta))
|
||||||
{
|
{
|
||||||
@ -368,7 +368,7 @@ uint8_t *SDRdaemonSourceBuffer::readData(int32_t length)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRdaemonSourceBuffer::printMeta(const QString& header, SDRDaemonMetaDataFEC *metaData)
|
void SDRdaemonSourceBuffer::printMeta(const QString& header, RemoteMetaDataFEC *metaData)
|
||||||
{
|
{
|
||||||
qDebug() << header << ": "
|
qDebug() << header << ": "
|
||||||
<< "|" << metaData->m_centerFrequency
|
<< "|" << metaData->m_centerFrequency
|
||||||
|
@ -17,12 +17,12 @@
|
|||||||
#ifndef PLUGINS_SAMPLESOURCE_SDRDAEMONSOURCE_SDRDAEMONSOURCEBUFFER_H_
|
#ifndef PLUGINS_SAMPLESOURCE_SDRDAEMONSOURCE_SDRDAEMONSOURCEBUFFER_H_
|
||||||
#define PLUGINS_SAMPLESOURCE_SDRDAEMONSOURCE_SDRDAEMONSOURCEBUFFER_H_
|
#define PLUGINS_SAMPLESOURCE_SDRDAEMONSOURCE_SDRDAEMONSOURCEBUFFER_H_
|
||||||
|
|
||||||
|
#include <channel/remotedatablock.h>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include "cm256.h"
|
#include "cm256.h"
|
||||||
#include "util/movingaverage.h"
|
#include "util/movingaverage.h"
|
||||||
#include "channel/sdrdaemondatablock.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define SDRDAEMONSOURCE_UDPSIZE 512 // UDP payload size
|
#define SDRDAEMONSOURCE_UDPSIZE 512 // UDP payload size
|
||||||
@ -40,7 +40,7 @@ public:
|
|||||||
uint8_t *readData(int32_t length); //!< Read data from buffer
|
uint8_t *readData(int32_t length); //!< Read data from buffer
|
||||||
|
|
||||||
// meta data
|
// meta data
|
||||||
const SDRDaemonMetaDataFEC& getCurrentMeta() const { return m_currentMeta; }
|
const RemoteMetaDataFEC& getCurrentMeta() const { return m_currentMeta; }
|
||||||
|
|
||||||
// samples timestamp
|
// samples timestamp
|
||||||
uint32_t getTVOutSec() const { return m_tvOut_sec; }
|
uint32_t getTVOutSec() const { return m_tvOut_sec; }
|
||||||
@ -105,7 +105,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const int framesSize = SDRDAEMONSOURCE_NBDECODERSLOTS * (SDRDaemonNbOrginalBlocks - 1) * SDRDaemonNbBytesPerBlock;
|
static const int framesSize = SDRDAEMONSOURCE_NBDECODERSLOTS * (RemoteNbOrginalBlocks - 1) * RemoteNbBytesPerBlock;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const int nbDecoderSlots = SDRDAEMONSOURCE_NBDECODERSLOTS;
|
static const int nbDecoderSlots = SDRDAEMONSOURCE_NBDECODERSLOTS;
|
||||||
@ -113,16 +113,16 @@ private:
|
|||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct BufferFrame
|
struct BufferFrame
|
||||||
{
|
{
|
||||||
SDRDaemonProtectedBlock m_blocks[SDRDaemonNbOrginalBlocks - 1];
|
RemoteProtectedBlock m_blocks[RemoteNbOrginalBlocks - 1];
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
struct DecoderSlot
|
struct DecoderSlot
|
||||||
{
|
{
|
||||||
SDRDaemonProtectedBlock m_blockZero; //!< First block of a frame. Has meta data.
|
RemoteProtectedBlock m_blockZero; //!< First block of a frame. Has meta data.
|
||||||
SDRDaemonProtectedBlock m_originalBlocks[SDRDaemonNbOrginalBlocks]; //!< Original blocks retrieved directly or by later FEC
|
RemoteProtectedBlock m_originalBlocks[RemoteNbOrginalBlocks]; //!< Original blocks retrieved directly or by later FEC
|
||||||
SDRDaemonProtectedBlock m_recoveryBlocks[SDRDaemonNbOrginalBlocks]; //!< Recovery blocks (FEC blocks) with max size
|
RemoteProtectedBlock m_recoveryBlocks[RemoteNbOrginalBlocks]; //!< Recovery blocks (FEC blocks) with max size
|
||||||
CM256::cm256_block m_cm256DescriptorBlocks[SDRDaemonNbOrginalBlocks]; //!< CM256 decoder descriptors (block addresses and block indexes)
|
CM256::cm256_block m_cm256DescriptorBlocks[RemoteNbOrginalBlocks]; //!< CM256 decoder descriptors (block addresses and block indexes)
|
||||||
int m_blockCount; //!< number of blocks received for this frame
|
int m_blockCount; //!< number of blocks received for this frame
|
||||||
int m_originalCount; //!< number of original blocks received
|
int m_originalCount; //!< number of original blocks received
|
||||||
int m_recoveryCount; //!< number of recovery blocks received
|
int m_recoveryCount; //!< number of recovery blocks received
|
||||||
@ -130,7 +130,7 @@ private:
|
|||||||
bool m_metaRetrieved; //!< true if meta data (block zero) was retrieved
|
bool m_metaRetrieved; //!< true if meta data (block zero) was retrieved
|
||||||
};
|
};
|
||||||
|
|
||||||
SDRDaemonMetaDataFEC m_currentMeta; //!< Stored current meta data
|
RemoteMetaDataFEC m_currentMeta; //!< Stored current meta data
|
||||||
CM256::cm256_encoder_params m_paramsCM256; //!< CM256 decoder parameters block
|
CM256::cm256_encoder_params m_paramsCM256; //!< CM256 decoder parameters block
|
||||||
DecoderSlot m_decoderSlots[nbDecoderSlots]; //!< CM256 decoding control/buffer slots
|
DecoderSlot m_decoderSlots[nbDecoderSlots]; //!< CM256 decoding control/buffer slots
|
||||||
BufferFrame m_frames[nbDecoderSlots]; //!< Samples buffer
|
BufferFrame m_frames[nbDecoderSlots]; //!< Samples buffer
|
||||||
@ -165,7 +165,7 @@ private:
|
|||||||
CM256 m_cm256; //!< CM256 library
|
CM256 m_cm256; //!< CM256 library
|
||||||
bool m_cm256_OK; //!< CM256 library initialized OK
|
bool m_cm256_OK; //!< CM256 library initialized OK
|
||||||
|
|
||||||
inline SDRDaemonProtectedBlock* storeOriginalBlock(int slotIndex, int blockIndex, const SDRDaemonProtectedBlock& protectedBlock)
|
inline RemoteProtectedBlock* storeOriginalBlock(int slotIndex, int blockIndex, const RemoteProtectedBlock& protectedBlock)
|
||||||
{
|
{
|
||||||
if (blockIndex == 0) {
|
if (blockIndex == 0) {
|
||||||
// m_decoderSlots[slotIndex].m_originalBlocks[0] = protectedBlock;
|
// m_decoderSlots[slotIndex].m_originalBlocks[0] = protectedBlock;
|
||||||
@ -180,7 +180,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline SDRDaemonProtectedBlock& getOriginalBlock(int slotIndex, int blockIndex)
|
inline RemoteProtectedBlock& getOriginalBlock(int slotIndex, int blockIndex)
|
||||||
{
|
{
|
||||||
if (blockIndex == 0) {
|
if (blockIndex == 0) {
|
||||||
// return m_decoderSlots[slotIndex].m_originalBlocks[0];
|
// return m_decoderSlots[slotIndex].m_originalBlocks[0];
|
||||||
@ -191,17 +191,17 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline SDRDaemonMetaDataFEC *getMetaData(int slotIndex)
|
inline RemoteMetaDataFEC *getMetaData(int slotIndex)
|
||||||
{
|
{
|
||||||
// return (MetaDataFEC *) &m_decoderSlots[slotIndex].m_originalBlocks[0];
|
// return (MetaDataFEC *) &m_decoderSlots[slotIndex].m_originalBlocks[0];
|
||||||
return (SDRDaemonMetaDataFEC *) &m_decoderSlots[slotIndex].m_blockZero;
|
return (RemoteMetaDataFEC *) &m_decoderSlots[slotIndex].m_blockZero;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void resetOriginalBlocks(int slotIndex)
|
inline void resetOriginalBlocks(int slotIndex)
|
||||||
{
|
{
|
||||||
// memset((void *) m_decoderSlots[slotIndex].m_originalBlocks, 0, m_nbOriginalBlocks * sizeof(ProtectedBlock));
|
// memset((void *) m_decoderSlots[slotIndex].m_originalBlocks, 0, m_nbOriginalBlocks * sizeof(ProtectedBlock));
|
||||||
memset((void *) &m_decoderSlots[slotIndex].m_blockZero, 0, sizeof(SDRDaemonProtectedBlock));
|
memset((void *) &m_decoderSlots[slotIndex].m_blockZero, 0, sizeof(RemoteProtectedBlock));
|
||||||
memset((void *) m_frames[slotIndex].m_blocks, 0, (SDRDaemonNbOrginalBlocks - 1) * sizeof(SDRDaemonProtectedBlock));
|
memset((void *) m_frames[slotIndex].m_blocks, 0, (RemoteNbOrginalBlocks - 1) * sizeof(RemoteProtectedBlock));
|
||||||
}
|
}
|
||||||
|
|
||||||
void initDecodeAllSlots();
|
void initDecodeAllSlots();
|
||||||
@ -210,7 +210,7 @@ private:
|
|||||||
void checkSlotData(int slotIndex);
|
void checkSlotData(int slotIndex);
|
||||||
void initDecodeSlot(int slotIndex);
|
void initDecodeSlot(int slotIndex);
|
||||||
|
|
||||||
static void printMeta(const QString& header, SDRDaemonMetaDataFEC *metaData);
|
static void printMeta(const QString& header, RemoteMetaDataFEC *metaData);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ SDRdaemonSourceUDPHandler::SDRdaemonSourceUDPHandler(SampleSinkFifo *sampleFifo,
|
|||||||
m_throttleToggle(false),
|
m_throttleToggle(false),
|
||||||
m_autoCorrBuffer(true)
|
m_autoCorrBuffer(true)
|
||||||
{
|
{
|
||||||
m_udpBuf = new char[SDRDaemonUdpSize];
|
m_udpBuf = new char[RemoteUdpSize];
|
||||||
|
|
||||||
#ifdef USE_INTERNAL_TIMER
|
#ifdef USE_INTERNAL_TIMER
|
||||||
#warning "Uses internal timer"
|
#warning "Uses internal timer"
|
||||||
@ -165,7 +165,7 @@ void SDRdaemonSourceUDPHandler::dataReadyRead()
|
|||||||
qint64 pendingDataSize = m_dataSocket->pendingDatagramSize();
|
qint64 pendingDataSize = m_dataSocket->pendingDatagramSize();
|
||||||
m_udpReadBytes += m_dataSocket->readDatagram(&m_udpBuf[m_udpReadBytes], pendingDataSize, &m_remoteAddress, 0);
|
m_udpReadBytes += m_dataSocket->readDatagram(&m_udpBuf[m_udpReadBytes], pendingDataSize, &m_remoteAddress, 0);
|
||||||
|
|
||||||
if (m_udpReadBytes == SDRDaemonUdpSize) {
|
if (m_udpReadBytes == RemoteUdpSize) {
|
||||||
processData();
|
processData();
|
||||||
m_udpReadBytes = 0;
|
m_udpReadBytes = 0;
|
||||||
}
|
}
|
||||||
@ -175,7 +175,7 @@ void SDRdaemonSourceUDPHandler::dataReadyRead()
|
|||||||
void SDRdaemonSourceUDPHandler::processData()
|
void SDRdaemonSourceUDPHandler::processData()
|
||||||
{
|
{
|
||||||
m_sdrDaemonBuffer.writeData(m_udpBuf);
|
m_sdrDaemonBuffer.writeData(m_udpBuf);
|
||||||
const SDRDaemonMetaDataFEC& metaData = m_sdrDaemonBuffer.getCurrentMeta();
|
const RemoteMetaDataFEC& metaData = m_sdrDaemonBuffer.getCurrentMeta();
|
||||||
bool change = false;
|
bool change = false;
|
||||||
|
|
||||||
m_tv_msec = m_sdrDaemonBuffer.getTVOutMSec();
|
m_tv_msec = m_sdrDaemonBuffer.getTVOutMSec();
|
||||||
@ -259,7 +259,7 @@ void SDRdaemonSourceUDPHandler::tick()
|
|||||||
m_readLengthSamples += m_sdrDaemonBuffer.getRWBalanceCorrection();
|
m_readLengthSamples += m_sdrDaemonBuffer.getRWBalanceCorrection();
|
||||||
}
|
}
|
||||||
|
|
||||||
const SDRDaemonMetaDataFEC& metaData = m_sdrDaemonBuffer.getCurrentMeta();
|
const RemoteMetaDataFEC& metaData = m_sdrDaemonBuffer.getCurrentMeta();
|
||||||
m_readLength = m_readLengthSamples * (metaData.m_sampleBytes & 0xF) * 2;
|
m_readLength = m_readLengthSamples * (metaData.m_sampleBytes & 0xF) * 2;
|
||||||
|
|
||||||
if ((metaData.m_sampleBits == 16) && (SDR_RX_SAMP_SZ == 24)) // 16 -> 24 bits
|
if ((metaData.m_sampleBits == 16) && (SDR_RX_SAMP_SZ == 24)) // 16 -> 24 bits
|
||||||
|
@ -43,7 +43,7 @@ public:
|
|||||||
void stop();
|
void stop();
|
||||||
void configureUDPLink(const QString& address, quint16 port);
|
void configureUDPLink(const QString& address, quint16 port);
|
||||||
void getRemoteAddress(QString& s) const { s = m_remoteAddress.toString(); }
|
void getRemoteAddress(QString& s) const { s = m_remoteAddress.toString(); }
|
||||||
int getNbOriginalBlocks() const { return SDRDaemonNbOrginalBlocks; }
|
int getNbOriginalBlocks() const { return RemoteNbOrginalBlocks; }
|
||||||
bool isStreaming() const { return m_masterTimerConnected; }
|
bool isStreaming() const { return m_masterTimerConnected; }
|
||||||
int getSampleRate() const { return m_samplerate; }
|
int getSampleRate() const { return m_samplerate; }
|
||||||
int getCenterFrequency() const { return m_centerFrequency * 1000; }
|
int getCenterFrequency() const { return m_centerFrequency * 1000; }
|
||||||
|
@ -25,7 +25,7 @@ endif(LIBUSB_FOUND AND LIBIIO_FOUND)
|
|||||||
|
|
||||||
find_package(CM256cc)
|
find_package(CM256cc)
|
||||||
if(CM256CC_FOUND)
|
if(CM256CC_FOUND)
|
||||||
add_subdirectory(sdrdaemonsink)
|
add_subdirectory(remoteoutput)
|
||||||
endif(CM256CC_FOUND)
|
endif(CM256CC_FOUND)
|
||||||
|
|
||||||
find_package(SoapySDR)
|
find_package(SoapySDR)
|
||||||
@ -44,7 +44,7 @@ if (BUILD_DEBIAN)
|
|||||||
add_subdirectory(hackrfoutput)
|
add_subdirectory(hackrfoutput)
|
||||||
add_subdirectory(limesdroutput)
|
add_subdirectory(limesdroutput)
|
||||||
add_subdirectory(plutosdroutput)
|
add_subdirectory(plutosdroutput)
|
||||||
add_subdirectory(sdrdaemonsink)
|
add_subdirectory(remoteoutput)
|
||||||
endif (BUILD_DEBIAN)
|
endif (BUILD_DEBIAN)
|
||||||
|
|
||||||
add_subdirectory(filesink)
|
add_subdirectory(filesink)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
project(sdrdaemonsink)
|
project(remoteoutput)
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||||
set(PLUGIN_PREFIX "../../../plugins/samplesink/sdrdaemonsink")
|
set(PLUGIN_PREFIX "../../../plugins/samplesink/remoteoutput")
|
||||||
|
|
||||||
if (HAS_SSSE3)
|
if (HAS_SSSE3)
|
||||||
message(STATUS "SDRdaemonFEC: use SSSE3 SIMD" )
|
message(STATUS "SDRdaemonFEC: use SSSE3 SIMD" )
|
||||||
@ -12,20 +12,20 @@ else()
|
|||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(sdrdaemonsink_SOURCES
|
set(remoteoutput_SOURCES
|
||||||
${PLUGIN_PREFIX}/sdrdaemonsinkoutput.cpp
|
${PLUGIN_PREFIX}/remoteoutput.cpp
|
||||||
${PLUGIN_PREFIX}/sdrdaemonsinkplugin.cpp
|
${PLUGIN_PREFIX}/remoteoutputplugin.cpp
|
||||||
${PLUGIN_PREFIX}/sdrdaemonsinksettings.cpp
|
${PLUGIN_PREFIX}/remoteoutputsettings.cpp
|
||||||
${PLUGIN_PREFIX}/sdrdaemonsinkthread.cpp
|
${PLUGIN_PREFIX}/remoteoutputthread.cpp
|
||||||
${PLUGIN_PREFIX}/udpsinkfec.cpp
|
${PLUGIN_PREFIX}/udpsinkfec.cpp
|
||||||
${PLUGIN_PREFIX}/udpsinkfecworker.cpp
|
${PLUGIN_PREFIX}/udpsinkfecworker.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(sdrdaemonsink_HEADERS
|
set(remoteoutput_HEADERS
|
||||||
${PLUGIN_PREFIX}/sdrdaemonsinkoutput.h
|
${PLUGIN_PREFIX}/remoteoutput.h
|
||||||
${PLUGIN_PREFIX}/sdrdaemonsinkplugin.h
|
${PLUGIN_PREFIX}/remoteoutputplugin.h
|
||||||
${PLUGIN_PREFIX}/sdrdaemonsinksettings.h
|
${PLUGIN_PREFIX}/remoteoutputsettings.h
|
||||||
${PLUGIN_PREFIX}/sdrdaemonsinkthread.h
|
${PLUGIN_PREFIX}/remoteoutputthread.h
|
||||||
${PLUGIN_PREFIX}/udpsinkfec.h
|
${PLUGIN_PREFIX}/udpsinkfec.h
|
||||||
${PLUGIN_PREFIX}/udpsinkfecworker.h
|
${PLUGIN_PREFIX}/udpsinkfecworker.h
|
||||||
)
|
)
|
||||||
@ -51,20 +51,20 @@ add_definitions(${QT_DEFINITIONS})
|
|||||||
add_definitions(-DQT_PLUGIN)
|
add_definitions(-DQT_PLUGIN)
|
||||||
add_definitions(-DQT_SHARED)
|
add_definitions(-DQT_SHARED)
|
||||||
|
|
||||||
add_library(outputsdrdaemonsinksrv SHARED
|
add_library(outputremotesrv SHARED
|
||||||
${sdrdaemonsink_SOURCES}
|
${remoteoutput_SOURCES}
|
||||||
${sdrdaemonsink_HEADERS_MOC}
|
${remoteoutput_HEADERS_MOC}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (BUILD_DEBIAN)
|
if (BUILD_DEBIAN)
|
||||||
target_link_libraries(outputsdrdaemonsinksrv
|
target_link_libraries(outputremotesrv
|
||||||
${QT_LIBRARIES}
|
${QT_LIBRARIES}
|
||||||
sdrbase
|
sdrbase
|
||||||
swagger
|
swagger
|
||||||
cm256cc
|
cm256cc
|
||||||
)
|
)
|
||||||
else (BUILD_DEBIAN)
|
else (BUILD_DEBIAN)
|
||||||
target_link_libraries(outputsdrdaemonsinksrv
|
target_link_libraries(outputremotesrv
|
||||||
${QT_LIBRARIES}
|
${QT_LIBRARIES}
|
||||||
sdrbase
|
sdrbase
|
||||||
swagger
|
swagger
|
||||||
@ -72,6 +72,6 @@ target_link_libraries(outputsdrdaemonsinksrv
|
|||||||
)
|
)
|
||||||
endif (BUILD_DEBIAN)
|
endif (BUILD_DEBIAN)
|
||||||
|
|
||||||
target_link_libraries(outputsdrdaemonsinksrv Qt5::Core)
|
target_link_libraries(outputremotesrv Qt5::Core)
|
||||||
|
|
||||||
install(TARGETS outputsdrdaemonsinksrv DESTINATION lib/pluginssrv/samplesink)
|
install(TARGETS outputremotesrv DESTINATION lib/pluginssrv/samplesink)
|
@ -13,8 +13,8 @@ set(sdrbase_SOURCES
|
|||||||
|
|
||||||
channel/channelsinkapi.cpp
|
channel/channelsinkapi.cpp
|
||||||
channel/channelsourceapi.cpp
|
channel/channelsourceapi.cpp
|
||||||
channel/sdrdaemondataqueue.cpp
|
channel/remotedataqueue.cpp
|
||||||
channel/sdrdaemondatareadqueue.cpp
|
channel/remotedatareadqueue.cpp
|
||||||
|
|
||||||
commands/command.cpp
|
commands/command.cpp
|
||||||
|
|
||||||
@ -105,9 +105,9 @@ set(sdrbase_HEADERS
|
|||||||
|
|
||||||
channel/channelsinkapi.h
|
channel/channelsinkapi.h
|
||||||
channel/channelsourceapi.h
|
channel/channelsourceapi.h
|
||||||
channel/sdrdaemondataqueue.h
|
channel/remotedataqueue.h
|
||||||
channel/sdrdaemondatareadqueue.h
|
channel/remotedatareadqueue.h
|
||||||
channel/sdrdaemondatablock.h
|
channel/remotedatablock.h
|
||||||
|
|
||||||
commands/command.h
|
commands/command.h
|
||||||
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
// Copyright (C) 2018 Edouard Griffiths, F4EXB. //
|
// Copyright (C) 2018 Edouard Griffiths, F4EXB. //
|
||||||
// //
|
// //
|
||||||
// SDRdaemon sink channel (Rx) data block //
|
// Remote sink channel (Rx) data block //
|
||||||
// //
|
// //
|
||||||
// SDRdaemon is a detached SDR front end that handles the interface with a //
|
// SDRangel can serve as a remote SDR front end that handles the interface //
|
||||||
// physical device and sends or receives the I/Q samples stream to or from a //
|
// with a physical device and sends or receives the I/Q samples stream via UDP //
|
||||||
// SDRangel instance via UDP. It is controlled via a Web REST API. //
|
// to or from another SDRangel instance or any program implementing the same //
|
||||||
|
// protocol. The remote SDRangel is controlled via its Web REST API. //
|
||||||
// //
|
// //
|
||||||
// This program is free software; you can redistribute it and/or modify //
|
// 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 //
|
// it under the terms of the GNU General Public License as published by //
|
||||||
@ -34,7 +35,7 @@
|
|||||||
//#define UDPSINKFEC_NBTXBLOCKS 8
|
//#define UDPSINKFEC_NBTXBLOCKS 8
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct SDRDaemonMetaDataFEC
|
struct RemoteMetaDataFEC
|
||||||
{
|
{
|
||||||
uint32_t m_centerFrequency; //!< 4 center frequency in kHz
|
uint32_t m_centerFrequency; //!< 4 center frequency in kHz
|
||||||
uint32_t m_sampleRate; //!< 8 sample rate in Hz
|
uint32_t m_sampleRate; //!< 8 sample rate in Hz
|
||||||
@ -47,7 +48,7 @@ struct SDRDaemonMetaDataFEC
|
|||||||
uint32_t m_tv_usec; //!< 20 microseconds 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
|
uint32_t m_crc32; //!< 24 CRC32 of the above
|
||||||
|
|
||||||
bool operator==(const SDRDaemonMetaDataFEC& rhs)
|
bool operator==(const RemoteMetaDataFEC& rhs)
|
||||||
{
|
{
|
||||||
// Only the first 6 fields are relevant
|
// Only the first 6 fields are relevant
|
||||||
return (m_centerFrequency == rhs.m_centerFrequency)
|
return (m_centerFrequency == rhs.m_centerFrequency)
|
||||||
@ -72,7 +73,7 @@ struct SDRDaemonMetaDataFEC
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SDRDaemonHeader
|
struct RemoteHeader
|
||||||
{
|
{
|
||||||
uint16_t m_frameIndex;
|
uint16_t m_frameIndex;
|
||||||
uint8_t m_blockIndex;
|
uint8_t m_blockIndex;
|
||||||
@ -92,23 +93,23 @@ struct SDRDaemonHeader
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int SDRDaemonUdpSize = UDPSINKFEC_UDPSIZE;
|
static const int RemoteUdpSize = UDPSINKFEC_UDPSIZE;
|
||||||
static const int SDRDaemonNbOrginalBlocks = UDPSINKFEC_NBORIGINALBLOCKS;
|
static const int RemoteNbOrginalBlocks = UDPSINKFEC_NBORIGINALBLOCKS;
|
||||||
static const int SDRDaemonNbBytesPerBlock = UDPSINKFEC_UDPSIZE - sizeof(SDRDaemonHeader);
|
static const int RemoteNbBytesPerBlock = UDPSINKFEC_UDPSIZE - sizeof(RemoteHeader);
|
||||||
|
|
||||||
struct SDRDaemonProtectedBlock
|
struct RemoteProtectedBlock
|
||||||
{
|
{
|
||||||
uint8_t buf[SDRDaemonNbBytesPerBlock];
|
uint8_t buf[RemoteNbBytesPerBlock];
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
std::fill(buf, buf+SDRDaemonNbBytesPerBlock, 0);
|
std::fill(buf, buf+RemoteNbBytesPerBlock, 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SDRDaemonSuperBlock
|
struct RemoteSuperBlock
|
||||||
{
|
{
|
||||||
SDRDaemonHeader m_header;
|
RemoteHeader m_header;
|
||||||
SDRDaemonProtectedBlock m_protectedBlock;
|
RemoteProtectedBlock m_protectedBlock;
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
@ -118,7 +119,7 @@ struct SDRDaemonSuperBlock
|
|||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
struct SDRDaemonTxControlBlock
|
struct RemoteTxControlBlock
|
||||||
{
|
{
|
||||||
bool m_complete;
|
bool m_complete;
|
||||||
bool m_processed;
|
bool m_processed;
|
||||||
@ -128,7 +129,7 @@ struct SDRDaemonTxControlBlock
|
|||||||
QString m_dataAddress;
|
QString m_dataAddress;
|
||||||
uint16_t m_dataPort;
|
uint16_t m_dataPort;
|
||||||
|
|
||||||
SDRDaemonTxControlBlock() {
|
RemoteTxControlBlock() {
|
||||||
m_complete = false;
|
m_complete = false;
|
||||||
m_processed = false;
|
m_processed = false;
|
||||||
m_frameIndex = 0;
|
m_frameIndex = 0;
|
||||||
@ -139,7 +140,7 @@ struct SDRDaemonTxControlBlock
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SDRDaemonRxControlBlock
|
struct RemoteRxControlBlock
|
||||||
{
|
{
|
||||||
int m_blockCount; //!< number of blocks received for this frame
|
int m_blockCount; //!< number of blocks received for this frame
|
||||||
int m_originalCount; //!< number of original blocks received
|
int m_originalCount; //!< number of original blocks received
|
||||||
@ -147,7 +148,7 @@ struct SDRDaemonRxControlBlock
|
|||||||
bool m_metaRetrieved; //!< true if meta data (block zero) was retrieved
|
bool m_metaRetrieved; //!< true if meta data (block zero) was retrieved
|
||||||
int m_frameIndex; //!< this frame index or -1 if unset
|
int m_frameIndex; //!< this frame index or -1 if unset
|
||||||
|
|
||||||
SDRDaemonRxControlBlock() {
|
RemoteRxControlBlock() {
|
||||||
m_blockCount = 0;
|
m_blockCount = 0;
|
||||||
m_originalCount = 0;
|
m_originalCount = 0;
|
||||||
m_recoveryCount = 0;
|
m_recoveryCount = 0;
|
||||||
@ -156,18 +157,18 @@ struct SDRDaemonRxControlBlock
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SDRDaemonDataBlock
|
class RemoteDataBlock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SDRDaemonDataBlock() {
|
RemoteDataBlock() {
|
||||||
m_superBlocks = new SDRDaemonSuperBlock[256];
|
m_superBlocks = new RemoteSuperBlock[256];
|
||||||
}
|
}
|
||||||
~SDRDaemonDataBlock() {
|
~RemoteDataBlock() {
|
||||||
delete[] m_superBlocks;
|
delete[] m_superBlocks;
|
||||||
}
|
}
|
||||||
SDRDaemonTxControlBlock m_txControlBlock;
|
RemoteTxControlBlock m_txControlBlock;
|
||||||
SDRDaemonRxControlBlock m_rxControlBlock;
|
RemoteRxControlBlock m_rxControlBlock;
|
||||||
SDRDaemonSuperBlock *m_superBlocks;
|
RemoteSuperBlock *m_superBlocks;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SDRDAEMON_CHANNEL_SDRDAEMONDATABLOCK_H_ */
|
#endif /* SDRDAEMON_CHANNEL_SDRDAEMONDATABLOCK_H_ */
|
@ -1,11 +1,12 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
// Copyright (C) 2018 Edouard Griffiths, F4EXB. //
|
// Copyright (C) 2018 Edouard Griffiths, F4EXB. //
|
||||||
// //
|
// //
|
||||||
// SDRdaemon sink channel (Rx) data blocks queue //
|
// Remtoe sink channel (Rx) data blocks queue //
|
||||||
// //
|
// //
|
||||||
// SDRdaemon is a detached SDR front end that handles the interface with a //
|
// SDRangel can serve as a remote SDR front end that handles the interface //
|
||||||
// physical device and sends or receives the I/Q samples stream to or from a //
|
// with a physical device and sends or receives the I/Q samples stream via UDP //
|
||||||
// SDRangel instance via UDP. It is controlled via a Web REST API. //
|
// to or from another SDRangel instance or any program implementing the same //
|
||||||
|
// protocol. The remote SDRangel is controlled via its Web REST API. //
|
||||||
// //
|
// //
|
||||||
// This program is free software; you can redistribute it and/or modify //
|
// 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 //
|
// it under the terms of the GNU General Public License as published by //
|
||||||
@ -20,21 +21,21 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <channel/remotedatablock.h>
|
||||||
|
#include <channel/remotedataqueue.h>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QMutexLocker>
|
#include <QMutexLocker>
|
||||||
#include "channel/sdrdaemondataqueue.h"
|
|
||||||
#include "channel/sdrdaemondatablock.h"
|
|
||||||
|
|
||||||
SDRDaemonDataQueue::SDRDaemonDataQueue(QObject* parent) :
|
RemoteDataQueue::RemoteDataQueue(QObject* parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
m_lock(QMutex::Recursive),
|
m_lock(QMutex::Recursive),
|
||||||
m_queue()
|
m_queue()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SDRDaemonDataQueue::~SDRDaemonDataQueue()
|
RemoteDataQueue::~RemoteDataQueue()
|
||||||
{
|
{
|
||||||
SDRDaemonDataBlock* data;
|
RemoteDataBlock* data;
|
||||||
|
|
||||||
while ((data = pop()) != 0)
|
while ((data = pop()) != 0)
|
||||||
{
|
{
|
||||||
@ -43,7 +44,7 @@ SDRDaemonDataQueue::~SDRDaemonDataQueue()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRDaemonDataQueue::push(SDRDaemonDataBlock* data, bool emitSignal)
|
void RemoteDataQueue::push(RemoteDataBlock* data, bool emitSignal)
|
||||||
{
|
{
|
||||||
if (data)
|
if (data)
|
||||||
{
|
{
|
||||||
@ -58,7 +59,7 @@ void SDRDaemonDataQueue::push(SDRDaemonDataBlock* data, bool emitSignal)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDRDaemonDataBlock* SDRDaemonDataQueue::pop()
|
RemoteDataBlock* RemoteDataQueue::pop()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_lock);
|
QMutexLocker locker(&m_lock);
|
||||||
|
|
||||||
@ -72,14 +73,14 @@ SDRDaemonDataBlock* SDRDaemonDataQueue::pop()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int SDRDaemonDataQueue::size()
|
int RemoteDataQueue::size()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_lock);
|
QMutexLocker locker(&m_lock);
|
||||||
|
|
||||||
return m_queue.size();
|
return m_queue.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRDaemonDataQueue::clear()
|
void RemoteDataQueue::clear()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_lock);
|
QMutexLocker locker(&m_lock);
|
||||||
m_queue.clear();
|
m_queue.clear();
|
@ -1,11 +1,12 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
// Copyright (C) 2018 Edouard Griffiths, F4EXB. //
|
// Copyright (C) 2018 Edouard Griffiths, F4EXB. //
|
||||||
// //
|
// //
|
||||||
// SDRdaemon sink channel (Rx) data blocks queue //
|
// Remote sink channel (Rx) data blocks queue //
|
||||||
// //
|
// //
|
||||||
// SDRdaemon is a detached SDR front end that handles the interface with a //
|
// SDRangel can serve as a remote SDR front end that handles the interface //
|
||||||
// physical device and sends or receives the I/Q samples stream to or from a //
|
// with a physical device and sends or receives the I/Q samples stream via UDP //
|
||||||
// SDRangel instance via UDP. It is controlled via a Web REST API. //
|
// to or from another SDRangel instance or any program implementing the same //
|
||||||
|
// protocol. The remote SDRangel is controlled via its Web REST API. //
|
||||||
// //
|
// //
|
||||||
// This program is free software; you can redistribute it and/or modify //
|
// 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 //
|
// it under the terms of the GNU General Public License as published by //
|
||||||
@ -20,24 +21,24 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef SDRDAEMON_CHANNEL_SDRDAEMONDATAQUEUE_H_
|
#ifndef CHANNEL_REMOTEDATAQUEUE_H_
|
||||||
#define SDRDAEMON_CHANNEL_SDRDAEMONDATAQUEUE_H_
|
#define CHANNEL_REMOTEDATAQUEUE_H_
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QQueue>
|
#include <QQueue>
|
||||||
|
|
||||||
class SDRDaemonDataBlock;
|
class RemoteDataBlock;
|
||||||
|
|
||||||
class SDRDaemonDataQueue : public QObject {
|
class RemoteDataQueue : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SDRDaemonDataQueue(QObject* parent = NULL);
|
RemoteDataQueue(QObject* parent = NULL);
|
||||||
~SDRDaemonDataQueue();
|
~RemoteDataQueue();
|
||||||
|
|
||||||
void push(SDRDaemonDataBlock* dataBlock, bool emitSignal = true); //!< Push daa block onto queue
|
void push(RemoteDataBlock* dataBlock, bool emitSignal = true); //!< Push daa block onto queue
|
||||||
SDRDaemonDataBlock* pop(); //!< Pop message from queue
|
RemoteDataBlock* pop(); //!< Pop message from queue
|
||||||
|
|
||||||
int size(); //!< Returns queue size
|
int size(); //!< Returns queue size
|
||||||
void clear(); //!< Empty queue
|
void clear(); //!< Empty queue
|
||||||
@ -47,7 +48,7 @@ signals:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QMutex m_lock;
|
QMutex m_lock;
|
||||||
QQueue<SDRDaemonDataBlock*> m_queue;
|
QQueue<RemoteDataBlock*> m_queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SDRDAEMON_CHANNEL_SDRDAEMONDATAQUEUE_H_ */
|
#endif /* CHANNEL_REMOTEDATAQUEUE_H_ */
|
@ -1,11 +1,12 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
// Copyright (C) 2018 Edouard Griffiths, F4EXB. //
|
// Copyright (C) 2018 Edouard Griffiths, F4EXB. //
|
||||||
// //
|
// //
|
||||||
// SDRdaemon sink channel (Rx) data blocks to read queue //
|
// Remote sink channel (Rx) data blocks to read queue //
|
||||||
// //
|
// //
|
||||||
// SDRdaemon is a detached SDR front end that handles the interface with a //
|
// SDRangel can serve as a remote SDR front end that handles the interface //
|
||||||
// physical device and sends or receives the I/Q samples stream to or from a //
|
// with a physical device and sends or receives the I/Q samples stream via UDP //
|
||||||
// SDRangel instance via UDP. It is controlled via a Web REST API. //
|
// to or from another SDRangel instance or any program implementing the same //
|
||||||
|
// protocol. The remote SDRangel is controlled via its Web REST API. //
|
||||||
// //
|
// //
|
||||||
// This program is free software; you can redistribute it and/or modify //
|
// 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 //
|
// it under the terms of the GNU General Public License as published by //
|
||||||
@ -20,12 +21,12 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "channel/sdrdaemondatablock.h"
|
#include <channel/remotedatablock.h>
|
||||||
#include "channel/sdrdaemondatareadqueue.h"
|
#include <channel/remotedatareadqueue.h>
|
||||||
|
|
||||||
const uint32_t SDRDaemonDataReadQueue::MinimumMaxSize = 10;
|
const uint32_t RemoteDataReadQueue::MinimumMaxSize = 10;
|
||||||
|
|
||||||
SDRDaemonDataReadQueue::SDRDaemonDataReadQueue() :
|
RemoteDataReadQueue::RemoteDataReadQueue() :
|
||||||
m_dataBlock(0),
|
m_dataBlock(0),
|
||||||
m_maxSize(MinimumMaxSize),
|
m_maxSize(MinimumMaxSize),
|
||||||
m_blockIndex(1),
|
m_blockIndex(1),
|
||||||
@ -34,9 +35,9 @@ SDRDaemonDataReadQueue::SDRDaemonDataReadQueue() :
|
|||||||
m_full(false)
|
m_full(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
SDRDaemonDataReadQueue::~SDRDaemonDataReadQueue()
|
RemoteDataReadQueue::~RemoteDataReadQueue()
|
||||||
{
|
{
|
||||||
SDRDaemonDataBlock* data;
|
RemoteDataBlock* data;
|
||||||
|
|
||||||
while ((data = pop()) != 0)
|
while ((data = pop()) != 0)
|
||||||
{
|
{
|
||||||
@ -45,13 +46,13 @@ SDRDaemonDataReadQueue::~SDRDaemonDataReadQueue()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRDaemonDataReadQueue::push(SDRDaemonDataBlock* dataBlock)
|
void RemoteDataReadQueue::push(RemoteDataBlock* dataBlock)
|
||||||
{
|
{
|
||||||
if (length() >= m_maxSize)
|
if (length() >= m_maxSize)
|
||||||
{
|
{
|
||||||
qWarning("SDRDaemonDataReadQueue::push: queue is full");
|
qWarning("SDRDaemonDataReadQueue::push: queue is full");
|
||||||
m_full = true; // stop filling the queue
|
m_full = true; // stop filling the queue
|
||||||
SDRDaemonDataBlock *data = m_dataReadQueue.takeLast();
|
RemoteDataBlock *data = m_dataReadQueue.takeLast();
|
||||||
delete data;
|
delete data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +65,7 @@ void SDRDaemonDataReadQueue::push(SDRDaemonDataBlock* dataBlock)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDRDaemonDataBlock* SDRDaemonDataReadQueue::pop()
|
RemoteDataBlock* RemoteDataReadQueue::pop()
|
||||||
{
|
{
|
||||||
if (m_dataReadQueue.isEmpty())
|
if (m_dataReadQueue.isEmpty())
|
||||||
{
|
{
|
||||||
@ -79,14 +80,14 @@ SDRDaemonDataBlock* SDRDaemonDataReadQueue::pop()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRDaemonDataReadQueue::setSize(uint32_t size)
|
void RemoteDataReadQueue::setSize(uint32_t size)
|
||||||
{
|
{
|
||||||
if (size != m_maxSize) {
|
if (size != m_maxSize) {
|
||||||
m_maxSize = size < MinimumMaxSize ? MinimumMaxSize : size;
|
m_maxSize = size < MinimumMaxSize ? MinimumMaxSize : size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDRDaemonDataReadQueue::readSample(Sample& s, bool scaleForTx)
|
void RemoteDataReadQueue::readSample(Sample& s, bool scaleForTx)
|
||||||
{
|
{
|
||||||
// depletion/repletion state
|
// depletion/repletion state
|
||||||
if (m_dataBlock == 0)
|
if (m_dataBlock == 0)
|
||||||
@ -109,7 +110,7 @@ void SDRDaemonDataReadQueue::readSample(Sample& s, bool scaleForTx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int sampleSize = m_dataBlock->m_superBlocks[m_blockIndex].m_header.m_sampleBytes * 2;
|
int sampleSize = m_dataBlock->m_superBlocks[m_blockIndex].m_header.m_sampleBytes * 2;
|
||||||
uint32_t samplesPerBlock = SDRDaemonNbBytesPerBlock / sampleSize;
|
uint32_t samplesPerBlock = RemoteNbBytesPerBlock / sampleSize;
|
||||||
|
|
||||||
if (m_sampleIndex < samplesPerBlock)
|
if (m_sampleIndex < samplesPerBlock)
|
||||||
{
|
{
|
||||||
@ -122,7 +123,7 @@ void SDRDaemonDataReadQueue::readSample(Sample& s, bool scaleForTx)
|
|||||||
m_sampleIndex = 0;
|
m_sampleIndex = 0;
|
||||||
m_blockIndex++;
|
m_blockIndex++;
|
||||||
|
|
||||||
if (m_blockIndex < SDRDaemonNbOrginalBlocks)
|
if (m_blockIndex < RemoteNbOrginalBlocks)
|
||||||
{
|
{
|
||||||
convertDataToSample(s, m_blockIndex, m_sampleIndex, scaleForTx);
|
convertDataToSample(s, m_blockIndex, m_sampleIndex, scaleForTx);
|
||||||
m_sampleIndex++;
|
m_sampleIndex++;
|
@ -1,11 +1,12 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
// Copyright (C) 2018 Edouard Griffiths, F4EXB. //
|
// Copyright (C) 2018 Edouard Griffiths, F4EXB. //
|
||||||
// //
|
// //
|
||||||
// SDRdaemon sink channel (Rx) data blocks to read queue //
|
// Remote sink channel (Rx) data blocks to read queue //
|
||||||
// //
|
// //
|
||||||
// SDRdaemon is a detached SDR front end that handles the interface with a //
|
// SDRangel can serve as a remote SDR front end that handles the interface //
|
||||||
// physical device and sends or receives the I/Q samples stream to or from a //
|
// with a physical device and sends or receives the I/Q samples stream via UDP //
|
||||||
// SDRangel instance via UDP. It is controlled via a Web REST API. //
|
// to or from another SDRangel instance or any program implementing the same //
|
||||||
|
// protocol. The remote SDRangel is controlled via its Web REST API. //
|
||||||
// //
|
// //
|
||||||
// This program is free software; you can redistribute it and/or modify //
|
// 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 //
|
// it under the terms of the GNU General Public License as published by //
|
||||||
@ -20,22 +21,22 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef SDRDAEMON_CHANNEL_SDRDAEMONDATAREADQUEUE_H_
|
#ifndef CHANNEL_REMOTEDATAREADQUEUE_H_
|
||||||
#define SDRDAEMON_CHANNEL_SDRDAEMONDATAREADQUEUE_H_
|
#define CHANNEL_REMOTEDATAREADQUEUE_H_
|
||||||
|
|
||||||
#include <QQueue>
|
#include <QQueue>
|
||||||
|
|
||||||
class SDRDaemonDataBlock;
|
class RemoteDataBlock;
|
||||||
class Sample;
|
class Sample;
|
||||||
|
|
||||||
class SDRDaemonDataReadQueue
|
class RemoteDataReadQueue
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SDRDaemonDataReadQueue();
|
RemoteDataReadQueue();
|
||||||
~SDRDaemonDataReadQueue();
|
~RemoteDataReadQueue();
|
||||||
|
|
||||||
void push(SDRDaemonDataBlock* dataBlock); //!< push block on the queue
|
void push(RemoteDataBlock* dataBlock); //!< push block on the queue
|
||||||
SDRDaemonDataBlock* pop(); //!< Pop block from the queue
|
RemoteDataBlock* pop(); //!< Pop block from the queue
|
||||||
void readSample(Sample& s, bool scaleForTx = false); //!< Read sample from queue possibly scaling to Tx size
|
void readSample(Sample& s, bool scaleForTx = false); //!< Read sample from queue possibly scaling to Tx size
|
||||||
uint32_t length() const { return m_dataReadQueue.size(); } //!< Returns queue length
|
uint32_t length() const { return m_dataReadQueue.size(); } //!< Returns queue length
|
||||||
uint32_t size() const { return m_maxSize; } //!< Returns queue size (max length)
|
uint32_t size() const { return m_maxSize; } //!< Returns queue size (max length)
|
||||||
@ -45,8 +46,8 @@ public:
|
|||||||
static const uint32_t MinimumMaxSize;
|
static const uint32_t MinimumMaxSize;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QQueue<SDRDaemonDataBlock*> m_dataReadQueue;
|
QQueue<RemoteDataBlock*> m_dataReadQueue;
|
||||||
SDRDaemonDataBlock *m_dataBlock;
|
RemoteDataBlock *m_dataBlock;
|
||||||
uint32_t m_maxSize;
|
uint32_t m_maxSize;
|
||||||
uint32_t m_blockIndex;
|
uint32_t m_blockIndex;
|
||||||
uint32_t m_sampleIndex;
|
uint32_t m_sampleIndex;
|
||||||
@ -90,4 +91,4 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* SDRDAEMON_CHANNEL_SDRDAEMONDATAREADQUEUE_H_ */
|
#endif /* CHANNEL_REMOTEDATAREADQUEUE_H_ */
|
Loading…
Reference in New Issue
Block a user