mirror of https://github.com/f4exb/sdrangel.git
SDRDaemon: cleanup on UDP Tx side to use sdrdaemondatablock.h definitions and Rx sample size
This commit is contained in:
parent
05072ce4b9
commit
5e588ae09e
|
@ -52,7 +52,6 @@ DaemonSink::DaemonSink(DeviceSourceAPI *deviceAPI) :
|
||||||
m_dataBlock(0),
|
m_dataBlock(0),
|
||||||
m_centerFrequency(0),
|
m_centerFrequency(0),
|
||||||
m_sampleRate(48000),
|
m_sampleRate(48000),
|
||||||
m_sampleBytes(SDR_RX_SAMP_SZ <= 16 ? 2 : 4),
|
|
||||||
m_nbBlocksFEC(0),
|
m_nbBlocksFEC(0),
|
||||||
m_txDelay(35),
|
m_txDelay(35),
|
||||||
m_dataAddress("127.0.0.1"),
|
m_dataAddress("127.0.0.1"),
|
||||||
|
@ -115,7 +114,7 @@ void DaemonSink::feed(const SampleVector::const_iterator& begin, const SampleVec
|
||||||
|
|
||||||
metaData.m_centerFrequency = m_centerFrequency;
|
metaData.m_centerFrequency = m_centerFrequency;
|
||||||
metaData.m_sampleRate = m_sampleRate;
|
metaData.m_sampleRate = m_sampleRate;
|
||||||
metaData.m_sampleBytes = m_sampleBytes & 0xF;
|
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 = SDRDaemonNbOrginalBlocks;
|
||||||
metaData.m_nbFECBlocks = m_nbBlocksFEC;
|
metaData.m_nbFECBlocks = m_nbBlocksFEC;
|
||||||
|
@ -133,6 +132,8 @@ void DaemonSink::feed(const SampleVector::const_iterator& begin, const SampleVec
|
||||||
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_sampleBits = SDR_RX_SAMP_SZ;
|
||||||
memcpy((void *) &superBlock.m_protectedBlock, (const void *) &metaData, sizeof(SDRDaemonMetaDataFEC));
|
memcpy((void *) &superBlock.m_protectedBlock, (const void *) &metaData, sizeof(SDRDaemonMetaDataFEC));
|
||||||
|
|
||||||
if (!(metaData == m_currentMetaFEC))
|
if (!(metaData == m_currentMetaFEC))
|
||||||
|
@ -154,7 +155,7 @@ void DaemonSink::feed(const SampleVector::const_iterator& begin, const SampleVec
|
||||||
} // block zero
|
} // block zero
|
||||||
|
|
||||||
// handle different sample sizes...
|
// handle different sample sizes...
|
||||||
int samplesPerBlock = SDRDaemonNbBytesPerBlock / sizeof(Sample);
|
int samplesPerBlock = SDRDaemonNbBytesPerBlock / (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)],
|
||||||
|
@ -173,6 +174,8 @@ void DaemonSink::feed(const SampleVector::const_iterator& begin, const SampleVec
|
||||||
|
|
||||||
m_superBlock.m_header.m_frameIndex = m_frameCount;
|
m_superBlock.m_header.m_frameIndex = m_frameCount;
|
||||||
m_superBlock.m_header.m_blockIndex = m_txBlockIndex;
|
m_superBlock.m_header.m_blockIndex = m_txBlockIndex;
|
||||||
|
m_superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||||
|
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 == SDRDaemonNbOrginalBlocks - 1) // frame complete
|
||||||
|
|
|
@ -144,7 +144,6 @@ private:
|
||||||
|
|
||||||
uint64_t m_centerFrequency;
|
uint64_t m_centerFrequency;
|
||||||
uint32_t m_sampleRate;
|
uint32_t m_sampleRate;
|
||||||
uint8_t m_sampleBytes;
|
|
||||||
int m_nbBlocksFEC;
|
int m_nbBlocksFEC;
|
||||||
int m_txDelay;
|
int m_txDelay;
|
||||||
QString m_dataAddress;
|
QString m_dataAddress;
|
||||||
|
|
|
@ -132,6 +132,8 @@ void DaemonSinkThread::handleDataBlock(SDRDaemonDataBlock& dataBlock)
|
||||||
|
|
||||||
txBlockx[i].m_header.m_frameIndex = frameIndex;
|
txBlockx[i].m_header.m_frameIndex = frameIndex;
|
||||||
txBlockx[i].m_header.m_blockIndex = i;
|
txBlockx[i].m_header.m_blockIndex = i;
|
||||||
|
txBlockx[i].m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||||
|
txBlockx[i].m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||||
descriptorBlocks[i].Block = (void *) &(txBlockx[i].m_protectedBlock);
|
descriptorBlocks[i].Block = (void *) &(txBlockx[i].m_protectedBlock);
|
||||||
descriptorBlocks[i].Index = txBlockx[i].m_header.m_blockIndex;
|
descriptorBlocks[i].Index = txBlockx[i].m_header.m_blockIndex;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,7 @@ private:
|
||||||
QMutex m_startWaitMutex;
|
QMutex m_startWaitMutex;
|
||||||
QWaitCondition m_startWaiter;
|
QWaitCondition m_startWaiter;
|
||||||
bool m_running;
|
bool m_running;
|
||||||
|
uint8_t m_sampleBytes;
|
||||||
|
|
||||||
CM256 m_cm256;
|
CM256 m_cm256;
|
||||||
CM256 *m_cm256p;
|
CM256 *m_cm256p;
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
|
|
||||||
#include "device/devicesinkapi.h"
|
#include "device/devicesinkapi.h"
|
||||||
#include "device/deviceuiset.h"
|
#include "device/deviceuiset.h"
|
||||||
|
#include "channel/sdrdaemondatablock.h"
|
||||||
#include "udpsinkfec.h"
|
#include "udpsinkfec.h"
|
||||||
#include "sdrdaemonsinkgui.h"
|
#include "sdrdaemonsinkgui.h"
|
||||||
|
|
||||||
|
@ -215,7 +216,7 @@ void SDRdaemonSinkGui::updateSampleRate()
|
||||||
|
|
||||||
void SDRdaemonSinkGui::updateTxDelayTooltip()
|
void SDRdaemonSinkGui::updateTxDelayTooltip()
|
||||||
{
|
{
|
||||||
int samplesPerBlock = UDPSinkFEC::bytesPerBlock / (SDR_TX_SAMP_SZ <= 16 ? 4 : 8);
|
int samplesPerBlock = SDRDaemonNbBytesPerBlock / (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)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,6 @@ MESSAGE_CLASS_DEFINITION(UDPSinkFECWorker::MsgConfigureRemoteAddress, Message)
|
||||||
|
|
||||||
UDPSinkFEC::UDPSinkFEC() :
|
UDPSinkFEC::UDPSinkFEC() :
|
||||||
m_sampleRate(48000),
|
m_sampleRate(48000),
|
||||||
m_sampleBytes(SDR_TX_SAMP_SZ <= 16 ? 2 : 4),
|
|
||||||
m_sampleBits(SDR_TX_SAMP_SZ),
|
|
||||||
m_nbSamples(0),
|
m_nbSamples(0),
|
||||||
m_nbBlocksFEC(0),
|
m_nbBlocksFEC(0),
|
||||||
m_txDelayRatio(0.0),
|
m_txDelayRatio(0.0),
|
||||||
|
@ -40,8 +38,8 @@ UDPSinkFEC::UDPSinkFEC() :
|
||||||
m_frameCount(0),
|
m_frameCount(0),
|
||||||
m_sampleIndex(0)
|
m_sampleIndex(0)
|
||||||
{
|
{
|
||||||
memset((char *) m_txBlocks, 0, 4*256*sizeof(SuperBlock));
|
memset((char *) m_txBlocks, 0, 4*256*sizeof(SDRDaemonSuperBlock));
|
||||||
memset((char *) &m_superBlock, 0, sizeof(SuperBlock));
|
memset((char *) &m_superBlock, 0, sizeof(SDRDaemonSuperBlock));
|
||||||
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];
|
||||||
|
@ -74,7 +72,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 = bytesPerBlock / (m_sampleBytes*2);
|
int samplesPerBlock = SDRDaemonNbBytesPerBlock / (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";
|
||||||
|
@ -113,14 +111,14 @@ 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
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
MetaDataFEC metaData;
|
SDRDaemonMetaDataFEC metaData;
|
||||||
|
|
||||||
gettimeofday(&tv, 0);
|
gettimeofday(&tv, 0);
|
||||||
|
|
||||||
metaData.m_centerFrequency = 0; // frequency not set by stream
|
metaData.m_centerFrequency = 0; // frequency not set by stream
|
||||||
metaData.m_sampleRate = m_sampleRate;
|
metaData.m_sampleRate = m_sampleRate;
|
||||||
metaData.m_sampleBytes = m_sampleBytes & 0xF;
|
metaData.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||||
metaData.m_sampleBits = m_sampleBits;
|
metaData.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||||
metaData.m_nbOriginalBlocks = m_nbOriginalBlocks;
|
metaData.m_nbOriginalBlocks = m_nbOriginalBlocks;
|
||||||
metaData.m_nbFECBlocks = m_nbBlocksFEC;
|
metaData.m_nbFECBlocks = m_nbBlocksFEC;
|
||||||
metaData.m_tv_sec = tv.tv_sec;
|
metaData.m_tv_sec = tv.tv_sec;
|
||||||
|
@ -133,9 +131,11 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk
|
||||||
|
|
||||||
memset((char *) &m_superBlock, 0, sizeof(m_superBlock));
|
memset((char *) &m_superBlock, 0, sizeof(m_superBlock));
|
||||||
|
|
||||||
m_superBlock.header.frameIndex = m_frameCount;
|
m_superBlock.m_header.m_frameIndex = m_frameCount;
|
||||||
m_superBlock.header.blockIndex = m_txBlockIndex;
|
m_superBlock.m_header.m_blockIndex = m_txBlockIndex;
|
||||||
memcpy((char *) &m_superBlock.protectedBlock, (const char *) &metaData, sizeof(MetaDataFEC));
|
m_superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||||
|
m_superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||||
|
memcpy((char *) &m_superBlock.m_protectedBlock, (const char *) &metaData, sizeof(SDRDaemonMetaDataFEC));
|
||||||
|
|
||||||
if (!(metaData == m_currentMetaFEC))
|
if (!(metaData == m_currentMetaFEC))
|
||||||
{
|
{
|
||||||
|
@ -157,74 +157,28 @@ 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 = bytesPerBlock / (m_sampleBytes*2);
|
int samplesPerBlock = SDRDaemonNbBytesPerBlock / (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
|
||||||
{
|
{
|
||||||
if (sizeof(Sample) == m_sampleBytes*2) // can do direct copy if sample sizes are equal
|
memcpy((char *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)],
|
||||||
{
|
|
||||||
memcpy((char *) &m_superBlock.protectedBlock.m_buf[m_sampleIndex*m_sampleBytes*2],
|
|
||||||
(const char *) &(*it),
|
(const char *) &(*it),
|
||||||
inRemainingSamples * sizeof(Sample));
|
inRemainingSamples * sizeof(Sample));
|
||||||
}
|
|
||||||
else if ((sizeof(Sample) == 8) && (m_sampleBytes == 2)) // modulators produce 16 bit samples
|
|
||||||
{
|
|
||||||
for (int is = 0; is < inRemainingSamples; is++)
|
|
||||||
{
|
|
||||||
int16_t *rp = (int16_t*) &(m_superBlock.protectedBlock.m_buf[(m_sampleIndex+is)*m_sampleBytes*2]);
|
|
||||||
int16_t *ip = (int16_t*) &(m_superBlock.protectedBlock.m_buf[(m_sampleIndex+is)*m_sampleBytes*2+2]);
|
|
||||||
*rp = (it+is)->m_real & 0xFFFF;
|
|
||||||
*ip = (it+is)->m_imag & 0xFFFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((sizeof(Sample) == 4) && (m_sampleBytes == 4)) // use 16 bit samples for Tx
|
|
||||||
{
|
|
||||||
for (int is = 0; is < inRemainingSamples; is++)
|
|
||||||
{
|
|
||||||
int32_t *rp = (int32_t*) &(m_superBlock.protectedBlock.m_buf[(m_sampleIndex+is)*m_sampleBytes*2]);
|
|
||||||
int32_t *ip = (int32_t*) &(m_superBlock.protectedBlock.m_buf[(m_sampleIndex+is)*m_sampleBytes*2+4]);
|
|
||||||
*rp = (it+is)->m_real;
|
|
||||||
*ip = (it+is)->m_imag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_sampleIndex += inRemainingSamples;
|
m_sampleIndex += inRemainingSamples;
|
||||||
it = end; // all input samples are consumed
|
it = end; // all input samples are consumed
|
||||||
}
|
}
|
||||||
else // complete super block and initiate the next if not end of frame
|
else // complete super block and initiate the next if not end of frame
|
||||||
{
|
{
|
||||||
if (sizeof(Sample) == m_sampleBytes*2) // can do direct copy if sample sizes are equal
|
memcpy((char *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)],
|
||||||
{
|
|
||||||
memcpy((char *) &m_superBlock.protectedBlock.m_buf[m_sampleIndex*m_sampleBytes*2],
|
|
||||||
(const char *) &(*it),
|
(const char *) &(*it),
|
||||||
(samplesPerBlock - m_sampleIndex) * sizeof(Sample));
|
(samplesPerBlock - m_sampleIndex) * sizeof(Sample));
|
||||||
}
|
|
||||||
else if ((sizeof(Sample) == 8) && (m_sampleBytes == 2)) // modulators produce 16 bit samples
|
|
||||||
{
|
|
||||||
for (int is = 0; is < samplesPerBlock - m_sampleIndex; is++)
|
|
||||||
{
|
|
||||||
int16_t *rp = (int16_t*) &(m_superBlock.protectedBlock.m_buf[(m_sampleIndex+is)*m_sampleBytes*2]);
|
|
||||||
int16_t *ip = (int16_t*) &(m_superBlock.protectedBlock.m_buf[(m_sampleIndex+is)*m_sampleBytes*2+2]);
|
|
||||||
*rp = (it+is)->m_real & 0xFFFF;
|
|
||||||
*ip = (it+is)->m_imag & 0xFFFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((sizeof(Sample) == 4) && (m_sampleBytes == 4)) // use 16 bit samples for Tx
|
|
||||||
{
|
|
||||||
for (int is = 0; is < samplesPerBlock - m_sampleIndex; is++)
|
|
||||||
{
|
|
||||||
int32_t *rp = (int32_t*) &(m_superBlock.protectedBlock.m_buf[(m_sampleIndex+is)*m_sampleBytes*2]);
|
|
||||||
int32_t *ip = (int32_t*) &(m_superBlock.protectedBlock.m_buf[(m_sampleIndex+is)*m_sampleBytes*2+4]);
|
|
||||||
*rp = (it+is)->m_real;
|
|
||||||
*ip = (it+is)->m_imag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
it += samplesPerBlock - m_sampleIndex;
|
it += samplesPerBlock - m_sampleIndex;
|
||||||
m_sampleIndex = 0;
|
m_sampleIndex = 0;
|
||||||
|
|
||||||
m_superBlock.header.frameIndex = m_frameCount;
|
m_superBlock.m_header.m_frameIndex = m_frameCount;
|
||||||
m_superBlock.header.blockIndex = m_txBlockIndex;
|
m_superBlock.m_header.m_blockIndex = m_txBlockIndex;
|
||||||
|
m_superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||||
|
m_superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||||
m_txBlocks[m_txBlocksIndex][m_txBlockIndex] = m_superBlock;
|
m_txBlocks[m_txBlocksIndex][m_txBlockIndex] = m_superBlock;
|
||||||
|
|
||||||
if (m_txBlockIndex == m_nbOriginalBlocks - 1) // frame complete
|
if (m_txBlockIndex == m_nbOriginalBlocks - 1) // frame complete
|
||||||
|
@ -263,7 +217,7 @@ UDPSinkFECWorker::~UDPSinkFECWorker()
|
||||||
m_inputMessageQueue.clear();
|
m_inputMessageQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDPSinkFECWorker::pushTxFrame(UDPSinkFEC::SuperBlock *txBlocks,
|
void UDPSinkFECWorker::pushTxFrame(SDRDaemonSuperBlock *txBlocks,
|
||||||
uint32_t nbBlocksFEC,
|
uint32_t nbBlocksFEC,
|
||||||
uint32_t txDelay,
|
uint32_t txDelay,
|
||||||
uint16_t frameIndex)
|
uint16_t frameIndex)
|
||||||
|
@ -320,11 +274,11 @@ void UDPSinkFECWorker::handleInputMessages()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDPSinkFECWorker::encodeAndTransmit(UDPSinkFEC::SuperBlock *txBlockx, uint16_t frameIndex, uint32_t nbBlocksFEC, uint32_t txDelay)
|
void UDPSinkFECWorker::encodeAndTransmit(SDRDaemonSuperBlock *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
|
||||||
UDPSinkFEC::ProtectedBlock fecBlocks[256]; //!< FEC data
|
SDRDaemonProtectedBlock fecBlocks[256]; //!< FEC data
|
||||||
|
|
||||||
if ((nbBlocksFEC == 0) || !m_cm256Valid)
|
if ((nbBlocksFEC == 0) || !m_cm256Valid)
|
||||||
{
|
{
|
||||||
|
@ -339,7 +293,7 @@ void UDPSinkFECWorker::encodeAndTransmit(UDPSinkFEC::SuperBlock *txBlockx, uint1
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cm256Params.BlockBytes = sizeof(UDPSinkFEC::ProtectedBlock);
|
cm256Params.BlockBytes = sizeof(SDRDaemonProtectedBlock);
|
||||||
cm256Params.OriginalCount = UDPSinkFEC::m_nbOriginalBlocks;
|
cm256Params.OriginalCount = UDPSinkFEC::m_nbOriginalBlocks;
|
||||||
cm256Params.RecoveryCount = nbBlocksFEC;
|
cm256Params.RecoveryCount = nbBlocksFEC;
|
||||||
|
|
||||||
|
@ -348,13 +302,15 @@ void UDPSinkFECWorker::encodeAndTransmit(UDPSinkFEC::SuperBlock *txBlockx, uint1
|
||||||
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].protectedBlock, 0, sizeof(UDPSinkFEC::ProtectedBlock));
|
memset((char *) &txBlockx[i].m_protectedBlock, 0, sizeof(SDRDaemonProtectedBlock));
|
||||||
}
|
}
|
||||||
|
|
||||||
txBlockx[i].header.frameIndex = frameIndex;
|
txBlockx[i].m_header.m_frameIndex = frameIndex;
|
||||||
txBlockx[i].header.blockIndex = i;
|
txBlockx[i].m_header.m_blockIndex = i;
|
||||||
descriptorBlocks[i].Block = (void *) &(txBlockx[i].protectedBlock);
|
txBlockx[i].m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
||||||
descriptorBlocks[i].Index = txBlockx[i].header.blockIndex;
|
txBlockx[i].m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
||||||
|
descriptorBlocks[i].Block = (void *) &(txBlockx[i].m_protectedBlock);
|
||||||
|
descriptorBlocks[i].Index = txBlockx[i].m_header.m_blockIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode FEC blocks
|
// Encode FEC blocks
|
||||||
|
@ -367,7 +323,7 @@ void UDPSinkFECWorker::encodeAndTransmit(UDPSinkFEC::SuperBlock *txBlockx, uint1
|
||||||
// Merge FEC with data to transmit
|
// Merge FEC with data to transmit
|
||||||
for (int i = 0; i < cm256Params.RecoveryCount; i++)
|
for (int i = 0; i < cm256Params.RecoveryCount; i++)
|
||||||
{
|
{
|
||||||
txBlockx[i + cm256Params.OriginalCount].protectedBlock = fecBlocks[i];
|
txBlockx[i + cm256Params.OriginalCount].m_protectedBlock = fecBlocks[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transmit all blocks
|
// Transmit all blocks
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "util/CRC64.h"
|
#include "util/CRC64.h"
|
||||||
#include "util/messagequeue.h"
|
#include "util/messagequeue.h"
|
||||||
#include "util/message.h"
|
#include "util/message.h"
|
||||||
|
#include "channel/sdrdaemondatablock.h"
|
||||||
|
|
||||||
#include "UDPSocket.h"
|
#include "UDPSocket.h"
|
||||||
|
|
||||||
|
@ -42,52 +43,52 @@ class UDPSinkFEC : public QObject
|
||||||
public:
|
public:
|
||||||
static const uint32_t m_udpSize = 512; //!< Size of UDP block in number of bytes
|
static const uint32_t m_udpSize = 512; //!< Size of UDP block in number of bytes
|
||||||
static const uint32_t m_nbOriginalBlocks = 128; //!< Number of original blocks in a protected block sequence
|
static const uint32_t m_nbOriginalBlocks = 128; //!< Number of original blocks in a protected block sequence
|
||||||
#pragma pack(push, 1)
|
//#pragma pack(push, 1)
|
||||||
struct MetaDataFEC
|
// struct MetaDataFEC
|
||||||
{
|
// {
|
||||||
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
|
||||||
uint8_t m_sampleBytes; //!< 9 MSB(4): indicators, LSB(4) number of bytes per sample
|
// uint8_t m_sampleBytes; //!< 9 MSB(4): indicators, LSB(4) number of bytes per sample
|
||||||
uint8_t m_sampleBits; //!< 10 number of effective bits per sample
|
// uint8_t m_sampleBits; //!< 10 number of effective bits per sample
|
||||||
uint8_t m_nbOriginalBlocks; //!< 11 number of blocks with original (protected) data
|
// uint8_t m_nbOriginalBlocks; //!< 11 number of blocks with original (protected) data
|
||||||
uint8_t m_nbFECBlocks; //!< 12 number of blocks carrying FEC
|
// uint8_t m_nbFECBlocks; //!< 12 number of blocks carrying FEC
|
||||||
uint32_t m_tv_sec; //!< 16 seconds of timestamp at start time of super-frame processing
|
// uint32_t m_tv_sec; //!< 16 seconds of timestamp at start time of super-frame processing
|
||||||
uint32_t m_tv_usec; //!< 20 microseconds of timestamp at start time of super-frame processing
|
// uint32_t m_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 MetaDataFEC& rhs)
|
// bool operator==(const MetaDataFEC& rhs)
|
||||||
{
|
// {
|
||||||
return (memcmp((const char *) this, (const char *) &rhs, 12) == 0); // Only the 12 first bytes are relevant
|
// return (memcmp((const char *) this, (const char *) &rhs, 12) == 0); // Only the 12 first bytes are relevant
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
void init()
|
// void init()
|
||||||
{
|
// {
|
||||||
memset((char *) this, 0, sizeof(MetaDataFEC));
|
// memset((char *) this, 0, sizeof(MetaDataFEC));
|
||||||
m_nbFECBlocks = -1;
|
// m_nbFECBlocks = -1;
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
struct Header
|
// struct Header
|
||||||
{
|
// {
|
||||||
uint16_t frameIndex;
|
// uint16_t frameIndex;
|
||||||
uint8_t blockIndex;
|
// uint8_t blockIndex;
|
||||||
uint8_t filler;
|
// uint8_t filler;
|
||||||
uint32_t filler2;
|
// uint32_t filler2;
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
static const int bytesPerBlock = m_udpSize - sizeof(Header);
|
// static const int bytesPerBlock = m_udpSize - sizeof(Header);
|
||||||
|
//
|
||||||
struct ProtectedBlock
|
// struct ProtectedBlock
|
||||||
{
|
// {
|
||||||
uint8_t m_buf[bytesPerBlock];
|
// uint8_t m_buf[bytesPerBlock];
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
struct SuperBlock
|
// struct SuperBlock
|
||||||
{
|
// {
|
||||||
Header header;
|
// Header header;
|
||||||
ProtectedBlock protectedBlock;
|
// ProtectedBlock protectedBlock;
|
||||||
};
|
// };
|
||||||
#pragma pack(pop)
|
//#pragma pack(pop)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct UDP sink
|
* Construct UDP sink
|
||||||
|
@ -127,8 +128,6 @@ private:
|
||||||
std::string m_error;
|
std::string m_error;
|
||||||
|
|
||||||
uint32_t m_sampleRate; //!< sample rate in Hz
|
uint32_t m_sampleRate; //!< sample rate in Hz
|
||||||
uint8_t m_sampleBytes; //!< number of bytes per sample
|
|
||||||
uint8_t m_sampleBits; //!< number of effective bits per sample
|
|
||||||
uint32_t m_nbSamples; //!< total number of samples sent int the last frame
|
uint32_t m_nbSamples; //!< total number of samples sent int the last frame
|
||||||
|
|
||||||
QHostAddress m_ownAddress;
|
QHostAddress m_ownAddress;
|
||||||
|
@ -137,12 +136,12 @@ private:
|
||||||
uint8_t* m_bufMeta;
|
uint8_t* m_bufMeta;
|
||||||
uint8_t* m_buf;
|
uint8_t* m_buf;
|
||||||
|
|
||||||
MetaDataFEC m_currentMetaFEC; //!< Meta data for current frame
|
SDRDaemonMetaDataFEC 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
|
||||||
SuperBlock m_txBlocks[4][256]; //!< UDP blocks to send with original data + FEC
|
SDRDaemonSuperBlock m_txBlocks[4][256]; //!< UDP blocks to send with original data + FEC
|
||||||
SuperBlock m_superBlock; //!< current super block being built
|
SDRDaemonSuperBlock 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
|
||||||
|
@ -161,13 +160,13 @@ public:
|
||||||
{
|
{
|
||||||
MESSAGE_CLASS_DECLARATION
|
MESSAGE_CLASS_DECLARATION
|
||||||
public:
|
public:
|
||||||
UDPSinkFEC::SuperBlock *getTxBlocks() const { return m_txBlockx; }
|
SDRDaemonSuperBlock *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(
|
||||||
UDPSinkFEC::SuperBlock *txBlocks,
|
SDRDaemonSuperBlock *txBlocks,
|
||||||
uint32_t nbBlocksFEC,
|
uint32_t nbBlocksFEC,
|
||||||
uint32_t txDelay,
|
uint32_t txDelay,
|
||||||
uint16_t frameIndex)
|
uint16_t frameIndex)
|
||||||
|
@ -176,13 +175,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UDPSinkFEC::SuperBlock *m_txBlockx;
|
SDRDaemonSuperBlock *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(
|
||||||
UDPSinkFEC::SuperBlock *txBlocks,
|
SDRDaemonSuperBlock *txBlocks,
|
||||||
uint32_t nbBlocksFEC,
|
uint32_t nbBlocksFEC,
|
||||||
uint32_t txDelay,
|
uint32_t txDelay,
|
||||||
uint16_t frameIndex) :
|
uint16_t frameIndex) :
|
||||||
|
@ -218,7 +217,7 @@ public:
|
||||||
UDPSinkFECWorker();
|
UDPSinkFECWorker();
|
||||||
~UDPSinkFECWorker();
|
~UDPSinkFECWorker();
|
||||||
|
|
||||||
void pushTxFrame(UDPSinkFEC::SuperBlock *txBlocks,
|
void pushTxFrame(SDRDaemonSuperBlock *txBlocks,
|
||||||
uint32_t nbBlocksFEC,
|
uint32_t nbBlocksFEC,
|
||||||
uint32_t txDelay,
|
uint32_t txDelay,
|
||||||
uint16_t frameIndex);
|
uint16_t frameIndex);
|
||||||
|
@ -237,7 +236,7 @@ private slots:
|
||||||
void handleInputMessages();
|
void handleInputMessages();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void encodeAndTransmit(UDPSinkFEC::SuperBlock *txBlockx, uint16_t frameIndex, uint32_t nbBlocksFEC, uint32_t txDelay);
|
void encodeAndTransmit(SDRDaemonSuperBlock *txBlockx, uint16_t frameIndex, uint32_t nbBlocksFEC, uint32_t txDelay);
|
||||||
|
|
||||||
volatile bool m_running;
|
volatile bool m_running;
|
||||||
CM256 m_cm256; //!< CM256 library object
|
CM256 m_cm256; //!< CM256 library object
|
||||||
|
|
|
@ -38,7 +38,7 @@ struct SDRDaemonMetaDataFEC
|
||||||
{
|
{
|
||||||
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
|
||||||
uint8_t m_sampleBytes; //!< 9 4 LSB: number of bytes per sample (2 or 3)
|
uint8_t m_sampleBytes; //!< 9 4 LSB: number of bytes per sample (2 or 4)
|
||||||
uint8_t m_sampleBits; //!< 10 number of effective bits per sample (deprecated)
|
uint8_t m_sampleBits; //!< 10 number of effective bits per sample (deprecated)
|
||||||
uint8_t m_nbOriginalBlocks; //!< 11 number of blocks with original (protected) data
|
uint8_t m_nbOriginalBlocks; //!< 11 number of blocks with original (protected) data
|
||||||
uint8_t m_nbFECBlocks; //!< 12 number of blocks carrying FEC
|
uint8_t m_nbFECBlocks; //!< 12 number of blocks carrying FEC
|
||||||
|
@ -69,13 +69,17 @@ struct SDRDaemonHeader
|
||||||
{
|
{
|
||||||
uint16_t m_frameIndex;
|
uint16_t m_frameIndex;
|
||||||
uint8_t m_blockIndex;
|
uint8_t m_blockIndex;
|
||||||
|
uint8_t m_sampleBytes; //!< number of bytes per sample (2 or 4) for this block
|
||||||
|
uint8_t m_sampleBits; //!< number of bits per sample
|
||||||
uint8_t m_filler;
|
uint8_t m_filler;
|
||||||
uint32_t m_filler2;
|
uint16_t m_filler2;
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
m_frameIndex = 0;
|
m_frameIndex = 0;
|
||||||
m_blockIndex = 0;
|
m_blockIndex = 0;
|
||||||
|
m_sampleBytes = 2;
|
||||||
|
m_sampleBits = 16;
|
||||||
m_filler = 0;
|
m_filler = 0;
|
||||||
m_filler2 = 0;
|
m_filler2 = 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue