mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-25 01:18:38 -05:00
Compare commits
6 Commits
bb1f833d02
...
ef4b54a7b1
Author | SHA1 | Date | |
---|---|---|---|
|
ef4b54a7b1 | ||
|
20ed490018 | ||
|
4faa3dbe8c | ||
|
3cb22c8b8a | ||
|
f1059bd547 | ||
|
2515f08409 |
@ -85,7 +85,6 @@ void RemoteSinkSender::sendDataBlock(RemoteDataBlock *dataBlock)
|
|||||||
|
|
||||||
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;
|
|
||||||
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;
|
||||||
RemoteSuperBlock *txBlockx = dataBlock->m_superBlocks;
|
RemoteSuperBlock *txBlockx = dataBlock->m_superBlocks;
|
||||||
@ -94,11 +93,8 @@ void RemoteSinkSender::sendDataBlock(RemoteDataBlock *dataBlock)
|
|||||||
{
|
{
|
||||||
if (m_socket)
|
if (m_socket)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < RemoteNbOrginalBlocks; i++)
|
for (int i = 0; i < RemoteNbOrginalBlocks; i++) { // send block via UDP
|
||||||
{
|
|
||||||
// send block via UDP
|
|
||||||
m_socket->writeDatagram((const char*)&txBlockx[i], (qint64 ) RemoteUdpSize, m_address, dataPort);
|
m_socket->writeDatagram((const char*)&txBlockx[i], (qint64 ) RemoteUdpSize, m_address, dataPort);
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(txDelay));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,11 +135,8 @@ void RemoteSinkSender::sendDataBlock(RemoteDataBlock *dataBlock)
|
|||||||
// Transmit all blocks
|
// Transmit all blocks
|
||||||
if (m_socket)
|
if (m_socket)
|
||||||
{
|
{
|
||||||
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 ) RemoteUdpSize, m_address, dataPort);
|
m_socket->writeDatagram((const char*)&txBlockx[i], (qint64 ) RemoteUdpSize, m_address, dataPort);
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(txDelay));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,6 @@ RemoteSinkSink::RemoteSinkSink() :
|
|||||||
m_frequencyOffset(0),
|
m_frequencyOffset(0),
|
||||||
m_basebandSampleRate(48000),
|
m_basebandSampleRate(48000),
|
||||||
m_nbBlocksFEC(0),
|
m_nbBlocksFEC(0),
|
||||||
m_txDelay(35),
|
|
||||||
m_dataAddress("127.0.0.1"),
|
m_dataAddress("127.0.0.1"),
|
||||||
m_dataPort(9090)
|
m_dataPort(9090)
|
||||||
{
|
{
|
||||||
@ -165,7 +164,6 @@ void RemoteSinkSink::feed(const SampleVector::const_iterator& begin, const Sampl
|
|||||||
m_dataBlock->m_txControlBlock.m_processed = false;
|
m_dataBlock->m_txControlBlock.m_processed = false;
|
||||||
m_dataBlock->m_txControlBlock.m_complete = true;
|
m_dataBlock->m_txControlBlock.m_complete = true;
|
||||||
m_dataBlock->m_txControlBlock.m_nbBlocksFEC = m_nbBlocksFEC;
|
m_dataBlock->m_txControlBlock.m_nbBlocksFEC = m_nbBlocksFEC;
|
||||||
m_dataBlock->m_txControlBlock.m_txDelay = m_txDelay;
|
|
||||||
m_dataBlock->m_txControlBlock.m_dataAddress = m_dataAddress;
|
m_dataBlock->m_txControlBlock.m_dataAddress = m_dataAddress;
|
||||||
m_dataBlock->m_txControlBlock.m_dataPort = m_dataPort;
|
m_dataBlock->m_txControlBlock.m_dataPort = m_dataPort;
|
||||||
|
|
||||||
|
@ -61,7 +61,6 @@ private:
|
|||||||
int64_t m_frequencyOffset;
|
int64_t m_frequencyOffset;
|
||||||
uint32_t m_basebandSampleRate;
|
uint32_t m_basebandSampleRate;
|
||||||
int m_nbBlocksFEC;
|
int m_nbBlocksFEC;
|
||||||
int m_txDelay;
|
|
||||||
QString m_dataAddress;
|
QString m_dataAddress;
|
||||||
uint16_t m_dataPort;
|
uint16_t m_dataPort;
|
||||||
|
|
||||||
|
@ -330,12 +330,9 @@ void RemoteSourceGUI::on_dataPort_returnPressed()
|
|||||||
bool dataOk;
|
bool dataOk;
|
||||||
int dataPort = ui->dataPort->text().toInt(&dataOk);
|
int dataPort = ui->dataPort->text().toInt(&dataOk);
|
||||||
|
|
||||||
if((!dataOk) || (dataPort < 1024) || (dataPort > 65535))
|
if ((!dataOk) || (dataPort < 1024) || (dataPort > 65535)) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
m_settings.m_dataPort = dataPort;
|
m_settings.m_dataPort = dataPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,8 +347,7 @@ void RemoteSourceGUI::on_dataApplyButton_clicked(bool checked)
|
|||||||
bool dataOk;
|
bool dataOk;
|
||||||
int udpDataPort = ui->dataPort->text().toInt(&dataOk);
|
int udpDataPort = ui->dataPort->text().toInt(&dataOk);
|
||||||
|
|
||||||
if((dataOk) && (udpDataPort >= 1024) && (udpDataPort < 65535))
|
if ((dataOk) && (udpDataPort >= 1024) && (udpDataPort < 65535)) {
|
||||||
{
|
|
||||||
m_settings.m_dataPort = udpDataPort;
|
m_settings.m_dataPort = udpDataPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@
|
|||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="pushButton">
|
<widget class="QPushButton" name="dataApplyButton">
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>30</width>
|
<width>30</width>
|
||||||
|
@ -35,7 +35,9 @@ RemoteSourceSource::RemoteSourceSource() :
|
|||||||
}
|
}
|
||||||
|
|
||||||
RemoteSourceSource::~RemoteSourceSource()
|
RemoteSourceSource::~RemoteSourceSource()
|
||||||
{}
|
{
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
void RemoteSourceSource::pull(SampleVector::iterator begin, unsigned int nbSamples)
|
void RemoteSourceSource::pull(SampleVector::iterator begin, unsigned int nbSamples)
|
||||||
{
|
{
|
||||||
@ -105,7 +107,7 @@ void RemoteSourceSource::stop()
|
|||||||
{
|
{
|
||||||
stopWorker();
|
stopWorker();
|
||||||
m_sourceWorker->deleteLater();
|
m_sourceWorker->deleteLater();
|
||||||
m_sourceWorker = 0;
|
m_sourceWorker = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_running = false;
|
m_running = false;
|
||||||
@ -276,4 +278,4 @@ void RemoteSourceSource::applyChannelSettings(int channelSampleRate, bool force)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_channelSampleRate = channelSampleRate;
|
m_channelSampleRate = channelSampleRate;
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
#include <channel/remotedataqueue.h>
|
#include <channel/remotedataqueue.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <QUdpSocket>
|
#include <QThread>
|
||||||
#include "cm256cc/cm256.h"
|
|
||||||
|
|
||||||
|
#include "cm256cc/cm256.h"
|
||||||
#include "remotesourceworker.h"
|
#include "remotesourceworker.h"
|
||||||
|
|
||||||
MESSAGE_CLASS_DEFINITION(RemoteSourceWorker::MsgDataBind, Message)
|
MESSAGE_CLASS_DEFINITION(RemoteSourceWorker::MsgDataBind, Message)
|
||||||
@ -31,10 +31,18 @@ RemoteSourceWorker::RemoteSourceWorker(RemoteDataQueue *dataQueue, QObject* pare
|
|||||||
m_running(false),
|
m_running(false),
|
||||||
m_dataQueue(dataQueue),
|
m_dataQueue(dataQueue),
|
||||||
m_address(QHostAddress::LocalHost),
|
m_address(QHostAddress::LocalHost),
|
||||||
m_socket(nullptr)
|
m_socket(this),
|
||||||
|
m_mutex(QMutex::Recursive),
|
||||||
|
m_sampleRate(0)
|
||||||
{
|
{
|
||||||
std::fill(m_dataBlocks, m_dataBlocks+4, (RemoteDataBlock *) 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);
|
||||||
|
connect(&m_socket, SIGNAL(readyRead()),this, SLOT(recv()));
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
|
||||||
|
connect(&m_socket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), this, &APRSWorker::errorOccurred);
|
||||||
|
#else
|
||||||
|
connect(&m_socket, &QAbstractSocket::errorOccurred, this, &RemoteSourceWorker::errorOccurred);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteSourceWorker::~RemoteSourceWorker()
|
RemoteSourceWorker::~RemoteSourceWorker()
|
||||||
@ -48,19 +56,43 @@ void RemoteSourceWorker::dataBind(const QString& address, uint16_t port)
|
|||||||
m_inputMessageQueue.push(msg);
|
m_inputMessageQueue.push(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteSourceWorker::startWork()
|
bool RemoteSourceWorker::startWork()
|
||||||
{
|
{
|
||||||
qDebug("RemoteSourceWorker::startWork");
|
qDebug("RemoteSourceWorker::startWork");
|
||||||
m_socket = new QUdpSocket(this);
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
m_running = false;
|
m_socket.setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, getDataSocketBufferSize(m_sampleRate));
|
||||||
|
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||||
|
connect(thread(), SIGNAL(started()), this, SLOT(started()));
|
||||||
|
connect(thread(), SIGNAL(finished()), this, SLOT(finished()));
|
||||||
|
m_running = true;
|
||||||
|
return m_running;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteSourceWorker::started()
|
||||||
|
{
|
||||||
|
disconnect(thread(), SIGNAL(started()), this, SLOT(started()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteSourceWorker::stopWork()
|
void RemoteSourceWorker::stopWork()
|
||||||
{
|
{
|
||||||
qDebug("RemoteSourceWorker::stopWork");
|
qDebug("RemoteSourceWorker::stopWork");
|
||||||
delete m_socket;
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
m_socket = nullptr;
|
disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteSourceWorker::finished()
|
||||||
|
{
|
||||||
|
// Close any existing connection
|
||||||
|
if (m_socket.isOpen()) {
|
||||||
|
m_socket.close();
|
||||||
|
}
|
||||||
m_running = false;
|
m_running = false;
|
||||||
|
disconnect(thread(), SIGNAL(finished()), this, SLOT(finished()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteSourceWorker::errorOccurred(QAbstractSocket::SocketError socketError)
|
||||||
|
{
|
||||||
|
qWarning() << "RemoteSourceWorker::errorOccurred: " << socketError;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteSourceWorker::handleInputMessages()
|
void RemoteSourceWorker::handleInputMessages()
|
||||||
@ -71,15 +103,12 @@ void RemoteSourceWorker::handleInputMessages()
|
|||||||
{
|
{
|
||||||
if (MsgDataBind::match(*message))
|
if (MsgDataBind::match(*message))
|
||||||
{
|
{
|
||||||
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
MsgDataBind* notif = (MsgDataBind*) message;
|
MsgDataBind* notif = (MsgDataBind*) message;
|
||||||
qDebug("RemoteSourceWorker::handleInputMessages: MsgDataBind: %s:%d", qPrintable(notif->getAddress().toString()), notif->getPort());
|
qDebug("RemoteSourceWorker::handleInputMessages: MsgDataBind: %s:%d", qPrintable(notif->getAddress().toString()), notif->getPort());
|
||||||
|
disconnect(&m_socket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
|
||||||
if (m_socket)
|
m_socket.bind(notif->getAddress(), notif->getPort());
|
||||||
{
|
connect(&m_socket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
|
||||||
disconnect(m_socket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
|
|
||||||
m_socket->bind(notif->getAddress(), notif->getPort());
|
|
||||||
connect(m_socket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,16 +118,30 @@ void RemoteSourceWorker::readPendingDatagrams()
|
|||||||
RemoteSuperBlock superBlock;
|
RemoteSuperBlock superBlock;
|
||||||
qint64 size;
|
qint64 size;
|
||||||
|
|
||||||
while (m_socket->hasPendingDatagrams())
|
while (m_socket.hasPendingDatagrams())
|
||||||
{
|
{
|
||||||
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(RemoteSuperBlock), &sender, &senderPort);
|
size = m_socket.readDatagram((char *) &superBlock, (long long int) sizeof(RemoteSuperBlock), &sender, &senderPort);
|
||||||
|
|
||||||
if (size == sizeof(RemoteSuperBlock))
|
if (size == sizeof(RemoteSuperBlock))
|
||||||
{
|
{
|
||||||
unsigned int dataBlockIndex = superBlock.m_header.m_frameIndex % m_nbDataBlocks;
|
unsigned int dataBlockIndex = superBlock.m_header.m_frameIndex % m_nbDataBlocks;
|
||||||
|
int blockIndex = superBlock.m_header.m_blockIndex;
|
||||||
|
|
||||||
|
if (blockIndex == 0) // first block with meta data
|
||||||
|
{
|
||||||
|
const RemoteMetaDataFEC *metaData = (const RemoteMetaDataFEC *) &superBlock.m_protectedBlock;
|
||||||
|
uint32_t sampleRate = metaData->m_sampleRate;
|
||||||
|
|
||||||
|
if (m_sampleRate != sampleRate)
|
||||||
|
{
|
||||||
|
qDebug("RemoteSourceWorker::readPendingDatagrams: sampleRate: %u", sampleRate);
|
||||||
|
m_socket.setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, getDataSocketBufferSize(sampleRate));
|
||||||
|
m_sampleRate = sampleRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// create the first block for this index
|
// create the first block for this index
|
||||||
if (m_dataBlocks[dataBlockIndex] == 0) {
|
if (m_dataBlocks[dataBlockIndex] == 0) {
|
||||||
@ -145,3 +188,12 @@ void RemoteSourceWorker::readPendingDatagrams()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int RemoteSourceWorker::getDataSocketBufferSize(uint32_t inSampleRate)
|
||||||
|
{
|
||||||
|
// set a floor value at 24 kS/s
|
||||||
|
uint32_t samplerate = inSampleRate < 24000 ? 24000 : inSampleRate;
|
||||||
|
// 250 ms (1/4s) at current sample rate
|
||||||
|
int bufferSize = (samplerate * 2 * (SDR_RX_SAMP_SZ == 16 ? 2 : 4)) / 4;
|
||||||
|
qDebug("RemoteSourceWorker::getDataSocketBufferSize: %d bytes", bufferSize);
|
||||||
|
return bufferSize;
|
||||||
|
}
|
||||||
|
@ -20,13 +20,13 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
|
#include <QUdpSocket>
|
||||||
|
|
||||||
#include "util/message.h"
|
#include "util/message.h"
|
||||||
#include "util/messagequeue.h"
|
#include "util/messagequeue.h"
|
||||||
|
|
||||||
class RemoteDataQueue;
|
class RemoteDataQueue;
|
||||||
class RemoteDataBlock;
|
class RemoteDataBlock;
|
||||||
class QUdpSocket;
|
|
||||||
|
|
||||||
class RemoteSourceWorker : public QObject {
|
class RemoteSourceWorker : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -57,7 +57,7 @@ public:
|
|||||||
RemoteSourceWorker(RemoteDataQueue *dataQueue, QObject* parent = 0);
|
RemoteSourceWorker(RemoteDataQueue *dataQueue, QObject* parent = 0);
|
||||||
~RemoteSourceWorker();
|
~RemoteSourceWorker();
|
||||||
|
|
||||||
void startWork();
|
bool startWork();
|
||||||
void stopWork();
|
void stopWork();
|
||||||
void dataBind(const QString& address, uint16_t port);
|
void dataBind(const QString& address, uint16_t port);
|
||||||
|
|
||||||
@ -68,12 +68,19 @@ private:
|
|||||||
RemoteDataQueue *m_dataQueue;
|
RemoteDataQueue *m_dataQueue;
|
||||||
|
|
||||||
QHostAddress m_address;
|
QHostAddress m_address;
|
||||||
QUdpSocket *m_socket;
|
QUdpSocket m_socket;
|
||||||
|
QMutex m_mutex;
|
||||||
|
|
||||||
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
|
||||||
RemoteDataBlock *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
|
||||||
|
uint32_t m_sampleRate; //!< current sample rate from meta data
|
||||||
|
|
||||||
|
static int getDataSocketBufferSize(uint32_t inSampleRate);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void started();
|
||||||
|
void finished();
|
||||||
|
void errorOccurred(QAbstractSocket::SocketError socketError);
|
||||||
void handleInputMessages();
|
void handleInputMessages();
|
||||||
void readPendingDatagrams();
|
void readPendingDatagrams();
|
||||||
};
|
};
|
||||||
|
@ -100,8 +100,6 @@ bool RemoteOutput::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_remoteOutputWorker->setTxDelay(m_settings.m_txDelay);
|
|
||||||
|
|
||||||
mutexLocker.unlock();
|
mutexLocker.unlock();
|
||||||
//applySettings(m_generalSettings, m_settings, true);
|
//applySettings(m_generalSettings, m_settings, true);
|
||||||
qDebug("RemoteOutput::start: started");
|
qDebug("RemoteOutput::start: started");
|
||||||
@ -260,7 +258,6 @@ void RemoteOutput::applySettings(const RemoteOutputSettings& settings, bool forc
|
|||||||
{
|
{
|
||||||
QMutexLocker mutexLocker(&m_mutex);
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
bool forwardChange = false;
|
bool forwardChange = false;
|
||||||
bool changeTxDelay = false;
|
|
||||||
QList<QString> reverseAPIKeys;
|
QList<QString> reverseAPIKeys;
|
||||||
|
|
||||||
if ((m_settings.m_dataAddress != settings.m_dataAddress) || force) {
|
if ((m_settings.m_dataAddress != settings.m_dataAddress) || force) {
|
||||||
@ -295,7 +292,6 @@ void RemoteOutput::applySettings(const RemoteOutputSettings& settings, bool forc
|
|||||||
m_tickMultiplier = m_tickMultiplier < 20 ? 20 : m_tickMultiplier; // not below half a second
|
m_tickMultiplier = m_tickMultiplier < 20 ? 20 : m_tickMultiplier; // not below half a second
|
||||||
|
|
||||||
forwardChange = true;
|
forwardChange = true;
|
||||||
changeTxDelay = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (force || (m_settings.m_nbFECBlocks != settings.m_nbFECBlocks))
|
if (force || (m_settings.m_nbFECBlocks != settings.m_nbFECBlocks))
|
||||||
@ -305,28 +301,12 @@ void RemoteOutput::applySettings(const RemoteOutputSettings& settings, bool forc
|
|||||||
if (m_remoteOutputWorker != 0) {
|
if (m_remoteOutputWorker != 0) {
|
||||||
m_remoteOutputWorker->setNbBlocksFEC(settings.m_nbFECBlocks);
|
m_remoteOutputWorker->setNbBlocksFEC(settings.m_nbFECBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
changeTxDelay = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (force || (m_settings.m_txDelay != settings.m_txDelay))
|
|
||||||
{
|
|
||||||
reverseAPIKeys.append("txDelay");
|
|
||||||
changeTxDelay = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changeTxDelay)
|
|
||||||
{
|
|
||||||
if (m_remoteOutputWorker != 0) {
|
|
||||||
m_remoteOutputWorker->setTxDelay(settings.m_txDelay);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mutexLocker.unlock();
|
mutexLocker.unlock();
|
||||||
|
|
||||||
qDebug() << "RemoteOutput::applySettings:"
|
qDebug() << "RemoteOutput::applySettings:"
|
||||||
<< " m_sampleRate: " << settings.m_sampleRate
|
<< " m_sampleRate: " << settings.m_sampleRate
|
||||||
<< " m_txDelay: " << settings.m_txDelay
|
|
||||||
<< " m_nbFECBlocks: " << settings.m_nbFECBlocks
|
<< " m_nbFECBlocks: " << settings.m_nbFECBlocks
|
||||||
<< " m_apiAddress: " << settings.m_apiAddress
|
<< " m_apiAddress: " << settings.m_apiAddress
|
||||||
<< " m_apiPort: " << settings.m_apiPort
|
<< " m_apiPort: " << settings.m_apiPort
|
||||||
@ -421,9 +401,6 @@ void RemoteOutput::webapiUpdateDeviceSettings(
|
|||||||
if (deviceSettingsKeys.contains("sampleRate")) {
|
if (deviceSettingsKeys.contains("sampleRate")) {
|
||||||
settings.m_sampleRate = response.getRemoteOutputSettings()->getSampleRate();
|
settings.m_sampleRate = response.getRemoteOutputSettings()->getSampleRate();
|
||||||
}
|
}
|
||||||
if (deviceSettingsKeys.contains("txDelay")) {
|
|
||||||
settings.m_txDelay = response.getRemoteOutputSettings()->getTxDelay();
|
|
||||||
}
|
|
||||||
if (deviceSettingsKeys.contains("nbFECBlocks")) {
|
if (deviceSettingsKeys.contains("nbFECBlocks")) {
|
||||||
settings.m_nbFECBlocks = response.getRemoteOutputSettings()->getNbFecBlocks();
|
settings.m_nbFECBlocks = response.getRemoteOutputSettings()->getNbFecBlocks();
|
||||||
}
|
}
|
||||||
@ -474,7 +451,6 @@ void RemoteOutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& re
|
|||||||
{
|
{
|
||||||
response.getRemoteOutputSettings()->setCenterFrequency(settings.m_centerFrequency);
|
response.getRemoteOutputSettings()->setCenterFrequency(settings.m_centerFrequency);
|
||||||
response.getRemoteOutputSettings()->setSampleRate(settings.m_sampleRate);
|
response.getRemoteOutputSettings()->setSampleRate(settings.m_sampleRate);
|
||||||
response.getRemoteOutputSettings()->setTxDelay(settings.m_txDelay);
|
|
||||||
response.getRemoteOutputSettings()->setNbFecBlocks(settings.m_nbFECBlocks);
|
response.getRemoteOutputSettings()->setNbFecBlocks(settings.m_nbFECBlocks);
|
||||||
response.getRemoteOutputSettings()->setApiAddress(new QString(settings.m_apiAddress));
|
response.getRemoteOutputSettings()->setApiAddress(new QString(settings.m_apiAddress));
|
||||||
response.getRemoteOutputSettings()->setApiPort(settings.m_apiPort);
|
response.getRemoteOutputSettings()->setApiPort(settings.m_apiPort);
|
||||||
@ -659,9 +635,6 @@ void RemoteOutput::webapiReverseSendSettings(QList<QString>& deviceSettingsKeys,
|
|||||||
if (deviceSettingsKeys.contains("sampleRate") || force) {
|
if (deviceSettingsKeys.contains("sampleRate") || force) {
|
||||||
swgRemoteOutputSettings->setSampleRate(settings.m_sampleRate);
|
swgRemoteOutputSettings->setSampleRate(settings.m_sampleRate);
|
||||||
}
|
}
|
||||||
if (deviceSettingsKeys.contains("txDelay") || force) {
|
|
||||||
swgRemoteOutputSettings->setTxDelay(settings.m_txDelay);
|
|
||||||
}
|
|
||||||
if (deviceSettingsKeys.contains("nbFECBlocks") || force) {
|
if (deviceSettingsKeys.contains("nbFECBlocks") || force) {
|
||||||
swgRemoteOutputSettings->setNbFecBlocks(settings.m_nbFECBlocks);
|
swgRemoteOutputSettings->setNbFecBlocks(settings.m_nbFECBlocks);
|
||||||
}
|
}
|
||||||
|
@ -211,20 +211,11 @@ void RemoteOutputSinkGui::updateSampleRate()
|
|||||||
ui->deviceRateText->setText(tr("%1k").arg((float)(m_sampleRate) / 1000));
|
ui->deviceRateText->setText(tr("%1k").arg((float)(m_sampleRate) / 1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteOutputSinkGui::updateTxDelayTooltip()
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
ui->txDelayText->setToolTip(tr("%1 us").arg(QString::number(delay*1e6, 'f', 0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoteOutputSinkGui::displaySettings()
|
void RemoteOutputSinkGui::displaySettings()
|
||||||
{
|
{
|
||||||
blockApplySettings(true);
|
blockApplySettings(true);
|
||||||
ui->centerFrequency->setValue(m_deviceCenterFrequency / 1000);
|
ui->centerFrequency->setValue(m_deviceCenterFrequency / 1000);
|
||||||
ui->sampleRate->setValue(m_settings.m_sampleRate);
|
ui->sampleRate->setValue(m_settings.m_sampleRate);
|
||||||
ui->txDelay->setValue(m_settings.m_txDelay*100);
|
|
||||||
ui->txDelayText->setText(tr("%1").arg(m_settings.m_txDelay*100));
|
|
||||||
ui->nbFECBlocks->setValue(m_settings.m_nbFECBlocks);
|
ui->nbFECBlocks->setValue(m_settings.m_nbFECBlocks);
|
||||||
|
|
||||||
QString s0 = QString::number(128 + m_settings.m_nbFECBlocks, 'f', 0);
|
QString s0 = QString::number(128 + m_settings.m_nbFECBlocks, 'f', 0);
|
||||||
@ -288,15 +279,6 @@ void RemoteOutputSinkGui::updateStatus()
|
|||||||
void RemoteOutputSinkGui::on_sampleRate_changed(quint64 value)
|
void RemoteOutputSinkGui::on_sampleRate_changed(quint64 value)
|
||||||
{
|
{
|
||||||
m_settings.m_sampleRate = value;
|
m_settings.m_sampleRate = value;
|
||||||
updateTxDelayTooltip();
|
|
||||||
sendSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoteOutputSinkGui::on_txDelay_valueChanged(int value)
|
|
||||||
{
|
|
||||||
m_settings.m_txDelay = value / 100.0;
|
|
||||||
ui->txDelayText->setText(tr("%1").arg(value));
|
|
||||||
updateTxDelayTooltip();
|
|
||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,7 +290,6 @@ void RemoteOutputSinkGui::on_nbFECBlocks_valueChanged(int value)
|
|||||||
QString s = QString::number(nbOriginalBlocks + nbFECBlocks, 'f', 0);
|
QString s = QString::number(nbOriginalBlocks + nbFECBlocks, 'f', 0);
|
||||||
QString s1 = QString::number(nbFECBlocks, 'f', 0);
|
QString s1 = QString::number(nbFECBlocks, 'f', 0);
|
||||||
ui->nominalNbBlocksText->setText(tr("%1/%2").arg(s).arg(s1));
|
ui->nominalNbBlocksText->setText(tr("%1/%2").arg(s).arg(s1));
|
||||||
updateTxDelayTooltip();
|
|
||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +124,6 @@ private:
|
|||||||
void sendControl(bool force = false);
|
void sendControl(bool force = false);
|
||||||
void sendSettings();
|
void sendSettings();
|
||||||
void updateSampleRate();
|
void updateSampleRate();
|
||||||
void updateTxDelayTooltip();
|
|
||||||
void displayEventCounts();
|
void displayEventCounts();
|
||||||
void displayEventStatus(int recoverableCount, int unrecoverableCount);
|
void displayEventStatus(int recoverableCount, int unrecoverableCount);
|
||||||
void displayEventTimer();
|
void displayEventTimer();
|
||||||
@ -134,7 +133,6 @@ private:
|
|||||||
private slots:
|
private slots:
|
||||||
void handleInputMessages();
|
void handleInputMessages();
|
||||||
void on_sampleRate_changed(quint64 value);
|
void on_sampleRate_changed(quint64 value);
|
||||||
void on_txDelay_valueChanged(int value);
|
|
||||||
void on_nbFECBlocks_valueChanged(int value);
|
void on_nbFECBlocks_valueChanged(int value);
|
||||||
void on_deviceIndex_returnPressed();
|
void on_deviceIndex_returnPressed();
|
||||||
void on_channelIndex_returnPressed();
|
void on_channelIndex_returnPressed();
|
||||||
|
@ -249,60 +249,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="txDelayLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>UDly</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QDial" name="txDelay">
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>24</width>
|
|
||||||
<height>24</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Delay between consecutive UDP packets in percentage of nominal UDP packet process time</string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>10</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>90</number>
|
|
||||||
</property>
|
|
||||||
<property name="pageStep">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>50</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="txDelayText">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>90</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer">
|
<spacer name="horizontalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
@ -22,8 +22,6 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
#include <thread>
|
|
||||||
#include <chrono>
|
|
||||||
#include <boost/crc.hpp>
|
#include <boost/crc.hpp>
|
||||||
#include <boost/cstdint.hpp>
|
#include <boost/cstdint.hpp>
|
||||||
|
|
||||||
@ -93,7 +91,6 @@ void RemoteOutputSender::sendDataBlock(RemoteDataBlock *dataBlock)
|
|||||||
|
|
||||||
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;
|
|
||||||
m_remoteHostAddress.setAddress(dataBlock->m_txControlBlock.m_dataAddress);
|
m_remoteHostAddress.setAddress(dataBlock->m_txControlBlock.m_dataAddress);
|
||||||
uint16_t dataPort = dataBlock->m_txControlBlock.m_dataPort;
|
uint16_t dataPort = dataBlock->m_txControlBlock.m_dataPort;
|
||||||
RemoteSuperBlock *txBlockx = dataBlock->m_superBlocks;
|
RemoteSuperBlock *txBlockx = dataBlock->m_superBlocks;
|
||||||
@ -102,11 +99,8 @@ void RemoteOutputSender::sendDataBlock(RemoteDataBlock *dataBlock)
|
|||||||
{
|
{
|
||||||
if (m_udpSocket)
|
if (m_udpSocket)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < RemoteNbOrginalBlocks; i++)
|
for (int i = 0; i < RemoteNbOrginalBlocks; i++) { // send block via UDP
|
||||||
{
|
|
||||||
// send block via UDP
|
|
||||||
m_udpSocket->writeDatagram((const char*)&txBlockx[i], (qint64 ) RemoteUdpSize, m_remoteHostAddress, dataPort);
|
m_udpSocket->writeDatagram((const char*)&txBlockx[i], (qint64 ) RemoteUdpSize, m_remoteHostAddress, dataPort);
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(txDelay));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,11 +146,8 @@ void RemoteOutputSender::sendDataBlock(RemoteDataBlock *dataBlock)
|
|||||||
// Transmit all blocks
|
// Transmit all blocks
|
||||||
if (m_udpSocket)
|
if (m_udpSocket)
|
||||||
{
|
{
|
||||||
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_udpSocket->writeDatagram((const char*)&txBlockx[i], (qint64 ) RemoteUdpSize, m_remoteHostAddress, dataPort);
|
m_udpSocket->writeDatagram((const char*)&txBlockx[i], (qint64 ) RemoteUdpSize, m_remoteHostAddress, dataPort);
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(txDelay));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,6 @@ void RemoteOutputSettings::resetToDefaults()
|
|||||||
{
|
{
|
||||||
m_centerFrequency = 435000*1000;
|
m_centerFrequency = 435000*1000;
|
||||||
m_sampleRate = 48000;
|
m_sampleRate = 48000;
|
||||||
m_txDelay = 0.35;
|
|
||||||
m_nbFECBlocks = 0;
|
m_nbFECBlocks = 0;
|
||||||
m_apiAddress = "127.0.0.1";
|
m_apiAddress = "127.0.0.1";
|
||||||
m_apiPort = 9091;
|
m_apiPort = 9091;
|
||||||
@ -47,7 +46,6 @@ QByteArray RemoteOutputSettings::serialize() const
|
|||||||
|
|
||||||
s.writeU64(1, m_centerFrequency);
|
s.writeU64(1, m_centerFrequency);
|
||||||
s.writeU32(2, m_sampleRate);
|
s.writeU32(2, m_sampleRate);
|
||||||
s.writeFloat(3, m_txDelay);
|
|
||||||
s.writeU32(4, m_nbFECBlocks);
|
s.writeU32(4, m_nbFECBlocks);
|
||||||
s.writeString(5, m_apiAddress);
|
s.writeString(5, m_apiAddress);
|
||||||
s.writeU32(6, m_apiPort);
|
s.writeU32(6, m_apiPort);
|
||||||
@ -79,7 +77,6 @@ bool RemoteOutputSettings::deserialize(const QByteArray& data)
|
|||||||
|
|
||||||
d.readU64(1, &m_centerFrequency, 435000*1000);
|
d.readU64(1, &m_centerFrequency, 435000*1000);
|
||||||
d.readU32(2, &m_sampleRate, 48000);
|
d.readU32(2, &m_sampleRate, 48000);
|
||||||
d.readFloat(3, &m_txDelay, 0.5);
|
|
||||||
d.readU32(4, &m_nbFECBlocks, 0);
|
d.readU32(4, &m_nbFECBlocks, 0);
|
||||||
d.readString(5, &m_apiAddress, "127.0.0.1");
|
d.readString(5, &m_apiAddress, "127.0.0.1");
|
||||||
d.readU32(6, &uintval, 9090);
|
d.readU32(6, &uintval, 9090);
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
struct RemoteOutputSettings {
|
struct RemoteOutputSettings {
|
||||||
quint64 m_centerFrequency;
|
quint64 m_centerFrequency;
|
||||||
quint32 m_sampleRate;
|
quint32 m_sampleRate;
|
||||||
float m_txDelay;
|
|
||||||
quint32 m_nbFECBlocks;
|
quint32 m_nbFECBlocks;
|
||||||
QString m_apiAddress;
|
QString m_apiAddress;
|
||||||
quint16 m_apiPort;
|
quint16 m_apiPort;
|
||||||
|
@ -49,7 +49,6 @@ public:
|
|||||||
|
|
||||||
void setSamplerate(int samplerate);
|
void setSamplerate(int samplerate);
|
||||||
void setNbBlocksFEC(uint32_t nbBlocksFEC) { m_udpSinkFEC.setNbBlocksFEC(nbBlocksFEC); };
|
void setNbBlocksFEC(uint32_t nbBlocksFEC) { m_udpSinkFEC.setNbBlocksFEC(nbBlocksFEC); };
|
||||||
void setTxDelay(float txDelay) { m_udpSinkFEC.setTxDelay(txDelay); };
|
|
||||||
void setDataAddress(const QString& address, uint16_t port) { m_udpSinkFEC.setRemoteAddress(address, port); }
|
void setDataAddress(const QString& address, uint16_t port) { m_udpSinkFEC.setRemoteAddress(address, port); }
|
||||||
|
|
||||||
bool isRunning() const { return m_running; }
|
bool isRunning() const { return m_running; }
|
||||||
|
@ -32,7 +32,6 @@ UDPSinkFEC::UDPSinkFEC() :
|
|||||||
m_nbSamples(0),
|
m_nbSamples(0),
|
||||||
m_nbBlocksFEC(0),
|
m_nbBlocksFEC(0),
|
||||||
m_txDelayRatio(0.0),
|
m_txDelayRatio(0.0),
|
||||||
m_txDelay(0),
|
|
||||||
m_dataBlock(nullptr),
|
m_dataBlock(nullptr),
|
||||||
m_txBlockIndex(0),
|
m_txBlockIndex(0),
|
||||||
m_txBlocksIndex(0),
|
m_txBlocksIndex(0),
|
||||||
@ -71,35 +70,16 @@ void UDPSinkFEC::stopSender()
|
|||||||
m_senderThread->wait();
|
m_senderThread->wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDPSinkFEC::setTxDelay(float txDelayRatio)
|
|
||||||
{
|
|
||||||
// delay is calculated from the fraction of the nominal UDP block process time
|
|
||||||
// frame size: 127 * (126 or 63 samples depending on I or Q sample bytes of 2 or 4 bytes respectively)
|
|
||||||
// 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
|
|
||||||
m_txDelayRatio = txDelayRatio;
|
|
||||||
int samplesPerBlock = RemoteNbBytesPerBlock / sizeof(Sample);
|
|
||||||
double delay = m_sampleRate == 0 ? 1.0 : (127*samplesPerBlock*txDelayRatio) / m_sampleRate;
|
|
||||||
delay /= 128 + m_nbBlocksFEC;
|
|
||||||
m_txDelay = delay * 1e6;
|
|
||||||
qDebug() << "UDPSinkFEC::setTxDelay:"
|
|
||||||
<< "txDelay:" << txDelayRatio
|
|
||||||
<< "m_txDelay:" << m_txDelay << " us"
|
|
||||||
<< "m_sampleRate:" << m_sampleRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UDPSinkFEC::setNbBlocksFEC(uint32_t nbBlocksFEC)
|
void UDPSinkFEC::setNbBlocksFEC(uint32_t nbBlocksFEC)
|
||||||
{
|
{
|
||||||
qDebug() << "UDPSinkFEC::setNbBlocksFEC: nbBlocksFEC: " << nbBlocksFEC;
|
qDebug() << "UDPSinkFEC::setNbBlocksFEC: nbBlocksFEC: " << nbBlocksFEC;
|
||||||
m_nbBlocksFEC = nbBlocksFEC;
|
m_nbBlocksFEC = nbBlocksFEC;
|
||||||
setTxDelay(m_txDelayRatio);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDPSinkFEC::setSampleRate(uint32_t sampleRate)
|
void UDPSinkFEC::setSampleRate(uint32_t sampleRate)
|
||||||
{
|
{
|
||||||
qDebug() << "UDPSinkFEC::setSampleRate: sampleRate: " << sampleRate;
|
qDebug() << "UDPSinkFEC::setSampleRate: sampleRate: " << sampleRate;
|
||||||
m_sampleRate = sampleRate;
|
m_sampleRate = sampleRate;
|
||||||
setTxDelay(m_txDelayRatio);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDPSinkFEC::setRemoteAddress(const QString& address, uint16_t port)
|
void UDPSinkFEC::setRemoteAddress(const QString& address, uint16_t port)
|
||||||
@ -200,7 +180,6 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk
|
|||||||
m_dataBlock->m_txControlBlock.m_processed = false;
|
m_dataBlock->m_txControlBlock.m_processed = false;
|
||||||
m_dataBlock->m_txControlBlock.m_complete = true;
|
m_dataBlock->m_txControlBlock.m_complete = true;
|
||||||
m_dataBlock->m_txControlBlock.m_nbBlocksFEC = m_nbBlocksFEC;
|
m_dataBlock->m_txControlBlock.m_nbBlocksFEC = m_nbBlocksFEC;
|
||||||
m_dataBlock->m_txControlBlock.m_txDelay = m_txDelay;
|
|
||||||
m_dataBlock->m_txControlBlock.m_dataAddress = m_remoteAddress;
|
m_dataBlock->m_txControlBlock.m_dataAddress = m_remoteAddress;
|
||||||
m_dataBlock->m_txControlBlock.m_dataPort = m_remotePort;
|
m_dataBlock->m_txControlBlock.m_dataPort = m_remotePort;
|
||||||
|
|
||||||
|
@ -67,7 +67,6 @@ public:
|
|||||||
void setSampleRate(uint32_t sampleRate);
|
void setSampleRate(uint32_t sampleRate);
|
||||||
|
|
||||||
void setNbBlocksFEC(uint32_t nbBlocksFEC);
|
void setNbBlocksFEC(uint32_t nbBlocksFEC);
|
||||||
void setTxDelay(float txDelayRatio);
|
|
||||||
void setRemoteAddress(const QString& address, uint16_t port);
|
void setRemoteAddress(const QString& address, uint16_t port);
|
||||||
|
|
||||||
/** Return true if the stream is OK, return false if there is an error. */
|
/** Return true if the stream is OK, return false if there is an error. */
|
||||||
@ -87,7 +86,6 @@ private:
|
|||||||
RemoteMetaDataFEC 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
|
|
||||||
RemoteDataBlock *m_dataBlock;
|
RemoteDataBlock *m_dataBlock;
|
||||||
RemoteSuperBlock 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
|
||||||
|
@ -68,8 +68,7 @@ LocalInputGui::LocalInputGui(DeviceUISet *deviceUISet, QWidget* parent) :
|
|||||||
m_countUnrecoverable(0),
|
m_countUnrecoverable(0),
|
||||||
m_countRecovered(0),
|
m_countRecovered(0),
|
||||||
m_doApplySettings(true),
|
m_doApplySettings(true),
|
||||||
m_forceSettings(true),
|
m_forceSettings(true)
|
||||||
m_txDelay(0.0)
|
|
||||||
{
|
{
|
||||||
m_paletteGreenText.setColor(QPalette::WindowText, Qt::green);
|
m_paletteGreenText.setColor(QPalette::WindowText, Qt::green);
|
||||||
m_paletteWhiteText.setColor(QPalette::WindowText, Qt::white);
|
m_paletteWhiteText.setColor(QPalette::WindowText, Qt::white);
|
||||||
|
@ -92,7 +92,6 @@ private:
|
|||||||
|
|
||||||
bool m_doApplySettings;
|
bool m_doApplySettings;
|
||||||
bool m_forceSettings;
|
bool m_forceSettings;
|
||||||
double m_txDelay;
|
|
||||||
|
|
||||||
QPalette m_paletteGreenText;
|
QPalette m_paletteGreenText;
|
||||||
QPalette m_paletteWhiteText;
|
QPalette m_paletteWhiteText;
|
||||||
|
@ -68,8 +68,7 @@ RemoteInputGui::RemoteInputGui(DeviceUISet *deviceUISet, QWidget* parent) :
|
|||||||
m_countUnrecoverable(0),
|
m_countUnrecoverable(0),
|
||||||
m_countRecovered(0),
|
m_countRecovered(0),
|
||||||
m_doApplySettings(true),
|
m_doApplySettings(true),
|
||||||
m_forceSettings(true),
|
m_forceSettings(true)
|
||||||
m_txDelay(0.0)
|
|
||||||
{
|
{
|
||||||
m_paletteGreenText.setColor(QPalette::WindowText, Qt::green);
|
m_paletteGreenText.setColor(QPalette::WindowText, Qt::green);
|
||||||
m_paletteWhiteText.setColor(QPalette::WindowText, Qt::white);
|
m_paletteWhiteText.setColor(QPalette::WindowText, Qt::white);
|
||||||
|
@ -94,7 +94,6 @@ private:
|
|||||||
|
|
||||||
bool m_doApplySettings;
|
bool m_doApplySettings;
|
||||||
bool m_forceSettings;
|
bool m_forceSettings;
|
||||||
double m_txDelay;
|
|
||||||
|
|
||||||
QPalette m_paletteGreenText;
|
QPalette m_paletteGreenText;
|
||||||
QPalette m_paletteWhiteText;
|
QPalette m_paletteWhiteText;
|
||||||
|
@ -177,7 +177,6 @@ Example of a JSON file (delay is an example you normally do not need it):
|
|||||||
"reverseAPIPort": 8888,
|
"reverseAPIPort": 8888,
|
||||||
"rgbColor": -7601148,
|
"rgbColor": -7601148,
|
||||||
"title": "Channel 0",
|
"title": "Channel 0",
|
||||||
"txDelay": 0,
|
|
||||||
"useReverseAPI": 0
|
"useReverseAPI": 0
|
||||||
},
|
},
|
||||||
"channelType": "RemoteSink",
|
"channelType": "RemoteSink",
|
||||||
|
@ -126,16 +126,15 @@ struct RemoteTxControlBlock
|
|||||||
bool m_processed;
|
bool m_processed;
|
||||||
uint16_t m_frameIndex;
|
uint16_t m_frameIndex;
|
||||||
int m_nbBlocksFEC;
|
int m_nbBlocksFEC;
|
||||||
int m_txDelay;
|
|
||||||
QString m_dataAddress;
|
QString m_dataAddress;
|
||||||
uint16_t m_dataPort;
|
uint16_t m_dataPort;
|
||||||
|
|
||||||
RemoteTxControlBlock() {
|
RemoteTxControlBlock()
|
||||||
|
{
|
||||||
m_complete = false;
|
m_complete = false;
|
||||||
m_processed = false;
|
m_processed = false;
|
||||||
m_frameIndex = 0;
|
m_frameIndex = 0;
|
||||||
m_nbBlocksFEC = 0;
|
m_nbBlocksFEC = 0;
|
||||||
m_txDelay = 100;
|
|
||||||
m_dataAddress = "127.0.0.1";
|
m_dataAddress = "127.0.0.1";
|
||||||
m_dataPort = 9090;
|
m_dataPort = 9090;
|
||||||
}
|
}
|
||||||
|
@ -9841,11 +9841,6 @@ margin-bottom: 20px;
|
|||||||
"sampleRate" : {
|
"sampleRate" : {
|
||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
},
|
},
|
||||||
"txDelay" : {
|
|
||||||
"type" : "number",
|
|
||||||
"format" : "float",
|
|
||||||
"description" : "minimum delay in ms between two consecutive packets sending"
|
|
||||||
},
|
|
||||||
"nbFECBlocks" : {
|
"nbFECBlocks" : {
|
||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
},
|
},
|
||||||
@ -51601,7 +51596,7 @@ except ApiException as e:
|
|||||||
</div>
|
</div>
|
||||||
<div id="generator">
|
<div id="generator">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
Generated 2021-12-04T20:19:18.225+01:00
|
Generated 2021-12-07T06:38:29.681+01:00
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -6,10 +6,6 @@ RemoteOutputSettings:
|
|||||||
format: int64
|
format: int64
|
||||||
sampleRate:
|
sampleRate:
|
||||||
type: integer
|
type: integer
|
||||||
txDelay:
|
|
||||||
description: minimum delay in ms between two consecutive packets sending
|
|
||||||
type: number
|
|
||||||
format: float
|
|
||||||
nbFECBlocks:
|
nbFECBlocks:
|
||||||
type: integer
|
type: integer
|
||||||
apiAddress:
|
apiAddress:
|
||||||
|
@ -6,10 +6,6 @@ RemoteOutputSettings:
|
|||||||
format: int64
|
format: int64
|
||||||
sampleRate:
|
sampleRate:
|
||||||
type: integer
|
type: integer
|
||||||
txDelay:
|
|
||||||
description: minimum delay in ms between two consecutive packets sending
|
|
||||||
type: number
|
|
||||||
format: float
|
|
||||||
nbFECBlocks:
|
nbFECBlocks:
|
||||||
type: integer
|
type: integer
|
||||||
apiAddress:
|
apiAddress:
|
||||||
|
@ -9841,11 +9841,6 @@ margin-bottom: 20px;
|
|||||||
"sampleRate" : {
|
"sampleRate" : {
|
||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
},
|
},
|
||||||
"txDelay" : {
|
|
||||||
"type" : "number",
|
|
||||||
"format" : "float",
|
|
||||||
"description" : "minimum delay in ms between two consecutive packets sending"
|
|
||||||
},
|
|
||||||
"nbFECBlocks" : {
|
"nbFECBlocks" : {
|
||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
},
|
},
|
||||||
@ -51601,7 +51596,7 @@ except ApiException as e:
|
|||||||
</div>
|
</div>
|
||||||
<div id="generator">
|
<div id="generator">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
Generated 2021-12-04T20:19:18.225+01:00
|
Generated 2021-12-07T06:38:29.681+01:00
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -32,8 +32,6 @@ SWGRemoteOutputSettings::SWGRemoteOutputSettings() {
|
|||||||
m_center_frequency_isSet = false;
|
m_center_frequency_isSet = false;
|
||||||
sample_rate = 0;
|
sample_rate = 0;
|
||||||
m_sample_rate_isSet = false;
|
m_sample_rate_isSet = false;
|
||||||
tx_delay = 0.0f;
|
|
||||||
m_tx_delay_isSet = false;
|
|
||||||
nb_fec_blocks = 0;
|
nb_fec_blocks = 0;
|
||||||
m_nb_fec_blocks_isSet = false;
|
m_nb_fec_blocks_isSet = false;
|
||||||
api_address = nullptr;
|
api_address = nullptr;
|
||||||
@ -68,8 +66,6 @@ SWGRemoteOutputSettings::init() {
|
|||||||
m_center_frequency_isSet = false;
|
m_center_frequency_isSet = false;
|
||||||
sample_rate = 0;
|
sample_rate = 0;
|
||||||
m_sample_rate_isSet = false;
|
m_sample_rate_isSet = false;
|
||||||
tx_delay = 0.0f;
|
|
||||||
m_tx_delay_isSet = false;
|
|
||||||
nb_fec_blocks = 0;
|
nb_fec_blocks = 0;
|
||||||
m_nb_fec_blocks_isSet = false;
|
m_nb_fec_blocks_isSet = false;
|
||||||
api_address = new QString("");
|
api_address = new QString("");
|
||||||
@ -99,7 +95,6 @@ SWGRemoteOutputSettings::cleanup() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(api_address != nullptr) {
|
if(api_address != nullptr) {
|
||||||
delete api_address;
|
delete api_address;
|
||||||
}
|
}
|
||||||
@ -133,8 +128,6 @@ SWGRemoteOutputSettings::fromJsonObject(QJsonObject &pJson) {
|
|||||||
|
|
||||||
::SWGSDRangel::setValue(&sample_rate, pJson["sampleRate"], "qint32", "");
|
::SWGSDRangel::setValue(&sample_rate, pJson["sampleRate"], "qint32", "");
|
||||||
|
|
||||||
::SWGSDRangel::setValue(&tx_delay, pJson["txDelay"], "float", "");
|
|
||||||
|
|
||||||
::SWGSDRangel::setValue(&nb_fec_blocks, pJson["nbFECBlocks"], "qint32", "");
|
::SWGSDRangel::setValue(&nb_fec_blocks, pJson["nbFECBlocks"], "qint32", "");
|
||||||
|
|
||||||
::SWGSDRangel::setValue(&api_address, pJson["apiAddress"], "QString", "QString");
|
::SWGSDRangel::setValue(&api_address, pJson["apiAddress"], "QString", "QString");
|
||||||
@ -179,9 +172,6 @@ SWGRemoteOutputSettings::asJsonObject() {
|
|||||||
if(m_sample_rate_isSet){
|
if(m_sample_rate_isSet){
|
||||||
obj->insert("sampleRate", QJsonValue(sample_rate));
|
obj->insert("sampleRate", QJsonValue(sample_rate));
|
||||||
}
|
}
|
||||||
if(m_tx_delay_isSet){
|
|
||||||
obj->insert("txDelay", QJsonValue(tx_delay));
|
|
||||||
}
|
|
||||||
if(m_nb_fec_blocks_isSet){
|
if(m_nb_fec_blocks_isSet){
|
||||||
obj->insert("nbFECBlocks", QJsonValue(nb_fec_blocks));
|
obj->insert("nbFECBlocks", QJsonValue(nb_fec_blocks));
|
||||||
}
|
}
|
||||||
@ -239,16 +229,6 @@ SWGRemoteOutputSettings::setSampleRate(qint32 sample_rate) {
|
|||||||
this->m_sample_rate_isSet = true;
|
this->m_sample_rate_isSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
|
||||||
SWGRemoteOutputSettings::getTxDelay() {
|
|
||||||
return tx_delay;
|
|
||||||
}
|
|
||||||
void
|
|
||||||
SWGRemoteOutputSettings::setTxDelay(float tx_delay) {
|
|
||||||
this->tx_delay = tx_delay;
|
|
||||||
this->m_tx_delay_isSet = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
qint32
|
qint32
|
||||||
SWGRemoteOutputSettings::getNbFecBlocks() {
|
SWGRemoteOutputSettings::getNbFecBlocks() {
|
||||||
return nb_fec_blocks;
|
return nb_fec_blocks;
|
||||||
@ -370,9 +350,6 @@ SWGRemoteOutputSettings::isSet(){
|
|||||||
if(m_sample_rate_isSet){
|
if(m_sample_rate_isSet){
|
||||||
isObjectUpdated = true; break;
|
isObjectUpdated = true; break;
|
||||||
}
|
}
|
||||||
if(m_tx_delay_isSet){
|
|
||||||
isObjectUpdated = true; break;
|
|
||||||
}
|
|
||||||
if(m_nb_fec_blocks_isSet){
|
if(m_nb_fec_blocks_isSet){
|
||||||
isObjectUpdated = true; break;
|
isObjectUpdated = true; break;
|
||||||
}
|
}
|
||||||
|
@ -48,9 +48,6 @@ public:
|
|||||||
qint32 getSampleRate();
|
qint32 getSampleRate();
|
||||||
void setSampleRate(qint32 sample_rate);
|
void setSampleRate(qint32 sample_rate);
|
||||||
|
|
||||||
float getTxDelay();
|
|
||||||
void setTxDelay(float tx_delay);
|
|
||||||
|
|
||||||
qint32 getNbFecBlocks();
|
qint32 getNbFecBlocks();
|
||||||
void setNbFecBlocks(qint32 nb_fec_blocks);
|
void setNbFecBlocks(qint32 nb_fec_blocks);
|
||||||
|
|
||||||
@ -94,9 +91,6 @@ private:
|
|||||||
qint32 sample_rate;
|
qint32 sample_rate;
|
||||||
bool m_sample_rate_isSet;
|
bool m_sample_rate_isSet;
|
||||||
|
|
||||||
float tx_delay;
|
|
||||||
bool m_tx_delay_isSet;
|
|
||||||
|
|
||||||
qint32 nb_fec_blocks;
|
qint32 nb_fec_blocks;
|
||||||
bool m_nb_fec_blocks_isSet;
|
bool m_nb_fec_blocks_isSet;
|
||||||
|
|
||||||
|
@ -53,7 +53,6 @@ def getInputOptions():
|
|||||||
parser.add_option("--rmt-address", dest="remote_address", help="RemoteSink: destination data address", metavar="IP_ADDRESS", type="string")
|
parser.add_option("--rmt-address", dest="remote_address", help="RemoteSink: destination data address", metavar="IP_ADDRESS", type="string")
|
||||||
parser.add_option("--rmt-port", dest="remote_port", help="RemoteSink: destination data port", metavar="PORT", type="int")
|
parser.add_option("--rmt-port", dest="remote_port", help="RemoteSink: destination data port", metavar="PORT", type="int")
|
||||||
parser.add_option("--rmt-fec", dest="remote_fec", help="RemoteSink: number of FEC blocks per frame", metavar="NUMBER", type="int")
|
parser.add_option("--rmt-fec", dest="remote_fec", help="RemoteSink: number of FEC blocks per frame", metavar="NUMBER", type="int")
|
||||||
parser.add_option("--rmt-txdelay", dest="remote_tx_delay", help="RemoteSink: inter block UDP Tx delay percentage", metavar="PERCENT", type="int")
|
|
||||||
|
|
||||||
(options, args) = parser.parse_args()
|
(options, args) = parser.parse_args()
|
||||||
|
|
||||||
@ -326,8 +325,6 @@ def setupChannel(deviceset_url, options):
|
|||||||
settings["RemoteSinkSettings"]["dataPort"] = options.remote_port
|
settings["RemoteSinkSettings"]["dataPort"] = options.remote_port
|
||||||
if options.remote_fec:
|
if options.remote_fec:
|
||||||
settings["RemoteSinkSettings"]["nbFECBlocks"] = options.remote_fec
|
settings["RemoteSinkSettings"]["nbFECBlocks"] = options.remote_fec
|
||||||
if options.remote_tx_delay:
|
|
||||||
settings["RemoteSinkSettings"]["txDelay"] = options.remote_tx_delay
|
|
||||||
|
|
||||||
r = callAPI(deviceset_url + "/channel/%d/settings" % i, "PATCH", None, settings, "Change demod")
|
r = callAPI(deviceset_url + "/channel/%d/settings" % i, "PATCH", None, settings, "Change demod")
|
||||||
if r is None:
|
if r is None:
|
||||||
|
@ -63,7 +63,6 @@
|
|||||||
"reverseAPIPort": 8888,
|
"reverseAPIPort": 8888,
|
||||||
"rgbColor": -7601148,
|
"rgbColor": -7601148,
|
||||||
"title": "Channel 0",
|
"title": "Channel 0",
|
||||||
"txDelay": 0,
|
|
||||||
"useReverseAPI": 0
|
"useReverseAPI": 0
|
||||||
},
|
},
|
||||||
"channelType": "RemoteSink",
|
"channelType": "RemoteSink",
|
||||||
@ -98,7 +97,6 @@
|
|||||||
"reverseAPIPort": 8888,
|
"reverseAPIPort": 8888,
|
||||||
"rgbColor": -7601148,
|
"rgbColor": -7601148,
|
||||||
"title": "Remote sink",
|
"title": "Remote sink",
|
||||||
"txDelay": 0,
|
|
||||||
"useReverseAPI": 0
|
"useReverseAPI": 0
|
||||||
},
|
},
|
||||||
"channelType": "RemoteSink",
|
"channelType": "RemoteSink",
|
||||||
@ -133,7 +131,6 @@
|
|||||||
"reverseAPIPort": 8888,
|
"reverseAPIPort": 8888,
|
||||||
"rgbColor": -7601148,
|
"rgbColor": -7601148,
|
||||||
"title": "Remote sink",
|
"title": "Remote sink",
|
||||||
"txDelay": 0,
|
|
||||||
"useReverseAPI": 0
|
"useReverseAPI": 0
|
||||||
},
|
},
|
||||||
"channelType": "RemoteSink",
|
"channelType": "RemoteSink",
|
||||||
@ -148,4 +145,4 @@
|
|||||||
null,
|
null,
|
||||||
"Start device on deviceset R0"
|
"Start device on deviceset R0"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user