diff --git a/devices/sdrdaemon/CMakeLists.txt b/devices/sdrdaemon/CMakeLists.txt deleted file mode 100644 index 51bc08d8c..000000000 --- a/devices/sdrdaemon/CMakeLists.txt +++ /dev/null @@ -1,55 +0,0 @@ -project(sdrdaemondevice) - -if (HAS_SSSE3) - message(STATUS "SDRdaemonDevice: use SSSE3 SIMD" ) -elseif (HAS_NEON) - message(STATUS "SDRdaemonDevice: use Neon SIMD" ) -else() - message(STATUS "SDRdaemonDevice: Unsupported architecture") - return() -endif() - -set(sdrdaemondevice_SOURCES - sdrdaemonfecbuffer.cpp -) - -set(sdrdaemondevice_HEADERS - sdrdaemonfecbuffer.h -) - -add_definitions(${QT_DEFINITIONS}) -add_definitions(-DQT_SHARED) - -if (BUILD_DEBIAN) -include_directories( - . - ${CMAKE_CURRENT_BINARY_DIR} - ${LIBCM256CCSRC} -) -else (BUILD_DEBIAN) -include_directories( - . - ${CMAKE_CURRENT_BINARY_DIR} - ${CM256CC_INCLUDE_DIR} -) -endif (BUILD_DEBIAN) - -add_library(sdrdaemondevice SHARED - ${sdrdaemondevice_SOURCES} -) - -if (BUILD_DEBIAN) -target_link_libraries(sdrdaemondevice - ${QT_LIBRARIES} - cm256cc -) -else (BUILD_DEBIAN) -target_link_libraries(sdrdaemondevice - ${QT_LIBRARIES} - ${CM256CC_LIBRARIES} -) -endif (BUILD_DEBIAN) - -qt5_use_modules(sdrdaemondevice Core) - -install(TARGETS sdrdaemondevice DESTINATION lib) diff --git a/devices/sdrdaemon/sdrdaemonfecbuffer.cpp b/devices/sdrdaemon/sdrdaemonfecbuffer.cpp deleted file mode 100644 index bb8629627..000000000 --- a/devices/sdrdaemon/sdrdaemonfecbuffer.cpp +++ /dev/null @@ -1,377 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2016 Edouard Griffiths, F4EXB // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation as version 3 of the License, or // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License V3 for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program. If not, see . // -/////////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include - -#include "sdrdaemonfecbuffer.h" - - -const int SDRdaemonFECBuffer::m_sampleSize = 2; -const int SDRdaemonFECBuffer::m_iqSampleSize = 2 * m_sampleSize; - -SDRdaemonFECBuffer::SDRdaemonFECBuffer(uint32_t throttlems) : - m_decoderIndexHead(nbDecoderSlots/2), - m_frameHead(0), - m_curNbBlocks(0), - m_minNbBlocks(256), - m_curOriginalBlocks(0), - m_minOriginalBlocks(128), - m_curNbRecovery(0), - m_maxNbRecovery(0), - m_framesDecoded(true), - m_readIndex(0), - m_throttlemsNominal(throttlems), - m_readBuffer(0), - m_readSize(0), - 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_tvOut_sec = 0; - m_tvOut_usec = 0; - m_readNbBytes = 1; - m_paramsCM256.BlockBytes = sizeof(ProtectedBlock); // never changes - m_paramsCM256.OriginalCount = m_nbOriginalBlocks; // never changes - - if (!m_cm256.isInitialized()) { - m_cm256_OK = false; - qDebug() << "SDRdaemonFECBuffer::SDRdaemonFECBuffer: cannot initialize CM256 library"; - } else { - m_cm256_OK = true; - } -} - -SDRdaemonFECBuffer::~SDRdaemonFECBuffer() -{ - if (m_readBuffer) { - delete[] m_readBuffer; - } -} - -void SDRdaemonFECBuffer::initDecodeAllSlots() -{ - for (int i = 0; i < nbDecoderSlots; i++) - { - m_decoderSlots[i].m_blockCount = 0; - m_decoderSlots[i].m_originalCount = 0; - m_decoderSlots[i].m_recoveryCount = 0; - m_decoderSlots[i].m_decoded = false; - m_decoderSlots[i].m_metaRetrieved = false; - resetOriginalBlocks(i); - memset((void *) m_decoderSlots[i].m_recoveryBlocks, 0, m_nbOriginalBlocks * sizeof(ProtectedBlock)); - } -} - -void SDRdaemonFECBuffer::initDecodeSlot(int slotIndex) -{ - // collect stats before voiding the slot - - m_curNbBlocks = m_decoderSlots[slotIndex].m_blockCount; - m_curOriginalBlocks = m_decoderSlots[slotIndex].m_originalCount; - m_curNbRecovery = m_decoderSlots[slotIndex].m_recoveryCount; - m_avgNbBlocks(m_curNbBlocks); - m_avgOrigBlocks(m_curOriginalBlocks); - m_avgNbRecovery(m_curNbRecovery); - m_framesDecoded = m_framesDecoded && m_decoderSlots[slotIndex].m_decoded; - - if (m_curNbBlocks < m_minNbBlocks) { - m_minNbBlocks = m_curNbBlocks; - } - - if (m_curOriginalBlocks < m_minOriginalBlocks) { - m_minOriginalBlocks = m_curOriginalBlocks; - } - - if (m_curNbRecovery > m_maxNbRecovery) { - m_maxNbRecovery = m_curNbRecovery; - } - - // void the slot - - m_decoderSlots[slotIndex].m_blockCount = 0; - m_decoderSlots[slotIndex].m_originalCount = 0; - m_decoderSlots[slotIndex].m_recoveryCount = 0; - m_decoderSlots[slotIndex].m_decoded = false; - m_decoderSlots[slotIndex].m_metaRetrieved = false; - - resetOriginalBlocks(slotIndex); - memset((void *) m_decoderSlots[slotIndex].m_recoveryBlocks, 0, m_nbOriginalBlocks * sizeof(ProtectedBlock)); -} - -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 - uint32_t 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; - } - - m_nbReads = 0; - m_nbWrites = 0; - } -} - -void SDRdaemonFECBuffer::checkSlotData(int slotIndex) -{ - int pseudoWriteIndex = slotIndex * sizeof(BufferFrame); - m_wrDeltaEstimate = pseudoWriteIndex - m_readIndex; - m_nbWrites++; - - int rwDelayBytes = (m_wrDeltaEstimate > 0 ? m_wrDeltaEstimate : sizeof(BufferFrame) * nbDecoderSlots + m_wrDeltaEstimate); - int sampleRate = m_currentMeta.m_sampleRate; - - if (sampleRate > 0) - { - int64_t ts = m_currentMeta.m_tv_sec * 1000000LL + m_currentMeta.m_tv_usec; - ts -= (rwDelayBytes * 1000000LL) / (sampleRate * sizeof(Sample)); - m_tvOut_sec = ts / 1000000LL; - m_tvOut_usec = ts - (m_tvOut_sec * 1000000LL); - } - - if (!m_decoderSlots[slotIndex].m_decoded) - { - qDebug() << "SDRdaemonFECBuffer::checkSlotData: incomplete frame:" - << " m_blockCount: " << m_decoderSlots[slotIndex].m_blockCount - << " m_recoveryCount: " << m_decoderSlots[slotIndex].m_recoveryCount; - } -} - -void SDRdaemonFECBuffer::writeData(char *array) -{ - SuperBlock *superBlock = (SuperBlock *) array; - int frameIndex = superBlock->header.frameIndex; - int decoderIndex = frameIndex % nbDecoderSlots; - - // frame break - - if (m_frameHead == -1) // initial state - { - m_decoderIndexHead = decoderIndex; // new decoder slot head - m_frameHead = frameIndex; - initReadIndex(); // reset read index - initDecodeAllSlots(); // initialize all slots - } - else if (m_frameHead != frameIndex) // frame break => new frame starts - { - 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 - } - - // Block processing - - if (m_decoderSlots[decoderIndex].m_blockCount < m_nbOriginalBlocks) // not enough blocks to decode -> store data - { - int blockIndex = superBlock->header.blockIndex; - int blockCount = m_decoderSlots[decoderIndex].m_blockCount; - int recoveryCount = m_decoderSlots[decoderIndex].m_recoveryCount; - m_decoderSlots[decoderIndex].m_cm256DescriptorBlocks[blockCount].Index = blockIndex; - - if (blockIndex == 0) // first block with meta - { - m_decoderSlots[decoderIndex].m_metaRetrieved = true; - } - - if (blockIndex < m_nbOriginalBlocks) // original data - { - m_decoderSlots[decoderIndex].m_cm256DescriptorBlocks[blockCount].Block = (void *) storeOriginalBlock(decoderIndex, blockIndex, superBlock->protectedBlock); - m_decoderSlots[decoderIndex].m_originalCount++; - } - else // recovery data - { - m_decoderSlots[decoderIndex].m_recoveryBlocks[recoveryCount] = superBlock->protectedBlock; - m_decoderSlots[decoderIndex].m_cm256DescriptorBlocks[blockCount].Block = (void *) &m_decoderSlots[decoderIndex].m_recoveryBlocks[recoveryCount]; - m_decoderSlots[decoderIndex].m_recoveryCount++; - } - } - - m_decoderSlots[decoderIndex].m_blockCount++; - - if (m_decoderSlots[decoderIndex].m_blockCount == m_nbOriginalBlocks) // ready to decode - { - m_decoderSlots[decoderIndex].m_decoded = true; - - if (m_cm256_OK && (m_decoderSlots[decoderIndex].m_recoveryCount > 0)) // recovery data used => need to decode FEC - { - m_paramsCM256.BlockBytes = sizeof(ProtectedBlock); // never changes - m_paramsCM256.OriginalCount = m_nbOriginalBlocks; // never changes - - if (m_decoderSlots[decoderIndex].m_metaRetrieved) { - m_paramsCM256.RecoveryCount = m_currentMeta.m_nbFECBlocks; - } else { - m_paramsCM256.RecoveryCount = m_decoderSlots[decoderIndex].m_recoveryCount; - } - - if (m_cm256.cm256_decode(m_paramsCM256, m_decoderSlots[decoderIndex].m_cm256DescriptorBlocks)) // CM256 decode - { - qDebug() << "SDRdaemonFECBuffer::writeData: decode CM256 error:" - << " m_originalCount: " << m_decoderSlots[decoderIndex].m_originalCount - << " m_recoveryCount: " << m_decoderSlots[decoderIndex].m_recoveryCount; - } - else - { - qDebug() << "SDRdaemonFECBuffer::writeData: decode CM256 success:" - << " m_originalCount: " << m_decoderSlots[decoderIndex].m_originalCount - << " m_recoveryCount: " << m_decoderSlots[decoderIndex].m_recoveryCount; - - for (int ir = 0; ir < m_decoderSlots[decoderIndex].m_recoveryCount; ir++) // restore missing blocks - { - int recoveryIndex = m_nbOriginalBlocks - m_decoderSlots[decoderIndex].m_recoveryCount + ir; - int blockIndex = m_decoderSlots[decoderIndex].m_cm256DescriptorBlocks[recoveryIndex].Index; - ProtectedBlock *recoveredBlock = (ProtectedBlock *) m_decoderSlots[decoderIndex].m_cm256DescriptorBlocks[recoveryIndex].Block; - - if (blockIndex == 0) // first block with meta - { - MetaDataFEC *metaData = (MetaDataFEC *) recoveredBlock; - - boost::crc_32_type crc32; - crc32.process_bytes(metaData, 20); - - if (crc32.checksum() == metaData->m_crc32) - { - m_decoderSlots[decoderIndex].m_metaRetrieved = true; - printMeta("SDRdaemonFECBuffer::writeData: recovered meta", metaData); - } - else - { - qDebug() << "SDRdaemonFECBuffer::writeData: recovered meta: invalid CRC32"; - } - } - - storeOriginalBlock(decoderIndex, blockIndex, *recoveredBlock); - - qDebug() << "SDRdaemonFECBuffer::writeData: recovered block #" << blockIndex; - } // restore missing blocks - } // CM256 decode - } // revovery - - if (m_decoderSlots[decoderIndex].m_metaRetrieved) // block zero with its meta data has been received - { - MetaDataFEC *metaData = getMetaData(decoderIndex); - - if (!(*metaData == m_currentMeta)) - { - int sampleRate = metaData->m_sampleRate; - - 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::writeData: new meta", metaData); // print for change other than timestamp - } - - m_currentMeta = *metaData; // renew current meta - } // check block 0 - } // decode -} - -uint8_t *SDRdaemonFECBuffer::readData(uint32_t length) -{ - uint8_t *buffer = (uint8_t *) m_frames; - uint32_t readIndex = m_readIndex; - - m_nbReads++; - - // SEGFAULT FIX: arbitratily truncate so that it does not exceed buffer length - if (length > framesSize) { - length = framesSize; - } - - if (m_readIndex + length < m_framesNbBytes) // ends before buffer bound - { - m_readIndex += length; - return &buffer[readIndex]; - } - else if (m_readIndex + length == m_framesNbBytes) // ends at buffer bound - { - m_readIndex = 0; - return &buffer[readIndex]; - } - else // ends after buffer bound - { - if (length > m_readSize) // reallocate composition buffer if necessary - { - if (m_readBuffer) { - delete[] m_readBuffer; - } - - m_readBuffer = new uint8_t[length]; - m_readSize = length; - } - - std::memcpy((void *) m_readBuffer, (const void *) &buffer[m_readIndex], m_framesNbBytes - m_readIndex); // copy end of buffer - length -= m_framesNbBytes - m_readIndex; - std::memcpy((void *) &m_readBuffer[m_framesNbBytes - m_readIndex], (const void *) buffer, length); // copy start of buffer - m_readIndex = length; - return m_readBuffer; - } -} - -void SDRdaemonFECBuffer::printMeta(const QString& header, MetaDataFEC *metaData) -{ - qDebug() << header << ": " - << "|" << metaData->m_centerFrequency - << ":" << metaData->m_sampleRate - << ":" << (int) (metaData->m_sampleBytes & 0xF) - << ":" << (int) metaData->m_sampleBits - << ":" << (int) metaData->m_nbOriginalBlocks - << ":" << (int) metaData->m_nbFECBlocks - << "|" << metaData->m_tv_sec - << ":" << metaData->m_tv_usec - << "|"; -} diff --git a/devices/sdrdaemon/sdrdaemonfecbuffer.h b/devices/sdrdaemon/sdrdaemonfecbuffer.h deleted file mode 100644 index 640a5f0b8..000000000 --- a/devices/sdrdaemon/sdrdaemonfecbuffer.h +++ /dev/null @@ -1,272 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2016 Edouard Griffiths, F4EXB // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation as version 3 of the License, or // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License V3 for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program. If not, see . // -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef DEVICES_SDRDAEMON_SDRDAEMONFECBUFFER_H_ -#define DEVICES_SDRDAEMON_SDRDAEMONFECBUFFER_H_ - -#include -#include -#include -#include "cm256.h" -#include "util/movingaverage.h" - - -#define SDRDAEMONFEC_UDPSIZE 512 // UDP payload size -#define SDRDAEMONSOURCE_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 -{ -public: -#pragma pack(push, 1) - struct MetaDataFEC - { - uint32_t m_centerFrequency; //!< 4 center frequency in kHz - 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_sampleBits; //!< 10 number of effective bits per sample - uint8_t m_nbOriginalBlocks; //!< 11 number of blocks with original (protected) data - 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_usec; //!< 20 microseconds of timestamp at start time of super-frame processing - uint32_t m_crc32; //!< 24 CRC32 of the above - - bool operator==(const MetaDataFEC& rhs) - { - return (memcmp((const void *) this, (const void *) &rhs, 12) == 0); // Only the 12 first bytes are relevant - } - - void init() - { - memset((void *) this, 0, sizeof(MetaDataFEC)); - } - }; - - struct Sample - { - int16_t i; - int16_t q; - }; - - struct Header - { - uint16_t frameIndex; - uint8_t blockIndex; - uint8_t filler; - }; - - static const int samplesPerBlock = (SDRDAEMONFEC_UDPSIZE - sizeof(Header)) / sizeof(Sample); - static const int framesSize = SDRDAEMONFEC_NBDECODERSLOTS * (SDRDAEMONSOURCE_NBORIGINALBLOCKS - 1) * (SDRDAEMONFEC_UDPSIZE - sizeof(Header)); - - struct ProtectedBlock - { - Sample samples[samplesPerBlock]; - }; - - struct SuperBlock - { - Header header; - ProtectedBlock protectedBlock; - }; -#pragma pack(pop) - - SDRdaemonFECBuffer(uint32_t throttlems); - ~SDRdaemonFECBuffer(); - - // R/W operations - void writeData(char *array); //!< Write data into buffer. - uint8_t *readData(uint32_t length); //!< Read data from buffer - - // meta data - const MetaDataFEC& getCurrentMeta() const { return m_currentMeta; } - - // samples timestamp - uint32_t getTVOutSec() const { return m_tvOut_sec; } - uint32_t getTVOutUsec() const { return m_tvOut_usec; } - - // stats - - int getCurNbBlocks() const { return m_curNbBlocks; } - int getCurOriginalBlocks() const { return m_curOriginalBlocks; } - int getCurNbRecovery() const { return m_curNbRecovery; } - float getAvgNbBlocks() const { return m_avgNbBlocks; } - float getAvgOriginalBlocks() const { return m_avgOrigBlocks; } - float getAvgNbRecovery() const { return m_avgNbRecovery; } - - int getMinNbBlocks() - { - int minNbBlocks = m_minNbBlocks; - m_minNbBlocks = 256; - return minNbBlocks; - } - - int getMinOriginalBlocks() - { - int minOriginalBlocks = m_minOriginalBlocks; - m_minOriginalBlocks = 128; - return minOriginalBlocks; - } - - int getMaxNbRecovery() - { - int maxNbRecovery = m_maxNbRecovery; - m_maxNbRecovery = 0; - return maxNbRecovery; - } - - bool allFramesDecoded() - { - bool framesDecoded = m_framesDecoded; - m_framesDecoded = true; - return framesDecoded; - } - - float getBufferLengthInSecs() const { return m_bufferLenSec; } - int32_t getRWBalanceCorrection() const { return m_balCorrection; } - - /** Get buffer gauge value in % of buffer size ([-50:50]) - * [-50:0] : write leads or read lags - * [0:50] : read leads or write lags - */ - inline int32_t getBufferGauge() const - { - if (m_framesNbBytes) - { - int32_t val = (m_wrDeltaEstimate * 100) / (int32_t) m_framesNbBytes; - int32_t ret = val < 0 ? -val - 50 : 50 -val; - return ret; - } - else - { - return 0; // default position - } - } - - static const int m_udpPayloadSize = SDRDAEMONFEC_UDPSIZE; - static const int m_nbOriginalBlocks = SDRDAEMONSOURCE_NBORIGINALBLOCKS; - static const int m_sampleSize; - static const int m_iqSampleSize; - -private: - static const int nbDecoderSlots = SDRDAEMONFEC_NBDECODERSLOTS; - -#pragma pack(push, 1) - struct BufferFrame - { - ProtectedBlock m_blocks[m_nbOriginalBlocks - 1]; - }; -#pragma pack(pop) - - struct DecoderSlot - { - ProtectedBlock m_blockZero; //!< First block of a frame. Has meta data. - ProtectedBlock m_originalBlocks[m_nbOriginalBlocks]; //!< Original blocks retrieved directly or by later FEC - ProtectedBlock m_recoveryBlocks[m_nbOriginalBlocks]; //!< Recovery blocks (FEC blocks) with max size - CM256::cm256_block m_cm256DescriptorBlocks[m_nbOriginalBlocks]; //!< CM256 decoder descriptors (block addresses and block indexes) - int m_blockCount; //!< number of blocks received for this frame - int m_originalCount; //!< number of original blocks received - int m_recoveryCount; //!< number of recovery blocks received - bool m_decoded; //!< true if decoded - bool m_metaRetrieved; //!< true if meta data (block zero) was retrieved - }; - - MetaDataFEC m_currentMeta; //!< Stored current meta data - CM256::cm256_encoder_params m_paramsCM256; //!< CM256 decoder parameters block - DecoderSlot m_decoderSlots[nbDecoderSlots]; //!< CM256 decoding control/buffer slots - BufferFrame m_frames[nbDecoderSlots]; //!< Samples buffer - uint32_t m_framesNbBytes; //!< Number of bytes in samples buffer - int m_decoderIndexHead; //!< index of the current head frame slot in decoding slots - int m_frameHead; //!< index of the current head frame sent - int m_curNbBlocks; //!< (stats) instantaneous number of blocks received - int m_minNbBlocks; //!< (stats) minimum number of blocks received since last poll - int m_curOriginalBlocks; //!< (stats) instantanous number of original blocks received - int m_minOriginalBlocks; //!< (stats) minimum number of original blocks received since last poll - int m_curNbRecovery; //!< (stats) instantaneous number of recovery blocks used - int m_maxNbRecovery; //!< (stats) maximum number of recovery blocks used since last poll - MovingAverage m_avgNbBlocks; //!< (stats) average number of blocks received - MovingAverage m_avgOrigBlocks; //!< (stats) average number of original blocks received - MovingAverage m_avgNbRecovery; //!< (stats) average number of recovery blocks used - bool m_framesDecoded; //!< [stats] true if all frames were decoded since last poll - int m_readIndex; //!< current byte read index in frames buffer - int m_wrDeltaEstimate; //!< Sampled estimate of write to read indexes difference - uint32_t m_tvOut_sec; //!< Estimated returned samples timestamp (seconds) - uint32_t m_tvOut_usec; //!< Estimated returned samples timestamp (microseconds) - 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 - - 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 - CM256 m_cm256; //!< CM256 library - bool m_cm256_OK; //!< CM256 library initialized OK - - inline ProtectedBlock* storeOriginalBlock(int slotIndex, int blockIndex, const ProtectedBlock& protectedBlock) - { - if (blockIndex == 0) { - // m_decoderSlots[slotIndex].m_originalBlocks[0] = protectedBlock; - // return &m_decoderSlots[slotIndex].m_originalBlocks[0]; - m_decoderSlots[slotIndex].m_blockZero = protectedBlock; - return &m_decoderSlots[slotIndex].m_blockZero; - } else { - // m_decoderSlots[slotIndex].m_originalBlocks[blockIndex] = protectedBlock; - // return &m_decoderSlots[slotIndex].m_originalBlocks[blockIndex]; - m_frames[slotIndex].m_blocks[blockIndex - 1] = protectedBlock; - return &m_frames[slotIndex].m_blocks[blockIndex - 1]; - } - } - - inline ProtectedBlock& getOriginalBlock(int slotIndex, int blockIndex) - { - if (blockIndex == 0) { - // return m_decoderSlots[slotIndex].m_originalBlocks[0]; - return m_decoderSlots[slotIndex].m_blockZero; - } else { - // return m_decoderSlots[slotIndex].m_originalBlocks[blockIndex]; - return m_frames[slotIndex].m_blocks[blockIndex - 1]; - } - } - - inline MetaDataFEC *getMetaData(int slotIndex) - { - // return (MetaDataFEC *) &m_decoderSlots[slotIndex].m_originalBlocks[0]; - return (MetaDataFEC *) &m_decoderSlots[slotIndex].m_blockZero; - } - - inline void resetOriginalBlocks(int slotIndex) - { - // memset((void *) m_decoderSlots[slotIndex].m_originalBlocks, 0, m_nbOriginalBlocks * sizeof(ProtectedBlock)); - memset((void *) &m_decoderSlots[slotIndex].m_blockZero, 0, sizeof(ProtectedBlock)); - memset((void *) m_frames[slotIndex].m_blocks, 0, (m_nbOriginalBlocks - 1) * sizeof(ProtectedBlock)); - } - - void initDecodeAllSlots(); - void initReadIndex(); - void rwCorrectionEstimate(int slotIndex); - void checkSlotData(int slotIndex); - void initDecodeSlot(int slotIndex); - - static void printMeta(const QString& header, MetaDataFEC *metaData); -}; - - - -#endif /* DEVICES_SDRDAEMON_SDRDAEMONFECBUFFER_H_ */