diff --git a/plugins/channel/bfm/bfmdemod.h b/plugins/channel/bfm/bfmdemod.h index 348585bbe..2de4b0e40 100644 --- a/plugins/channel/bfm/bfmdemod.h +++ b/plugins/channel/bfm/bfmdemod.h @@ -64,6 +64,7 @@ public: Real getPilotLevel() const { return m_pilotPLL.get_pilot_level(); } Real getDecoderQua() const { return m_rdsDecoder.m_qua; } + Real getDecoderCorr() const { return m_rdsDecoder.m_corr; } bool getDecoderSynced() const { return m_rdsDecoder.synced(); } Real getDemodAcc() const { return m_rdsDemod.m_report.acc; } Real getDemodQua() const { return m_rdsDemod.m_report.qua; } diff --git a/plugins/channel/bfm/bfmdemodgui.cpp b/plugins/channel/bfm/bfmdemodgui.cpp index f019d11ed..19a7109d5 100644 --- a/plugins/channel/bfm/bfmdemodgui.cpp +++ b/plugins/channel/bfm/bfmdemodgui.cpp @@ -530,6 +530,7 @@ void BFMDemodGUI::rdsUpdate(bool force) // Quality metrics ui->demodQText->setText(QString("%1 %").arg(m_bfmDemod->getDemodQua(), 0, 'f', 0)); ui->decoderQText->setText(QString("%1 %").arg(m_bfmDemod->getDecoderQua(), 0, 'f', 0)); + ui->decoderCorrText->setText(QString("%1 %").arg(m_bfmDemod->getDecoderCorr(), 0, 'f', 0)); Real accDb = CalcDb::dbPower(std::fabs(m_bfmDemod->getDemodAcc())); ui->accumText->setText(QString("%1 dB").arg(accDb, 0, 'f', 1)); ui->fclkText->setText(QString("%1 Hz").arg(m_bfmDemod->getDemodFclk(), 0, 'f', 2)); diff --git a/plugins/channel/bfm/bfmdemodgui.ui b/plugins/channel/bfm/bfmdemodgui.ui index f82516ee5..0381f7f44 100644 --- a/plugins/channel/bfm/bfmdemodgui.ui +++ b/plugins/channel/bfm/bfmdemodgui.ui @@ -553,6 +553,25 @@ + + + + + 40 + 0 + + + + Corrected blocks percentage + + + 0% + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + diff --git a/plugins/channel/bfm/rdsdecoder.cpp b/plugins/channel/bfm/rdsdecoder.cpp index da7e8d15f..0bf263757 100644 --- a/plugins/channel/bfm/rdsdecoder.cpp +++ b/plugins/channel/bfm/rdsdecoder.cpp @@ -16,6 +16,7 @@ /////////////////////////////////////////////////////////////////////////////////// #include +#include "boost/format.hpp" #include "rdsdecoder.h" const unsigned int RDSDecoder::offset_pos[5] = {0,1,2,3,2}; @@ -31,14 +32,32 @@ RDSDecoder::RDSDecoder() m_bitCounter = 0; m_lastseenOffset = 0; m_wrongBlocksCounter = 0; + m_correctedBlocksCounter = 0; m_blocksCounter = 0; m_blockBitCounter = 0; m_blockNumber = 0; m_groupAssemblyStarted = false; m_sync = SYNC; m_groupGoodBlocksCounter = 0; - m_wrongBlocksCounter = 0; m_goodBlock = false; + + m_error_lut[0x200] = 0b1000000000000000; + m_error_lut[0x300] = 0b1100000000000000; + m_error_lut[0x180] = 0b0110000000000000; + m_error_lut[0x0c0] = 0b0011000000000000; + m_error_lut[0x060] = 0b0001100000000000; + m_error_lut[0x030] = 0b1000110000000000; + m_error_lut[0x018] = 0b1000011000000000; + m_error_lut[0x00c] = 0b1000001100000000; + m_error_lut[0x006] = 0b1000000110000000; + m_error_lut[0x003] = 0b1000000011000000; + m_error_lut[0x2dd] = 0b1000000001100000; + m_error_lut[0x3b2] = 0b1000000000110000; + m_error_lut[0x1d9] = 0b1000000000011000; + m_error_lut[0x230] = 0b1000000000001100; + m_error_lut[0x118] = 0b1000000000000110; + m_error_lut[0x08c] = 0b1000000000000011; + m_error_lut[0x046] = 0b1000000000000001; } RDSDecoder::~RDSDecoder() @@ -130,8 +149,15 @@ bool RDSDecoder::frameSync(bool bit) } else { - m_wrongBlocksCounter++; - m_goodBlock = false; + if (err_corr(block_received_crc, block_calculated_crc, dataword)) + { + m_correctedBlocksCounter++; + } + else + { + m_wrongBlocksCounter++; + m_goodBlock = false; + } } } } @@ -145,8 +171,15 @@ bool RDSDecoder::frameSync(bool bit) } else { - m_wrongBlocksCounter++; - m_goodBlock = false; + if (err_corr(block_received_crc, block_calculated_crc, dataword)) + { + m_correctedBlocksCounter++; + } + else + { + m_wrongBlocksCounter++; + m_goodBlock = false; + } } } @@ -199,8 +232,10 @@ bool RDSDecoder::frameSync(bool bit) } m_qua = 2.0 * (50 - m_wrongBlocksCounter); + m_corr = 2.0 * m_correctedBlocksCounter; m_blocksCounter = 0; m_wrongBlocksCounter = 0; + m_correctedBlocksCounter = 0; } } break; @@ -258,3 +293,25 @@ unsigned int RDSDecoder::calc_syndrome(unsigned long message, unsigned char mlen return (reg & ((1<second; + /* + unsigned int syncorr = calc_syndrome(symbol, 16); + std::string recstring = str(boost::format("%03X") % received_crc); + std::string calstring = str(boost::format("%03X") % calculated_crc); + std::string synstring = str(boost::format("%03X") % syn); + std::string corstring = str(boost::format("%03X") % syncorr); + qDebug() << "RDSDecoder::err_corr: " << recstring.c_str() << ":" << calstring.c_str() << ":" << synstring.c_str() << ":" << corstring.c_str();*/ + return true; + } + else + { + return false; + } +} diff --git a/plugins/channel/bfm/rdsdecoder.h b/plugins/channel/bfm/rdsdecoder.h index 349df09a0..cb93bf582 100644 --- a/plugins/channel/bfm/rdsdecoder.h +++ b/plugins/channel/bfm/rdsdecoder.h @@ -18,6 +18,8 @@ #ifndef PLUGINS_CHANNEL_BFM_RDSDECODER_H_ #define PLUGINS_CHANNEL_BFM_RDSDECODER_H_ +#include + class RDSDecoder { public: @@ -29,13 +31,16 @@ public: bool synced() const { return m_sync == SYNC; } float m_qua; + float m_corr; protected: unsigned int calc_syndrome(unsigned long message, unsigned char mlen); + bool err_corr(unsigned int received_crc, unsigned int calculated_crc, unsigned int& symbol); void enter_sync(unsigned int sync_block_number); void enter_no_sync(); private: + typedef std::map ui_lut_t; unsigned long m_reg; enum { NO_SYNC, SYNC } m_sync; bool m_presync; @@ -44,12 +49,14 @@ private: unsigned char m_lastseenOffset; unsigned int m_blockBitCounter; unsigned int m_wrongBlocksCounter; + unsigned int m_correctedBlocksCounter; unsigned int m_blocksCounter; unsigned int m_groupGoodBlocksCounter; unsigned char m_blockNumber; bool m_groupAssemblyStarted; bool m_goodBlock; unsigned int m_group[4]; + ui_lut_t m_error_lut; /* see page 59, Annex C, table C.1 in the standard * offset word C' has been put at the end */