Browse Source

added QA file

tested bitslip detection
dev pre-lcl-refactor
Clemens Richter 9 years ago
parent
commit
ccb0263c85
  1. 40
      lib/rds_decoder_redsea_impl.cc
  2. 6
      lib/rds_decoder_redsea_impl.h
  3. 1
      python/CMakeLists.txt
  4. 41
      python/qa_rds_parser_table_qt.py
  5. 2
      python/rds_parser_table_qt.py

40
lib/rds_decoder_redsea_impl.cc

@ -30,6 +30,7 @@
#include "rds_decoder_redsea_impl.h" #include "rds_decoder_redsea_impl.h"
#include <map> #include <map>
#include <vector> #include <vector>
#include <bitset>
namespace gr { namespace gr {
namespace multirds { namespace multirds {
@ -100,6 +101,8 @@ void rds_decoder_redsea_impl::enter_sync(uint16_t sync_block_number) {
block_bit_counter = 0; block_bit_counter = 0;
block_number = (sync_block_number + 1) % 4; block_number = (sync_block_number + 1) % 4;
group_assembly_started = false; group_assembly_started = false;
last_pi =0x0000;
group_corrected_blocks_counter =0;
d_state = SYNC; d_state = SYNC;
} }
/* see Annex B, page 64 of the standard */ /* 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 // 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;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, 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++) { for (int shift=0; shift < 26; shift++) {
uint32_t errvec = ((e << shift) & kBitmask26); uint32_t errvec = ((e << shift) & kBitmask26);
uint16_t sy = calc_syndrome(errvec ^ offset_word[offset_num],26); 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) { if (kErrorLookup.count({(uint16_t)syndrome, (char)offset}) > 0) {
uint32_t err = kErrorLookup.at({(uint16_t)syndrome, (char)offset}); uint32_t err = kErrorLookup.at({(uint16_t)syndrome, (char)offset});
//dout << "correcting"<<std::endl; //dout << "correcting"<<std::endl;
//err=0;//correction disabled
corrected_block ^= err; corrected_block ^= err;
} }
return corrected_block; return corrected_block;
} }
@ -255,6 +260,7 @@ int rds_decoder_redsea_impl::work (int noutput_items,
else{//B else{//B
offset_char = 'c'; offset_char = 'c';
block_received_crc=checkword^offset_word[4]; block_received_crc=checkword^offset_word[4];
//dout<<"B"<<std::endl;
} }
if (block_received_crc==block_calculated_crc) { if (block_received_crc==block_calculated_crc) {
good_block=true; good_block=true;
@ -265,8 +271,11 @@ int rds_decoder_redsea_impl::work (int noutput_items,
good_block=true; good_block=true;
block_was_corrected=true; block_was_corrected=true;
group_corrected_blocks_counter++; group_corrected_blocks_counter++;
//wrong_blocks_counter++;
dataword=(corrected_block>>10) & 0xffff; dataword=(corrected_block>>10) & 0xffff;
checkword=corrected_block & 0x3ff; checkword=corrected_block & 0x3ff;
//dout << "corrected error"<<std::endl; //dout << "corrected error"<<std::endl;
}else { }else {
wrong_blocks_counter++; wrong_blocks_counter++;
@ -277,26 +286,42 @@ int rds_decoder_redsea_impl::work (int noutput_items,
} }
else { else {
block_received_crc=checkword^offset_word[block_number]; 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; good_block=true;
offset_char=expected_offset_char[block_number]; //expected_offset_char[]={'A','B','?','D'}; offset_char=expected_offset_char[block_number]; //expected_offset_char[]={'A','B','?','D'};
/*if (block_number==0) offset_char = 'A'; /*if (block_number==0) offset_char = 'A';
else if (block_number==1) offset_char = 'B'; else if (block_number==1) offset_char = 'B';
else if (block_number==3) offset_char = 'D';*/ else if (block_number==3) offset_char = 'D';*/
} else { } 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: //try correcting:
uint32_t corrected_block= correctBurstErrors(reg,expected_offset_char[block_number]); uint32_t corrected_block= correctBurstErrors(reg,expected_offset_char[block_number]);
if(corrected_block != reg) {//syndrome found in table == correction worked if(corrected_block != reg) {//syndrome found in table == correction worked
good_block=true; good_block=true;
block_was_corrected=true; block_was_corrected=true;
group_corrected_blocks_counter++; group_corrected_blocks_counter++;
//wrong_blocks_counter++;
dataword=(corrected_block>>10) & 0xffff; dataword=(corrected_block>>10) & 0xffff;
checkword=corrected_block & 0x3ff; checkword=corrected_block & 0x3ff;
//dout << "corrected error"<<std::endl; //dout << "corrected error"<<std::endl;
// dout << "old: 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_received_crc=checkword^offset_word[block_number];
// block_calculated_crc=calc_syndrome(dataword,16); // block_calculated_crc=calc_syndrome(dataword,16);
// dout << "new: rx:"<<block_received_crc<<"\tcalc:"<<block_calculated_crc<<std::endl; // dout << "new: rx:"<<block_received_crc<<"\tcalc:"<<block_calculated_crc<<std::endl;
offset_char=expected_offset_char[block_number]; offset_char=expected_offset_char[block_number];
} }
else{ 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 if (block_number==1 && good_block) {//2nd block - > read group type variant
variant=(dataword>>11)& 0x1; variant=(dataword>>11)& 0x1;
// uint8_t group=(dataword>>12)& 0xf; uint8_t group=(dataword>>12)& 0xf;
// dout << "group:"<< unsigned(group); // dout << "group:"<<std::setw(2)<< unsigned(group);
// dout << "\tvariant:" << unsigned(variant); // //dout << "\tvariant:" << unsigned(variant);
// if (variant==0)
// dout << "A";
// else
// dout << "B";
// //dout << "\tvariant:" << unsigned(variant);
// dout << "\twas_corrected: "<<block_was_corrected<< std::endl; // dout << "\twas_corrected: "<<block_was_corrected<< std::endl;
} }

6
lib/rds_decoder_redsea_impl.h

@ -55,11 +55,13 @@ private:
bool log; bool log;
bool presync; bool presync;
bool good_block; bool good_block;
bool block_was_corrected; bool block_was_corrected;
uint8_t group_corrected_blocks_counter; uint8_t group_corrected_blocks_counter;
bool group_assembly_started;
uint8_t variant; uint8_t variant;
uint16_t last_pi;
bool group_assembly_started;
uint8_t last_wrong_blocks_counter; uint8_t last_wrong_blocks_counter;
uint8_t lastseen_offset; uint8_t lastseen_offset;
uint8_t block_number; uint8_t block_number;

1
python/CMakeLists.txt

@ -53,3 +53,4 @@ include(GrTest)
set(GR_TEST_TARGET_DEPS gnuradio-multirds) set(GR_TEST_TARGET_DEPS gnuradio-multirds)
set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig) set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig)
GR_ADD_TEST(qa_rds_parser_table_qt ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_rds_parser_table_qt.py)

41
python/qa_rds_parser_table_qt.py

@ -0,0 +1,41 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2017 <+YOU OR YOUR COMPANY+>.
#
# This 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; either version 3, or (at your option)
# any later version.
#
# This software 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 for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
from gnuradio import gr, gr_unittest
from gnuradio import blocks
from rds_parser_table_qt import rds_parser_table_qt
class qa_rds_parser_table_qt (gr_unittest.TestCase):
def setUp (self):
self.tb = gr.top_block ()
def tearDown (self):
self.tb = None
def test_001_t (self):
# set up fg
self.tb.run ()
# check data
if __name__ == '__main__':
gr_unittest.run(qa_rds_parser_table_qt, "qa_rds_parser_table_qt.xml")

2
python/rds_parser_table_qt.py

@ -1272,7 +1272,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
#self.tableobj.decoders[port]['PI'] #self.tableobj.decoders[port]['PI']
inport=pmt.from_long(port) inport=pmt.from_long(port)
outport=pmt.from_long(audio_channel) outport=pmt.from_long(audio_channel)
print("sending chan:%i"%audio_channel) #print("sending chan:%i"%audio_channel)
send_pmt=pmt.cons(inport, outport) #make PDU: (metadata, data) pair send_pmt=pmt.cons(inport, outport) #make PDU: (metadata, data) pair
self.tableobj.message_port_pub(pmt.intern('ctrl'), send_pmt) self.tableobj.message_port_pub(pmt.intern('ctrl'), send_pmt)

Loading…
Cancel
Save