From 404c73fb802b8ccc565a11c609d0175c3b95de7e Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 10 Sep 2018 02:52:36 +0200 Subject: [PATCH] SDRDaemon: make Rx side truly 24/16 bit compatible in all configurations --- plugins/channelrx/daemonsink/daemonsink.cpp | 4 ++-- plugins/channelrx/daemonsink/daemonsinkgui.cpp | 2 +- plugins/samplesink/sdrdaemonsink/readme.md | 6 +++--- plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.cpp | 2 +- plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.cpp | 6 +++--- plugins/samplesink/sdrdaemonsink/udpsinkfec.cpp | 5 ++--- plugins/samplesink/sdrdaemonsink/udpsinkfec.h | 3 ++- plugins/samplesource/sdrdaemonsource/readme.md | 5 +++-- .../samplesource/sdrdaemonsource/sdrdaemonsourcebuffer.h | 1 + plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.cpp | 2 +- .../sdrdaemonsource/sdrdaemonsourceudphandler.cpp | 6 +++--- sdrdaemon/channel/sdrdaemondatablock.h | 4 +++- 12 files changed, 25 insertions(+), 21 deletions(-) diff --git a/plugins/channelrx/daemonsink/daemonsink.cpp b/plugins/channelrx/daemonsink/daemonsink.cpp index 4ca7ae2e8..a30dacc12 100644 --- a/plugins/channelrx/daemonsink/daemonsink.cpp +++ b/plugins/channelrx/daemonsink/daemonsink.cpp @@ -52,7 +52,7 @@ DaemonSink::DaemonSink(DeviceSourceAPI *deviceAPI) : m_dataBlock(0), m_centerFrequency(0), m_sampleRate(48000), - m_sampleBytes(SDR_RX_SAMP_SZ == 24 ? 4 : 2), + m_sampleBytes(SDR_RX_SAMP_SZ <= 16 ? 2 : 4), m_nbBlocksFEC(0), m_txDelay(35), m_dataAddress("127.0.0.1"), @@ -82,7 +82,7 @@ DaemonSink::~DaemonSink() void DaemonSink::setTxDelay(int txDelay, int nbBlocksFEC) { double txDelayRatio = txDelay / 100.0; - double delay = m_sampleRate == 0 ? 1.0 : (127*127*txDelayRatio) / m_sampleRate; + double delay = m_sampleRate == 0 ? 1.0 : (127*SDRDaemonSamplesPerBlock*txDelayRatio) / m_sampleRate; delay /= 128 + nbBlocksFEC; m_txDelay = roundf(delay*1e6); // microseconds qDebug() << "DaemonSink::setTxDelay:" diff --git a/plugins/channelrx/daemonsink/daemonsinkgui.cpp b/plugins/channelrx/daemonsink/daemonsinkgui.cpp index 9819b2efc..1900958b0 100644 --- a/plugins/channelrx/daemonsink/daemonsinkgui.cpp +++ b/plugins/channelrx/daemonsink/daemonsinkgui.cpp @@ -287,7 +287,7 @@ void DaemonSinkGUI::on_nbFECBlocks_valueChanged(int value) void DaemonSinkGUI::updateTxDelayTime() { double txDelayRatio = m_settings.m_txDelay / 100.0; - double delay = m_sampleRate == 0 ? 0.0 : (127*127*txDelayRatio) / m_sampleRate; + double delay = m_sampleRate == 0 ? 0.0 : (127*SDRDaemonSamplesPerBlock*txDelayRatio) / m_sampleRate; delay /= 128 + m_settings.m_nbFECBlocks; ui->txDelayTime->setText(tr("%1µs").arg(QString::number(delay*1e6, 'f', 0))); } diff --git a/plugins/samplesink/sdrdaemonsink/readme.md b/plugins/samplesink/sdrdaemonsink/readme.md index 710958b24..d04f4cca9 100644 --- a/plugins/samplesink/sdrdaemonsink/readme.md +++ b/plugins/samplesink/sdrdaemonsink/readme.md @@ -50,9 +50,9 @@ The value is a percentage of the nominal time it takes to process a block of sam - Sample rate on the network: _SR_ - Delay percentage: _d_ - Number of FEC blocks: _F_ - - There are 127 blocks of I/Q data per frame (1 meta block for 128 blocks) and each I/Q data block of 512 bytes (128 samples) has a 4 bytes header (1 sample) thus there are 127 samples remaining effectively. This gives the constant 127*127 = 16219 samples per frame in the formula + - There are 127 blocks of I/Q data per frame (1 meta block for 128 blocks) and each I/Q data block of 512 bytes (128 samples) has a 8 bytes header (2 samples) thus there are 126 samples remaining effectively. This gives the constant 127*126 = 16002 samples per frame in the formula -Formula: ((127 ✕ 127 ✕ _d_) / _SR_) / (128 + _F_) +Formula: ((127 ✕ 126 ✕ _d_) / _SR_) / (128 + _F_)

6: Forward Error Correction setting and status

@@ -64,7 +64,7 @@ This sets the number of FEC blocks per frame. A frame consists of 128 data block

6.2: Distant transmitter queue length

-This is the samples queue length reported from the distant transmitter. This is a number of vectors of 127 ✕ 127 ✕ _I_ samples where _I_ is the interpolation factor. This corresponds to a block of 127 ✕ 127 samples sent over the network. This numbers serves to throttle the sample generator so that the queue length is close to 8 vectors. +This is the samples queue length reported from the distant transmitter. This is a number of vectors of 127 ✕ 127 ✕ _I_ samples where _I_ is the interpolation factor. This corresponds to a block of 127 ✕ 126 samples sent over the network. This numbers serves to throttle the sample generator so that the queue length is close to 8 vectors.

6.3: Stream status

diff --git a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.cpp b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.cpp index 80cb47f24..08ac4ca32 100644 --- a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.cpp +++ b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkgui.cpp @@ -214,7 +214,7 @@ void SDRdaemonSinkGui::updateSampleRate() void SDRdaemonSinkGui::updateTxDelayTooltip() { - double delay = ((127*127*m_settings.m_txDelay) / m_settings.m_sampleRate)/(128 + m_settings.m_nbFECBlocks); + double delay = ((127*126*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))); } diff --git a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.cpp b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.cpp index cf76ab08a..bc112b475 100644 --- a/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.cpp +++ b/plugins/samplesink/sdrdaemonsink/sdrdaemonsinkoutput.cpp @@ -96,7 +96,7 @@ bool SDRdaemonSinkOutput::start() m_lastTimestampRateCorrection = 0; m_lastQueueLength = -2; // set first value out of bounds - double delay = ((127*127*m_settings.m_txDelay) / m_settings.m_sampleRate)/(128 + m_settings.m_nbFECBlocks); + double delay = ((127*126*m_settings.m_txDelay) / m_settings.m_sampleRate)/(128 + m_settings.m_nbFECBlocks); m_sdrDaemonSinkThread->setTxDelay((int) (delay*1e6)); mutexLocker.unlock(); @@ -278,13 +278,13 @@ void SDRdaemonSinkOutput::applySettings(const SDRdaemonSinkSettings& settings, b if (changeTxDelay) { - double delay = ((127*127*settings.m_txDelay) / settings.m_sampleRate)/(128 + settings.m_nbFECBlocks); + double delay = ((127*126*settings.m_txDelay) / settings.m_sampleRate)/(128 + settings.m_nbFECBlocks); qDebug("SDRdaemonSinkOutput::applySettings: Tx delay: %f us", delay*1e6); if (m_sdrDaemonSinkThread != 0) { // delay is calculated as a fraction of the nominal UDP block process time - // frame size: 127 * 127 samples + // frame size: 127 * 126 samples // 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_sdrDaemonSinkThread->setTxDelay((int) (delay*1e6)); diff --git a/plugins/samplesink/sdrdaemonsink/udpsinkfec.cpp b/plugins/samplesink/sdrdaemonsink/udpsinkfec.cpp index fdd7bad6a..9f9c973c6 100644 --- a/plugins/samplesink/sdrdaemonsink/udpsinkfec.cpp +++ b/plugins/samplesink/sdrdaemonsink/udpsinkfec.cpp @@ -29,7 +29,7 @@ MESSAGE_CLASS_DEFINITION(UDPSinkFECWorker::MsgConfigureRemoteAddress, Message) UDPSinkFEC::UDPSinkFEC() : m_sampleRate(48000), - m_sampleBytes(SDR_TX_SAMP_SZ == 24 ? 4 : 2), + m_sampleBytes(SDR_TX_SAMP_SZ <= 16 ? 2 : 4), m_sampleBits(SDR_TX_SAMP_SZ), m_nbSamples(0), m_nbBlocksFEC(0), @@ -101,7 +101,6 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk gettimeofday(&tv, 0); - // create meta data TODO: semaphore metaData.m_centerFrequency = 0; // frequency not set by stream metaData.m_sampleRate = m_sampleRate; metaData.m_sampleBytes = m_sampleBytes & 0xF; @@ -142,6 +141,7 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk m_txBlockIndex = 1; // next Tx block with data } + // TODO: memcpy is valid for 4 bytes samples only (16 bits) else conversion must take place to take only LSB assuming Tx is 16 bit only if (m_sampleIndex + inRemainingSamples < samplesPerBlock) // there is still room in the current super block { memcpy((char *) &m_superBlock.protectedBlock.m_samples[m_sampleIndex], @@ -167,7 +167,6 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk int nbBlocksFEC = m_nbBlocksFEC; int txDelay = m_txDelay; - // TODO: send blocks //qDebug("UDPSinkFEC::write: push frame to worker: %u", m_frameCount); m_udpWorker->pushTxFrame(m_txBlocks[m_txBlocksIndex], nbBlocksFEC, txDelay, m_frameCount); //m_txThread = new std::thread(transmitUDP, this, m_txBlocks[m_txBlocksIndex], m_frameCount, nbBlocksFEC, txDelay, m_cm256Valid); diff --git a/plugins/samplesink/sdrdaemonsink/udpsinkfec.h b/plugins/samplesink/sdrdaemonsink/udpsinkfec.h index 337a19ea5..6fea548e8 100644 --- a/plugins/samplesink/sdrdaemonsink/udpsinkfec.h +++ b/plugins/samplesink/sdrdaemonsink/udpsinkfec.h @@ -72,9 +72,10 @@ public: uint16_t frameIndex; uint8_t blockIndex; uint8_t filler; + uint32_t filler2; }; - static const int samplesPerBlock = (m_udpSize - sizeof(Header)) / sizeof(Sample); + static const int samplesPerBlock = (m_udpSize - sizeof(Header)) / (2 * SDR_TX_SAMP_SZ); struct ProtectedBlock { diff --git a/plugins/samplesource/sdrdaemonsource/readme.md b/plugins/samplesource/sdrdaemonsource/readme.md index b1732a09e..91a27b9c7 100644 --- a/plugins/samplesource/sdrdaemonsource/readme.md +++ b/plugins/samplesource/sdrdaemonsource/readme.md @@ -159,9 +159,10 @@ The value is a percentage of the nominal time it takes to process a block of sam - Sample rate on the network: _SR_ - Delay percentage: _d_ - Number of FEC blocks: _F_ - - There are 127 blocks of I/Q data per frame (1 meta block for 128 blocks) and each I/Q data block of 512 bytes (128 samples) has a 4 bytes header (1 sample) thus there are 127 samples remaining effectively. This gives the constant 127*127 = 16219 samples per frame in the formula + - There are 127 blocks of I/Q data per frame (1 meta block for 128 blocks) and each I/Q data block of 512 bytes (128 samples) has a 8 bytes header (1 sample for 24 bit and 2 samples for 16 bit) thus there are 126 (16 bit) or 63 (24 bit) samples remaining effectively. -Formula: ((127 ✕ 127 ✕ _d_) / _SR_) / (128 + _F_) +Formula (16 bit): ((127 ✕ 126 ✕ _d_) / _SR_) / (128 + _F_) +Formula (24 bit): ((127 ✕ 63 ✕ _d_) / _SR_) / (128 + _F_) thus half the above

8: Desired distant device sample rate

diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcebuffer.h b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcebuffer.h index 20873deb3..5ac67e9fa 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcebuffer.h +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcebuffer.h @@ -62,6 +62,7 @@ public: uint16_t frameIndex; uint8_t blockIndex; uint8_t filler; + uint32_t filler2; }; static const int framesSize = SDRDAEMONSOURCE_NBDECODERSLOTS * (SDRDAEMONSOURCE_NBORIGINALBLOCKS - 1) * (SDRDAEMONSOURCE_UDPSIZE - sizeof(Header)); diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.cpp b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.cpp index 802d16368..008b70319 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.cpp +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourcegui.cpp @@ -56,7 +56,7 @@ SDRdaemonSourceGui::SDRdaemonSourceGui(DeviceUISet *deviceUISet, QWidget* parent m_bufferGauge(-50), m_nbOriginalBlocks(128), m_nbFECBlocks(0), - m_sampleBits(16), + m_sampleBits(16), // assume 16 bits to start with m_sampleBytes(2), m_samplesCount(0), m_tickCount(0), diff --git a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp index c92c7dd82..1eeebce59 100644 --- a/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp +++ b/plugins/samplesource/sdrdaemonsource/sdrdaemonsourceudphandler.cpp @@ -264,7 +264,7 @@ void SDRdaemonSourceUDPHandler::tick() } const SDRdaemonSourceBuffer::MetaDataFEC& metaData = m_sdrDaemonBuffer.getCurrentMeta(); - m_readLength = m_readLengthSamples * metaData.m_sampleBytes * 2; + m_readLength = m_readLengthSamples * (metaData.m_sampleBytes & 0xF) * 2; if (SDR_RX_SAMP_SZ == metaData.m_sampleBits) // same sample size { @@ -304,9 +304,9 @@ void SDRdaemonSourceUDPHandler::tick() for (unsigned int is = 0; is < m_readLengthSamples; is++) { - m_converterBuffer[is] = ((int32_t *)buf)[2*is]>>8; // I -> MSB + m_converterBuffer[is] = ((int32_t *)buf)[2*is+1]>>8; // Q -> MSB m_converterBuffer[is] <<=16; - m_converterBuffer[is] += ((int32_t *)buf)[2*is+1]>>8; // Q -> LSB + m_converterBuffer[is] += ((int32_t *)buf)[2*is]>>8; // I -> LSB } m_sampleFifo->write(reinterpret_cast(m_converterBuffer), m_readLengthSamples*sizeof(Sample)); diff --git a/sdrdaemon/channel/sdrdaemondatablock.h b/sdrdaemon/channel/sdrdaemondatablock.h index bf1ab552f..6138fa729 100644 --- a/sdrdaemon/channel/sdrdaemondatablock.h +++ b/sdrdaemon/channel/sdrdaemondatablock.h @@ -70,18 +70,20 @@ struct SDRDaemonHeader uint16_t m_frameIndex; uint8_t m_blockIndex; uint8_t m_filler; + uint32_t m_filler2; void init() { m_frameIndex = 0; m_blockIndex = 0; m_filler = 0; + m_filler2 = 0; } }; static const int SDRDaemonUdpSize = UDPSINKFEC_UDPSIZE; static const int SDRDaemonNbOrginalBlocks = UDPSINKFEC_NBORIGINALBLOCKS; -static const int SDRDaemonSamplesPerBlock = (UDPSINKFEC_UDPSIZE - sizeof(SDRDaemonHeader)) / (SDR_RX_SAMP_SZ/4); +static const int SDRDaemonSamplesPerBlock = (UDPSINKFEC_UDPSIZE - sizeof(SDRDaemonHeader)) / sizeof(Sample); struct SDRDaemonProtectedBlock {