From b5af9b2f804d678c9e59fcc6067068062d134cf1 Mon Sep 17 00:00:00 2001 From: csrichter Date: Fri, 7 Apr 2017 09:00:43 +0200 Subject: [PATCH] decoder: added burst error correction from redsea (untestedgit add -A) --- grc/crfa_rds_decoder_redsea.xml | 2 +- lib/constants.h | 4 +- lib/rds_decoder_impl.cc | 1 + lib/rds_decoder_redsea_impl.cc | 179 ++++++++++++++++---------------- lib/rds_decoder_redsea_impl.h | 32 +++--- python/rds_parser_table_qt.py | 2 +- 6 files changed, 114 insertions(+), 106 deletions(-) diff --git a/grc/crfa_rds_decoder_redsea.xml b/grc/crfa_rds_decoder_redsea.xml index ddcd19d..c51b2e5 100644 --- a/grc/crfa_rds_decoder_redsea.xml +++ b/grc/crfa_rds_decoder_redsea.xml @@ -4,7 +4,7 @@ crfa_rds_decoder_redsea [crfa] import crfa - crfa.rds_decoder($log, $debug) + crfa.rds_decoder_redsea($log, $debug) Log log diff --git a/lib/constants.h b/lib/constants.h index cb1f85c..d41f330 100644 --- a/lib/constants.h +++ b/lib/constants.h @@ -25,7 +25,9 @@ static const unsigned int offset_pos[5]={0,1,2,3,2}; static const unsigned int offset_word[5]={252,408,360,436,848}; static const unsigned int syndrome[5]={383,14,303,663,748}; -static const char * const offset_name[]={"A","B","C","D","C'"}; +//static const char * const offset_name[]={"A","B","C","D","C'"}; +static const char offset_name[]={'A','B','C','D','c'}; +static const char expected_offset_char[]={'A','B','X','D'}; /* Annex F of RBDS Standard Table F.1 (North America) and * Table F.2 (Europe) */ diff --git a/lib/rds_decoder_impl.cc b/lib/rds_decoder_impl.cc index 650b9d7..aadf6db 100644 --- a/lib/rds_decoder_impl.cc +++ b/lib/rds_decoder_impl.cc @@ -54,6 +54,7 @@ namespace gr { set_output_multiple(104); // 1 RDS datagroup = 104 bits message_port_register_out(pmt::mp("out")); enter_no_sync(); + std::cout <<"i am old"<, uint32_t> kErrorLookup = makeErrorLookupTable(); + + std::cout<< "i am new"<< std::endl; + std::cout<< kErrorLookup.at({704, 'A'})<< std::endl; } /* @@ -75,7 +79,7 @@ void rds_decoder_redsea_impl::enter_no_sync() { d_state = NO_SYNC; } -void rds_decoder_redsea_impl::enter_sync(unsigned int sync_block_number) { +void rds_decoder_redsea_impl::enter_sync(uint16_t sync_block_number) { pmt::pmt_t data(pmt::PMT_T); //pmt::pmt_t meta(pmt::PMT_NIL); pmt::pmt_t meta(pmt::from_long(1)); @@ -89,14 +93,12 @@ void rds_decoder_redsea_impl::enter_sync(unsigned int sync_block_number) { group_assembly_started = false; d_state = SYNC; } - /* see Annex B, page 64 of the standard */ -unsigned int rds_decoder_redsea_impl::calc_syndrome(unsigned long message, - unsigned char mlen) { - unsigned long reg = 0; - unsigned int i; - const unsigned long poly = 0x5B9; - const unsigned char plen = 10; +uint16_t rds_decoder_redsea_impl::calc_syndrome(uint32_t message,uint8_t mlen) { + uint32_t reg = 0; + uint16_t i; + const uint32_t poly = 0x5B9; + const uint8_t plen = 10; for (i = mlen; i > 0; i--) { reg = (reg << 1) | ((message >> (i-1)) & 0x01); @@ -109,10 +111,51 @@ unsigned int rds_decoder_redsea_impl::calc_syndrome(unsigned long message, return (reg & ((1<, uint32_t> rds_decoder_redsea_impl::makeErrorLookupTable() { + std::map, uint32_t> result; +/*static const unsigned int offset_pos[5]={0,1,2,3,2}; +static const unsigned int offset_word[5]={252,408,360,436,848}; +static const unsigned int syndrome[5]={383,14,303,663,748}; +static const char * const offset_name[]={"A","B","C","D","c"};*/ +dout << "constructing error lookup table"<(errvec) < 0) { + uint32_t err = kErrorLookup.at({syndrome, offset}); + dout << "correcting"<> 8U) & 0xffU; @@ -143,19 +186,19 @@ int rds_decoder_redsea_impl::work (int noutput_items, { const bool *in = (const bool *) input_items[0]; - dout << "RDS data decoder at work: input_items = " + /*dout << "RDS data decoder at work: input_items = " << noutput_items << ", /104 = " - << noutput_items / 104 << std::endl; + << noutput_items / 104 << std::endl;*/ int i=0,j; - unsigned long bit_distance, block_distance; - unsigned int block_calculated_crc, block_received_crc, checkword,dataword; - unsigned int reg_syndrome; - unsigned char offset_char('x'); // x = error while decoding the word offset + uint32_t bit_distance, block_distance; + uint16_t block_calculated_crc, block_received_crc, checkword,dataword; + uint16_t reg_syndrome; + uint8_t offset_char('x'); // x = error while decoding the word offset /* the synchronization process is described in Annex C, page 66 of the standard */ while (i> 10; - - received_offset_ = offsetForSyndrome(calcSyndrome(block)); - - if (!acquireSync()) - continue; - - block_counter_++; - bool was_valid_word = true; - - if (expected_offset_ == OFFSET_C && received_offset_ == OFFSET_CI) - expected_offset_ = OFFSET_CI; - - block_has_errors_[block_counter_ % block_has_errors_.size()] = false; - - if (received_offset_ != expected_offset_) { - block_has_errors_[block_counter_ % block_has_errors_.size()] = true; - - was_valid_word = false; - - // Detect & correct clock slips (Section C.1.2) - if (expected_offset_ == OFFSET_A && pi_ != 0 && - ((wideblock_ >> 12) & kBitmask16) == pi_) { - message = pi_; - wideblock_ >>= 1; - received_offset_ = OFFSET_A; - } else if (expected_offset_ == OFFSET_A && pi_ != 0 && - ((wideblock_ >> 10) & kBitmask16) == pi_) { - message = pi_; - wideblock_ = (wideblock_ << 1) + getNextBit(); - received_offset_ = OFFSET_A; - left_to_read_ = 25; - } else { - uint32_t corrected_block = correctBurstErrors(block, expected_offset_); - if (corrected_block != block) { - message = corrected_block >> 10; - received_offset_ = expected_offset_; - } - } - - // Still no valid syndrome - if (received_offset_ != expected_offset_) - uncorrectable(); - } - - // Error-free block received - - if (received_offset_ == expected_offset_) { - if (expected_offset_ == OFFSET_CI) - group.setCI(message); - else - group.set(block_number_for_offset[expected_offset_], message); - - if (group.hasPi()) - pi_ = group.pi(); - } - - expected_offset_ = nextOffsetFor(expected_offset_); - - if (expected_offset_ == OFFSET_A) { - break; - }*/ good_block=false; dataword=(reg>>10) & 0xffff;//data part of received block (upper 16 bits) block_calculated_crc=calc_syndrome(dataword,16); @@ -261,13 +241,24 @@ int rds_decoder_redsea_impl::work (int noutput_items, good_block=true; offset_char = 'C'; } else { - block_received_crc=checkword^offset_word[4]; - if (block_received_crc==block_calculated_crc) { - good_block=true; - offset_char = 'c'; // C' (C-Tag) - } else { - wrong_blocks_counter++; - good_block=false; + //try correcting: + uint32_t corrected_block= correctBurstErrors(reg,'C'); + if(corrected_block != reg){ + good_block=true; + dataword=(corrected_block>>10) & 0xffff; + checkword=corrected_block & 0x3ff; + offset_char = 'C'; + lout << "corrected error"<>10) & 0xffff; + checkword=corrected_block & 0x3ff; + lout << "corrected error"<, uint32_t> kErrorLookup; enum { NO_SYNC, SYNC } d_state; //below copied from redsea enum eOffset { OFFSET_A, OFFSET_B, OFFSET_C, OFFSET_CI, OFFSET_D, OFFSET_INVALID } ; + std::map, uint32_t> makeErrorLookupTable(); uint32_t calcSyndrome(uint32_t vec); eOffset offsetForSyndrome(uint16_t syndrome); eOffset nextOffsetFor(eOffset o); - uint32_t correctBurstErrors(uint32_t block, eOffset offset); + uint32_t correctBurstErrors(uint32_t block, char offset); }; diff --git a/python/rds_parser_table_qt.py b/python/rds_parser_table_qt.py index 31558b2..2d18c77 100644 --- a/python/rds_parser_table_qt.py +++ b/python/rds_parser_table_qt.py @@ -471,7 +471,7 @@ class tmc_message: else: print(offset_loc) offset_loc_name="###INVALID###" - templates={"de_1":"{A}, {B} in Richtung {C}"#codeing handbook: zwischen {D} und {E}, sprachdurchsagen: zwischen {E} und {D} + templates={"de_1":"{A}, {B} in Richtung {C}"#coding handbook: zwischen {D} und {E}, sprachdurchsagen(manchmal): zwischen {E} und {D} TODO: swap D and E if offset-dir negative ,"de_2a":", zwischen {D} und {E}" ,"de_2b":", bei {D}"#extent==0 ,"en_1":"{A}, {B} {C}"