1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-02-03 09:44:01 -05:00

SDRdaemonFEC support. auto R/W correction

This commit is contained in:
f4exb 2016-07-13 03:31:19 +02:00
parent 95804345d5
commit c8785c94bb
4 changed files with 82 additions and 12 deletions

View File

@ -223,8 +223,6 @@ void SDRdaemonUDPHandler::tick()
{
m_throttlems = throttlems;
m_readLengthSamples = (m_sdrDaemonBuffer.getSampleRate() * (m_throttlems+(m_throttleToggle ? 1 : 0))) / 1000;
m_readLengthSamples += m_sdrDaemonBuffer.getRWBalanceCorrection();
m_readLength = m_readLengthSamples * SDRdaemonBuffer::m_iqSampleSize;
m_throttleToggle = !m_throttleToggle;
}
@ -232,6 +230,8 @@ void SDRdaemonUDPHandler::tick()
m_readLengthSamples += m_sdrDaemonBuffer.getRWBalanceCorrection();
}
m_readLength = m_readLengthSamples * SDRdaemonBuffer::m_iqSampleSize;
// read samples directly feeding the SampleFifo (no callback)
m_sampleFifo->write(reinterpret_cast<quint8*>(m_sdrDaemonBuffer.readData(m_readLength)), m_readLength);
m_samplesCount += m_readLengthSamples;

View File

@ -34,11 +34,16 @@ SDRdaemonFECBuffer::SDRdaemonFECBuffer(uint32_t throttlems) :
m_readIndex(0),
m_readBuffer(0),
m_readSize(0),
m_bufferLenSec(0.0f)
m_bufferLenSec(0.0f),
m_nbReads(0),
m_nbWrites(0),
m_balCorrection(0),
m_balCorrLimit(0)
{
m_currentMeta.init();
m_framesNbBytes = nbDecoderSlots * sizeof(BufferFrame);
m_wrDeltaEstimate = m_framesNbBytes / 2;
m_readNbBytes = 1;
m_paramsCM256.BlockBytes = sizeof(ProtectedBlock); // never changes
m_paramsCM256.OriginalCount = m_nbOriginalBlocks; // never changes
}
@ -70,12 +75,62 @@ void SDRdaemonFECBuffer::initReadIndex()
{
m_readIndex = ((m_decoderIndexHead + (nbDecoderSlots/2)) % nbDecoderSlots) * sizeof(BufferFrame);
m_wrDeltaEstimate = m_framesNbBytes / 2;
m_nbReads = 0;
m_nbWrites = 0;
}
void SDRdaemonFECBuffer::rwCorrectionEstimate(int slotIndex)
{
if (m_nbReads >= 40) // check every ~1s as tick is ~50ms
{
int targetPivotSlot = (slotIndex + (nbDecoderSlots/2)) % nbDecoderSlots; // slot at half buffer opposite of current write slot
int targetPivotIndex = targetPivotSlot * sizeof(BufferFrame); // buffer index corresponding to start of above slot
int normalizedReadIndex = (m_readIndex < targetPivotIndex ? m_readIndex + nbDecoderSlots * sizeof(BufferFrame) : m_readIndex)
- (targetPivotSlot * sizeof(BufferFrame)); // normalize read index so it is positive and zero at start of pivot slot
int dBytes;
int rwDelta = (m_nbReads * m_readNbBytes) - (m_nbWrites * sizeof(BufferFrame));
if (normalizedReadIndex < (nbDecoderSlots/ 2) * sizeof(BufferFrame)) // read leads
{
dBytes = - normalizedReadIndex - rwDelta;
}
else // read lags
{
dBytes = (nbDecoderSlots * sizeof(BufferFrame)) - normalizedReadIndex - rwDelta;
}
m_balCorrection = (m_balCorrection / 4) + (dBytes / (int) (m_iqSampleSize * m_nbReads)); // correction is in number of samples. Alpha = 0.25
if (m_balCorrection < -m_balCorrLimit) {
m_balCorrection = -m_balCorrLimit;
} else if (m_balCorrection > m_balCorrLimit) {
m_balCorrection = m_balCorrLimit;
}
float rwRatio = (float) (m_nbWrites * sizeof(BufferFrame)) / (float) (m_nbReads * m_readNbBytes);
qDebug() << "SDRdaemonFECBuffer::rwCorrectionEstimate: "
<< " m_nbReads: " << m_nbReads
<< " m_nbWrites: " << m_nbWrites
<< " rwDelta: " << rwDelta
<< " targetPivotSlot: " << targetPivotSlot
<< " targetPivotIndex: " << targetPivotIndex
<< " m_readIndex: " << m_readIndex
<< " normalizedReadIndex: " << normalizedReadIndex
<< " dBytes: " << dBytes
<< " m_balCorrection: " << m_balCorrection;
//m_balCorrection = dBytes / (int) (m_iqSampleSize * m_nbReads);
m_nbReads = 0;
m_nbWrites = 0;
}
}
void SDRdaemonFECBuffer::checkSlotData(int slotIndex)
{
int pseudoWriteIndex = slotIndex * sizeof(BufferFrame);
m_wrDeltaEstimate = pseudoWriteIndex - m_readIndex;
m_nbWrites++;
if (!m_decoderSlots[slotIndex].m_decoded)
//if (m_decoderSlots[slotIndex].m_blockCount < m_nbOriginalBlocks)
@ -95,6 +150,8 @@ void SDRdaemonFECBuffer::checkSlotData(int slotIndex)
if (sampleRate > 0) {
m_bufferLenSec = (float) m_framesNbBytes / (float) (sampleRate * m_iqSampleSize);
m_balCorrLimit = sampleRate / 1000; // +/- 1 ms correction max per read
m_readNbBytes = (sampleRate * m_iqSampleSize) / 20;
}
printMeta("SDRdaemonFECBuffer::checkSlotData: new meta", metaData); // print for change other than timestamp
@ -143,6 +200,7 @@ void SDRdaemonFECBuffer::writeData(char *array, uint32_t length)
m_decoderIndexHead = decoderIndex; // new decoder slot head
m_frameHead = frameIndex; // new frame head
checkSlotData(decoderIndex); // check slot before re-init
rwCorrectionEstimate(decoderIndex);
initDecodeSlot(decoderIndex); // collect stats and re-initialize current slot
}
@ -417,6 +475,8 @@ uint8_t *SDRdaemonFECBuffer::readData(int32_t length)
uint8_t *buffer = (uint8_t *) m_frames;
uint32_t readIndex = m_readIndex;
m_nbReads++;
if (m_readIndex + length < m_framesNbBytes) // ends before buffer bound
{
m_readIndex += length;

View File

@ -24,9 +24,9 @@
#include "util/movingaverage.h"
#define SDRDAEMONFEC_UDPSIZE 512 // UDP payload size
#define SDRDAEMONFEC_NBORIGINALBLOCKS 128 // number of sample blocks per frame excluding FEC blocks
#define SDRDAEMONFEC_NBDECODERSLOTS 16 // power of two sub multiple of uint16_t size. A too large one is superfluous.
#define SDRDAEMONFEC_UDPSIZE 512 // UDP payload size
#define SDRDAEMONFEC_NBORIGINALBLOCKS 128 // number of sample blocks per frame excluding FEC blocks
#define SDRDAEMONFEC_NBDECODERSLOTS 16 // power of two sub multiple of uint16_t size. A too large one is superfluous.
class SDRdaemonFECBuffer
{
@ -99,7 +99,7 @@ public:
float getAvgNbRecovery() const { return m_avgNbRecovery; }
float getBufferLengthInSecs() const { return m_bufferLenSec; }
int32_t getRWBalanceCorrection(int throttlems) const { return m_balCorrection; }
int32_t getRWBalanceCorrection() const { return m_balCorrection; }
/** Get buffer gauge value in % of buffer size ([-50:50])
* [-50:0] : write leads or read lags
@ -164,17 +164,22 @@ private:
MovingAverage<int, int, 10> m_avgNbRecovery; //!< (stats) average number of recovery blocks used
int m_readIndex; //!< current byte read index in frames buffer
int m_wrDeltaEstimate; //!< Sampled estimate of write to read indexes difference
int m_readNbBytes; //!< Nominal number of bytes per read (50ms)
uint32_t m_throttlemsNominal; //!< Initial throttle in ms
uint8_t* m_readBuffer; //!< Read buffer to hold samples when looping back to beginning of raw buffer
uint32_t m_readSize; //!< Read buffer size
int32_t m_balCorrection; //!< R/W balance correction in number of samples per nominal tick period
float m_bufferLenSec;
int m_nbReads; //!< Number of buffer reads since start of auto R/W balance correction period
int m_nbWrites; //!< Number of buffer writes since start of auto R/W balance correction period
int m_balCorrection; //!< R/W balance correction in number of samples
int m_balCorrLimit; //!< Correction absolute value limit in number of samples
void initDecodeAllSlots();
void initReadIndex();
void rwSkewEstimate(int slotIndex);
void rwCorrectionEstimate(int slotIndex);
void checkSlotData(int slotIndex);
void initDecodeSlot(int slotIndex);

View File

@ -202,11 +202,16 @@ void SDRdaemonFECUDPHandler::tick()
{
m_throttlems = throttlems;
m_readLengthSamples = (m_sdrDaemonBuffer.getCurrentMeta().m_sampleRate * (m_throttlems+(m_throttleToggle ? 1 : 0))) / 1000;
m_readLength = m_readLengthSamples * SDRdaemonFECBuffer::m_iqSampleSize;
m_throttleToggle = !m_throttleToggle;
}
// read samples directly feeding the SampleFifo (no callback)
if (m_autoCorrBuffer) {
m_readLengthSamples += m_sdrDaemonBuffer.getRWBalanceCorrection();
}
m_readLength = m_readLengthSamples * SDRdaemonFECBuffer::m_iqSampleSize;
// read samples directly feeding the SampleFifo (no callback)
m_sampleFifo->write(reinterpret_cast<quint8*>(m_sdrDaemonBuffer.readData(m_readLength)), m_readLength);
m_samplesCount += m_readLengthSamples;
@ -227,7 +232,7 @@ void SDRdaemonFECUDPHandler::tick()
m_sdrDaemonBuffer.getCurNbRecovery(),
m_sdrDaemonBuffer.getAvgNbBlocks(),
m_sdrDaemonBuffer.getAvgNbRecovery());
m_outputMessageQueueToGUI->push(report);
m_outputMessageQueueToGUI->push(report);
}
}