|
|
|
|
@ -30,6 +30,7 @@
|
|
|
|
|
#include "rds_decoder_redsea_impl.h" |
|
|
|
|
#include <map> |
|
|
|
|
#include <vector> |
|
|
|
|
#include <bitset> |
|
|
|
|
|
|
|
|
|
namespace gr { |
|
|
|
|
namespace multirds { |
|
|
|
|
@ -100,6 +101,8 @@ void rds_decoder_redsea_impl::enter_sync(uint16_t sync_block_number) {
|
|
|
|
|
block_bit_counter = 0; |
|
|
|
|
block_number = (sync_block_number + 1) % 4; |
|
|
|
|
group_assembly_started = false; |
|
|
|
|
last_pi =0x0000; |
|
|
|
|
group_corrected_blocks_counter =0; |
|
|
|
|
d_state = SYNC; |
|
|
|
|
} |
|
|
|
|
/* see Annex B, page 64 of the standard */ |
|
|
|
|
@ -137,7 +140,7 @@ static const char * const offset_name[]={"A","B","C","D","c"};*/
|
|
|
|
|
// Kopitz & Marks 1999: "RDS: The Radio Data System", p. 224
|
|
|
|
|
//for (uint32_t e=0x1;e <= 0x3;e+=0x2) {//for (uint32_t e : {0x1, 0x3}) {
|
|
|
|
|
//for (uint32_t e : {0x1, 0x3, 0x7,0x15,0x31}) {//fix up to 5 bit burst errors (as code should support)
|
|
|
|
|
for (uint32_t e : {0x1, 0x3}) {//fix up to 2 bit burst errors (as book says)
|
|
|
|
|
for (uint32_t e : {0x1,0x3}) {//fix up to 2-bit burst errors (as book says)
|
|
|
|
|
for (int shift=0; shift < 26; shift++) { |
|
|
|
|
uint32_t errvec = ((e << shift) & kBitmask26); |
|
|
|
|
uint16_t sy = calc_syndrome(errvec ^ offset_word[offset_num],26); |
|
|
|
|
@ -157,7 +160,9 @@ uint32_t rds_decoder_redsea_impl::correctBurstErrors(uint32_t block, char offset
|
|
|
|
|
if (kErrorLookup.count({(uint16_t)syndrome, (char)offset}) > 0) { |
|
|
|
|
uint32_t err = kErrorLookup.at({(uint16_t)syndrome, (char)offset}); |
|
|
|
|
//dout << "correcting"<<std::endl;
|
|
|
|
|
//err=0;//correction disabled
|
|
|
|
|
corrected_block ^= err; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
return corrected_block; |
|
|
|
|
} |
|
|
|
|
@ -255,6 +260,7 @@ int rds_decoder_redsea_impl::work (int noutput_items,
|
|
|
|
|
else{//B
|
|
|
|
|
offset_char = 'c'; |
|
|
|
|
block_received_crc=checkword^offset_word[4]; |
|
|
|
|
//dout<<"B"<<std::endl;
|
|
|
|
|
} |
|
|
|
|
if (block_received_crc==block_calculated_crc) { |
|
|
|
|
good_block=true; |
|
|
|
|
@ -265,8 +271,11 @@ int rds_decoder_redsea_impl::work (int noutput_items,
|
|
|
|
|
good_block=true; |
|
|
|
|
block_was_corrected=true; |
|
|
|
|
group_corrected_blocks_counter++; |
|
|
|
|
//wrong_blocks_counter++;
|
|
|
|
|
dataword=(corrected_block>>10) & 0xffff; |
|
|
|
|
checkword=corrected_block & 0x3ff; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//dout << "corrected error"<<std::endl;
|
|
|
|
|
}else { |
|
|
|
|
wrong_blocks_counter++; |
|
|
|
|
@ -277,26 +286,42 @@ int rds_decoder_redsea_impl::work (int noutput_items,
|
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
block_received_crc=checkword^offset_word[block_number]; |
|
|
|
|
if (block_received_crc==block_calculated_crc) { |
|
|
|
|
if (block_received_crc==block_calculated_crc) {//valid block
|
|
|
|
|
if (block_number==0) |
|
|
|
|
last_pi=dataword; |
|
|
|
|
good_block=true; |
|
|
|
|
offset_char=expected_offset_char[block_number]; //expected_offset_char[]={'A','B','?','D'};
|
|
|
|
|
/*if (block_number==0) offset_char = 'A';
|
|
|
|
|
else if (block_number==1) offset_char = 'B'; |
|
|
|
|
else if (block_number==3) offset_char = 'D';*/ |
|
|
|
|
} else { |
|
|
|
|
//detect clock slip
|
|
|
|
|
if (block_number==0 && last_pi!=0x000){//if PI was received earlier
|
|
|
|
|
uint16_t diff=dataword^(last_pi>>1); |
|
|
|
|
uint16_t diff2=(dataword>>1)^(last_pi); |
|
|
|
|
unsigned int num_diff_bits = std::bitset<16>(diff).count(); |
|
|
|
|
unsigned int num_diff_bits2 = std::bitset<16>(diff2).count(); |
|
|
|
|
if (num_diff_bits<2 or num_diff_bits2<2){ |
|
|
|
|
dout << "clockslip detection:"<<std::endl; |
|
|
|
|
dout << "dataword:"<<std::bitset<16>(dataword)<<"\tlast_pi:"<<std::bitset<16>(last_pi)<<std::endl; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
//try correcting:
|
|
|
|
|
uint32_t corrected_block= correctBurstErrors(reg,expected_offset_char[block_number]); |
|
|
|
|
if(corrected_block != reg) {//syndrome found in table == correction worked
|
|
|
|
|
good_block=true; |
|
|
|
|
block_was_corrected=true; |
|
|
|
|
group_corrected_blocks_counter++; |
|
|
|
|
//wrong_blocks_counter++;
|
|
|
|
|
dataword=(corrected_block>>10) & 0xffff; |
|
|
|
|
checkword=corrected_block & 0x3ff; |
|
|
|
|
|
|
|
|
|
//dout << "corrected error"<<std::endl;
|
|
|
|
|
//dout << "old: rx:"<<block_received_crc<<"\tcalc:"<<block_calculated_crc<<std::endl;
|
|
|
|
|
//block_received_crc=checkword^offset_word[block_number];
|
|
|
|
|
//block_calculated_crc=calc_syndrome(dataword,16);
|
|
|
|
|
//dout << "new: rx:"<<block_received_crc<<"\tcalc:"<<block_calculated_crc<<std::endl;
|
|
|
|
|
// dout << "old: rx:"<<block_received_crc<<"\tcalc:"<<block_calculated_crc<<std::endl;
|
|
|
|
|
// block_received_crc=checkword^offset_word[block_number];
|
|
|
|
|
// block_calculated_crc=calc_syndrome(dataword,16);
|
|
|
|
|
// dout << "new: rx:"<<block_received_crc<<"\tcalc:"<<block_calculated_crc<<std::endl;
|
|
|
|
|
|
|
|
|
|
offset_char=expected_offset_char[block_number]; |
|
|
|
|
} |
|
|
|
|
else{ |
|
|
|
|
@ -315,9 +340,14 @@ int rds_decoder_redsea_impl::work (int noutput_items,
|
|
|
|
|
} |
|
|
|
|
if (block_number==1 && good_block) {//2nd block - > read group type variant
|
|
|
|
|
variant=(dataword>>11)& 0x1; |
|
|
|
|
// uint8_t group=(dataword>>12)& 0xf;
|
|
|
|
|
// dout << "group:"<< unsigned(group);
|
|
|
|
|
// dout << "\tvariant:" << unsigned(variant);
|
|
|
|
|
uint8_t group=(dataword>>12)& 0xf; |
|
|
|
|
// dout << "group:"<<std::setw(2)<< unsigned(group);
|
|
|
|
|
// //dout << "\tvariant:" << unsigned(variant);
|
|
|
|
|
// if (variant==0)
|
|
|
|
|
// dout << "A";
|
|
|
|
|
// else
|
|
|
|
|
// dout << "B";
|
|
|
|
|
// //dout << "\tvariant:" << unsigned(variant);
|
|
|
|
|
// dout << "\twas_corrected: "<<block_was_corrected<< std::endl;
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|