From 9046b379ac8d3ad45e26115b6a3a0f2dc8331349 Mon Sep 17 00:00:00 2001 From: f4exb Date: Tue, 21 Aug 2018 14:00:56 +0200 Subject: [PATCH] SDRdaemon: UDP channel sink base final --- sdrdaemon/channel/sdrdaemonchannelsink.cpp | 85 ++++++++++++++++++++-- sdrdaemon/channel/sdrdaemonchannelsink.h | 23 +++++- sdrdaemon/channel/sdrdaemondatablock.h | 9 +++ 3 files changed, 109 insertions(+), 8 deletions(-) diff --git a/sdrdaemon/channel/sdrdaemonchannelsink.cpp b/sdrdaemon/channel/sdrdaemonchannelsink.cpp index b34f18c63..4f4e28432 100644 --- a/sdrdaemon/channel/sdrdaemonchannelsink.cpp +++ b/sdrdaemon/channel/sdrdaemonchannelsink.cpp @@ -42,7 +42,14 @@ SDRDaemonChannelSink::SDRDaemonChannelSink(DeviceSourceAPI *deviceAPI) : m_sinkThread(0), m_txBlockIndex(0), m_frameCount(0), - m_sampleIndex(0) + m_sampleIndex(0), + m_dataBlock(0), + m_centerFrequency(0), + m_sampleRate(48000), + m_sampleBytes(SDR_RX_SAMP_SZ/8), + m_sampleBits(8), + m_nbBlocksFEC(0), + m_txDelay(100) { setObjectName(m_channelId); @@ -56,12 +63,29 @@ SDRDaemonChannelSink::SDRDaemonChannelSink(DeviceSourceAPI *deviceAPI) : SDRDaemonChannelSink::~SDRDaemonChannelSink() { + m_dataBlockMutex.lock(); + if (m_dataBlock && !m_dataBlock->m_controlBlock.m_complete) { + delete m_dataBlock; + } + m_dataBlockMutex.unlock(); m_deviceAPI->removeChannelAPI(this); m_deviceAPI->removeThreadedSink(m_threadedChannelizer); delete m_threadedChannelizer; delete m_channelizer; } +void SDRDaemonChannelSink::setTxDelay(int txDelay) +{ + qDebug() << "SDRDaemonChannelSink::setTxDelay: txDelay: " << txDelay; + m_txDelay = txDelay; +} + +void SDRDaemonChannelSink::setNbBlocksFEC(int nbBlocksFEC) +{ + qDebug() << "SDRDaemonChannelSink::setNbBlocksFEC: nbBlocksFEC: " << nbBlocksFEC; + m_nbBlocksFEC = nbBlocksFEC; +} + void SDRDaemonChannelSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst __attribute__((unused))) { SampleVector::const_iterator it = begin; @@ -77,19 +101,19 @@ void SDRDaemonChannelSink::feed(const SampleVector::const_iterator& begin, const SDRDaemonMetaDataFEC metaData; gettimeofday(&tv, 0); - metaData.m_centerFrequency = 0; // TODO - metaData.m_sampleRate = 48000; // TODO - metaData.m_sampleBytes = SDR_RX_SAMP_SZ/8; - metaData.m_sampleBits = SDR_RX_SAMP_SZ; + metaData.m_centerFrequency = m_centerFrequency; + metaData.m_sampleRate = m_sampleRate; + metaData.m_sampleBytes = m_sampleBytes; + metaData.m_sampleBits = m_sampleBits; metaData.m_nbOriginalBlocks = SDRDaemonNbOrginalBlocks; - metaData.m_nbFECBlocks = 8; // TODO + metaData.m_nbFECBlocks = m_nbBlocksFEC; metaData.m_tv_sec = tv.tv_sec; metaData.m_tv_usec = tv.tv_usec; boost::crc_32_type crc32; crc32.process_bytes(&metaData, 20); metaData.m_crc32 = crc32.checksum(); - SDRDaemonSuperBlock& superBlock = m_dataBlock.m_superBlocks[0]; // first block + SDRDaemonSuperBlock& superBlock = m_dataBlock->m_superBlocks[0]; // first block memset((void *) &superBlock, 0, SDRDaemonUdpSize); @@ -112,8 +136,55 @@ void SDRDaemonChannelSink::feed(const SampleVector::const_iterator& begin, const m_currentMetaFEC = metaData; } + if (!m_dataBlock) { + m_dataBlock = new SDRDaemonDataBlock(); + } + m_txBlockIndex = 1; // next Tx block with data + } // block zero + + // TODO: handle different sample sizes... + if (m_sampleIndex + inRemainingSamples < SDRDaemonSamplesPerBlock) // there is still room in the current super block + { + memcpy((void *) &m_superBlock.m_protectedBlock.m_samples[m_sampleIndex], + (const void *) &(*(begin+inSamplesIndex)), + inRemainingSamples * sizeof(Sample)); + m_sampleIndex += inRemainingSamples; + it = end; // all input samples are consumed } + else // complete super block and initiate the next if not end of frame + { + memcpy((void *) &m_superBlock.m_protectedBlock.m_samples[m_sampleIndex], + (const void *) &(*(begin+inSamplesIndex)), + (SDRDaemonSamplesPerBlock - m_sampleIndex) * sizeof(Sample)); + it += SDRDaemonSamplesPerBlock - m_sampleIndex; + m_sampleIndex = 0; + + m_superBlock.m_header.m_frameIndex = m_frameCount; + m_superBlock.m_header.m_blockIndex = m_txBlockIndex; + m_dataBlock->m_superBlocks[m_txBlockIndex] = m_superBlock; + + if (m_txBlockIndex == SDRDaemonNbOrginalBlocks - 1) // frame complete + { + m_dataBlockMutex.lock(); + m_dataBlock->m_controlBlock.m_frameIndex = m_frameCount; + m_dataBlock->m_controlBlock.m_processed = false; + m_dataBlock->m_controlBlock.m_complete = true; + m_dataBlock->m_controlBlock.m_nbBlocksFEC = m_nbBlocksFEC; + m_dataBlock->m_controlBlock.m_txDelay = m_txDelay; + + m_dataQueue.push(m_dataBlock); + m_dataBlock = new SDRDaemonDataBlock(); // create a new one immediately + m_dataBlockMutex.unlock(); + + m_txBlockIndex = 0; + m_frameCount++; + } + else + { + m_txBlockIndex++; + } + } } } diff --git a/sdrdaemon/channel/sdrdaemonchannelsink.h b/sdrdaemon/channel/sdrdaemonchannelsink.h index e9e49e4f5..1f659b60c 100644 --- a/sdrdaemon/channel/sdrdaemonchannelsink.h +++ b/sdrdaemon/channel/sdrdaemonchannelsink.h @@ -23,6 +23,8 @@ #ifndef SDRDAEMON_CHANNEL_SDRDAEMONCHANNELSINK_H_ #define SDRDAEMON_CHANNEL_SDRDAEMONCHANNELSINK_H_ +#include + #include "cm256.h" #include "dsp/basebandsamplesink.h" @@ -54,6 +56,17 @@ public: virtual QByteArray serialize() const; virtual bool deserialize(const QByteArray& data); + /** Set center frequency given in Hz */ + void setCenterFrequency(uint64_t centerFrequency) { m_centerFrequency = centerFrequency / 1000; } + + /** Set sample rate given in Hz */ + void setSampleRate(uint32_t sampleRate) { m_sampleRate = sampleRate; } + + void setSampleBytes(uint8_t sampleBytes) { m_sampleBytes = sampleBytes; } + void setSampleBits(uint8_t sampleBits) { m_sampleBits = sampleBits; } + void setNbBlocksFEC(int nbBlocksFEC); + void setTxDelay(int txDelay); + static const QString m_channelIdURI; static const QString m_channelId; @@ -73,7 +86,15 @@ private: int m_sampleIndex; //!< Current sample index in protected block data SDRDaemonSuperBlock m_superBlock; SDRDaemonMetaDataFEC m_currentMetaFEC; - SDRDaemonDataBlock m_dataBlock; + SDRDaemonDataBlock *m_dataBlock; + QMutex m_dataBlockMutex; + + uint64_t m_centerFrequency; + uint32_t m_sampleRate; + uint8_t m_sampleBytes; + uint8_t m_sampleBits; + int m_nbBlocksFEC; + int m_txDelay; }; #endif /* SDRDAEMON_CHANNEL_SDRDAEMONCHANNELSINK_H_ */ diff --git a/sdrdaemon/channel/sdrdaemondatablock.h b/sdrdaemon/channel/sdrdaemondatablock.h index 422148ccd..4733462e6 100644 --- a/sdrdaemon/channel/sdrdaemondatablock.h +++ b/sdrdaemon/channel/sdrdaemondatablock.h @@ -81,10 +81,19 @@ struct SDRDaemonSuperBlock struct SDRDaemonTxControlBlock { + bool m_complete; bool m_processed; uint16_t m_frameIndex; int m_nbBlocksFEC; int m_txDelay; + + SDRDaemonTxControlBlock() { + m_complete = false; + m_processed = false; + m_frameIndex = 0; + m_nbBlocksFEC = 0; + m_txDelay = 100; + } }; class SDRDaemonDataBlock