From bbd8b06aaabc6488300076f5e1d0e9e565623825 Mon Sep 17 00:00:00 2001
From: csrichter
Date: Sat, 18 Mar 2017 11:49:40 +0100
Subject: [PATCH] completed EBU carset, fixed mapstring+psn unicode error,
added PI region info, experimented with redsea decoder
---
grc/CMakeLists.txt | 3 +-
grc/crfa_rds_decoder_redsea.xml | 45 ++++
include/crfa/CMakeLists.txt | 3 +-
include/crfa/rds_decoder_redsea.h | 56 +++++
lib/CMakeLists.txt | 3 +-
lib/rds_decoder_impl.cc | 6 +-
lib/rds_decoder_impl.h | 9 +
lib/rds_decoder_redsea_impl.cc | 334 ++++++++++++++++++++++++++++++
lib/rds_decoder_redsea_impl.h | 79 +++++++
python/rds_parser_table_qt.py | 112 ++++++----
swig/crfa_swig.i | 3 +
11 files changed, 608 insertions(+), 45 deletions(-)
create mode 100644 grc/crfa_rds_decoder_redsea.xml
create mode 100644 include/crfa/rds_decoder_redsea.h
create mode 100644 lib/rds_decoder_redsea_impl.cc
create mode 100644 lib/rds_decoder_redsea_impl.h
diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt
index eec0d11..e931ab7 100644
--- a/grc/CMakeLists.txt
+++ b/grc/CMakeLists.txt
@@ -28,5 +28,6 @@ install(FILES
crfa_vector_cutter.xml
crfa_decoder_compare.xml
crfa_diff_add_sync_decim.xml
- crfa_sync_decim.xml DESTINATION share/gnuradio/grc/blocks
+ crfa_sync_decim.xml
+ crfa_rds_decoder_redsea.xml DESTINATION share/gnuradio/grc/blocks
)
diff --git a/grc/crfa_rds_decoder_redsea.xml b/grc/crfa_rds_decoder_redsea.xml
new file mode 100644
index 0000000..ddcd19d
--- /dev/null
+++ b/grc/crfa_rds_decoder_redsea.xml
@@ -0,0 +1,45 @@
+
+
+ RDS Decoder (redsea)
+ crfa_rds_decoder_redsea
+ [crfa]
+ import crfa
+ crfa.rds_decoder($log, $debug)
+
+ Log
+ log
+ False
+ bool
+
+ Enable
+ True
+
+
+ Disable
+ False
+
+
+
+ Debug
+ debug
+ False
+ bool
+
+ Enable
+ True
+
+
+ Disable
+ False
+
+
+
+ in
+ byte
+
+
+ out
+ message
+ 1
+
+
diff --git a/include/crfa/CMakeLists.txt b/include/crfa/CMakeLists.txt
index 80deb04..505fbbd 100644
--- a/include/crfa/CMakeLists.txt
+++ b/include/crfa/CMakeLists.txt
@@ -24,5 +24,6 @@ install(FILES
api.h
rds_decoder.h
diff_add_sync_decim.h
- sync_decim.h DESTINATION include/crfa
+ sync_decim.h
+ rds_decoder_redsea.h DESTINATION include/crfa
)
diff --git a/include/crfa/rds_decoder_redsea.h b/include/crfa/rds_decoder_redsea.h
new file mode 100644
index 0000000..05b52ab
--- /dev/null
+++ b/include/crfa/rds_decoder_redsea.h
@@ -0,0 +1,56 @@
+/* -*- c++ -*- */
+/*
+ * 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.
+ */
+
+
+#ifndef INCLUDED_CRFA_RDS_DECODER_REDSEA_H
+#define INCLUDED_CRFA_RDS_DECODER_REDSEA_H
+
+#include
+#include
+
+namespace gr {
+ namespace crfa {
+
+ /*!
+ * \brief <+description of block+>
+ * \ingroup crfa
+ *
+ */
+ class CRFA_API rds_decoder_redsea : virtual public gr::sync_block
+ {
+ public:
+ typedef boost::shared_ptr sptr;
+
+ /*!
+ * \brief Return a shared_ptr to a new instance of crfa::rds_decoder_redsea.
+ *
+ * To avoid accidental use of raw pointers, crfa::rds_decoder_redsea's
+ * constructor is in a private implementation
+ * class. crfa::rds_decoder_redsea::make is the public interface for
+ * creating new instances.
+ */
+ static sptr make(bool log,bool debug);
+ };
+
+ } // namespace crfa
+} // namespace gr
+
+#endif /* INCLUDED_CRFA_RDS_DECODER_REDSEA_H */
+
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 91f8e20..022c609 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -27,7 +27,8 @@ link_directories(${Boost_LIBRARY_DIRS})
list(APPEND crfa_sources
rds_decoder_impl.cc
diff_add_sync_decim_impl.cc
- sync_decim_impl.cc )
+ sync_decim_impl.cc
+ rds_decoder_redsea_impl.cc )
set(crfa_sources "${crfa_sources}" PARENT_SCOPE)
if(NOT crfa_sources)
diff --git a/lib/rds_decoder_impl.cc b/lib/rds_decoder_impl.cc
index 259d287..650b9d7 100644
--- a/lib/rds_decoder_impl.cc
+++ b/lib/rds_decoder_impl.cc
@@ -28,6 +28,8 @@
#include
#include "constants.h"
#include "rds_decoder_impl.h"
+#include
+#include
namespace gr {
namespace crfa {
@@ -260,7 +262,9 @@ int rds_decoder_impl::work (int noutput_items,
bit_counter++;
}
return noutput_items;
- }/*work function*/
+ }/*end of work function*/
+
+
} /* namespace crfa */
} /* namespace gr */
diff --git a/lib/rds_decoder_impl.h b/lib/rds_decoder_impl.h
index 2fa36a3..6270b57 100644
--- a/lib/rds_decoder_impl.h
+++ b/lib/rds_decoder_impl.h
@@ -60,6 +60,15 @@ private:
unsigned char lastseen_offset;
unsigned char block_number;
enum { NO_SYNC, SYNC } d_state;
+ /*//below copied from redsea
+ enum eOffset {
+ OFFSET_A, OFFSET_B, OFFSET_C, OFFSET_CI, OFFSET_D, OFFSET_INVALID
+ } ;
+ uint32_t calcSyndrome(uint32_t vec);
+ eOffset offsetForSyndrome(uint16_t syndrome);
+ eOffset nextOffsetFor(eOffset o);
+ uint32_t correctBurstErrors(uint32_t block, eOffset offset);*/
+
};
diff --git a/lib/rds_decoder_redsea_impl.cc b/lib/rds_decoder_redsea_impl.cc
new file mode 100644
index 0000000..dca4a41
--- /dev/null
+++ b/lib/rds_decoder_redsea_impl.cc
@@ -0,0 +1,334 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 <+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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define dout debug && std::cout
+#define lout log && std::cout
+
+#include
+#include "constants.h"
+#include "rds_decoder_redsea_impl.h"
+#include
+#include
+
+namespace gr {
+ namespace crfa {
+
+ rds_decoder_redsea::sptr
+ rds_decoder_redsea::make(bool log, bool debug)
+ {
+ return gnuradio::get_initial_sptr
+ (new rds_decoder_redsea_impl(log, debug));
+ }
+
+ /*
+ * The private constructor
+ */
+ rds_decoder_redsea_impl::rds_decoder_redsea_impl(bool log, bool debug)
+ : gr::sync_block("rds_decoder_redsea",
+ gr::io_signature::make (1, 1, sizeof(char)),
+ gr::io_signature::make (0, 0, 0)),
+ log(log),
+ debug(debug)
+{
+ set_output_multiple(104); // 1 RDS datagroup = 104 bits
+ message_port_register_out(pmt::mp("out"));
+ enter_no_sync();
+}
+
+ /*
+ * Our virtual destructor.
+ */
+ rds_decoder_redsea_impl::~rds_decoder_redsea_impl()
+ {
+ }
+
+////////////////////////// HELPER FUNTIONS /////////////////////////
+
+void rds_decoder_redsea_impl::enter_no_sync() {
+ pmt::pmt_t data(pmt::PMT_F);
+ //pmt::pmt_t meta(pmt::PMT_NIL);
+ pmt::pmt_t meta(pmt::from_long(1));
+ pmt::pmt_t pdu(pmt::cons(meta, data)); // make PDU: (metadata, data) pair
+ message_port_pub(pmt::mp("out"), pdu);
+ presync = false;
+ d_state = NO_SYNC;
+}
+
+void rds_decoder_redsea_impl::enter_sync(unsigned int 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));
+ pmt::pmt_t pdu(pmt::cons(meta, data)); // make PDU: (metadata, data) pair
+ message_port_pub(pmt::mp("out"), pdu);
+ last_wrong_blocks_counter = 0;
+ wrong_blocks_counter = 0;
+ blocks_counter = 0;
+ block_bit_counter = 0;
+ block_number = (sync_block_number + 1) % 4;
+ 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;
+
+ for (i = mlen; i > 0; i--) {
+ reg = (reg << 1) | ((message >> (i-1)) & 0x01);
+ if (reg & (1 << plen)) reg = reg ^ poly;
+ }
+ for (i = plen; i > 0; i--) {
+ reg = reg << 1;
+ if (reg & (1<> 8U) & 0xffU;
+ bytes[1] = (group[0] ) & 0xffU;
+ bytes[2] = (group[1] >> 8U) & 0xffU;
+ bytes[3] = (group[1] ) & 0xffU;
+ bytes[4] = (group[2] >> 8U) & 0xffU;
+ bytes[5] = (group[2] ) & 0xffU;
+ bytes[6] = (group[3] >> 8U) & 0xffU;
+ bytes[7] = (group[3] ) & 0xffU;
+
+ // RDS offset words
+ bytes[8] = offset_chars[0];
+ bytes[9] = offset_chars[1];
+ bytes[10] = offset_chars[2];
+ bytes[11] = offset_chars[3];
+ bytes[12]=last_wrong_blocks_counter;
+ pmt::pmt_t data(pmt::make_blob(bytes, 13));
+ //pmt::pmt_t meta(pmt::PMT_NIL);
+ pmt::pmt_t meta(pmt::from_long(0));
+ pmt::pmt_t pdu(pmt::cons(meta, data)); // make PDU: (metadata, data) pair
+ message_port_pub(pmt::mp("out"), pdu);
+}
+//work function
+int rds_decoder_redsea_impl::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const bool *in = (const bool *) input_items[0];
+
+ dout << "RDS data decoder at work: input_items = "
+ << noutput_items << ", /104 = "
+ << 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
+
+/* the synchronization process is described in Annex C, page 66 of the standard */
+ while (i=offset_pos[j])
+ block_distance=offset_pos[j]+4-offset_pos[lastseen_offset];
+ else
+ block_distance=offset_pos[j]-offset_pos[lastseen_offset];
+ if ((block_distance*26)!=bit_distance) presync=false;
+ else {
+ lout << "@@@@@ Sync State Detected" << std::endl;
+ enter_sync(j);
+ }
+ }
+ break; //syndrome found, no more cycles
+ }
+ }
+ break;
+ case SYNC:
+/* wait until 26 bits enter the buffer */
+ if (block_bit_counter<25) block_bit_counter++;
+ else {
+ /*uint32_t block = reg;
+ uint16_t message = block >> 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);
+
+ checkword=reg & 0x3ff;//checkword part of received block (lower 10 bits)
+/* manage special case of C or C' offset word */
+ if (block_number==2) {
+ block_received_crc=checkword^offset_word[block_number];
+ if (block_received_crc==block_calculated_crc) {
+ 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;
+ }
+ }
+ }
+ else {
+ block_received_crc=checkword^offset_word[block_number];
+ if (block_received_crc==block_calculated_crc) {
+ good_block=true;
+ if (block_number==0) offset_char = 'A';
+ else if (block_number==1) offset_char = 'B';
+ else if (block_number==3) offset_char = 'D';
+ } else {
+ wrong_blocks_counter++;
+ good_block=false;
+ }
+ }
+/* done checking CRC */
+ if (block_number==0 && good_block) {
+ group_assembly_started=true;
+ group_good_blocks_counter=1;
+ }
+ if (group_assembly_started) {
+ if (!good_block) group_assembly_started=false;
+ else {
+ group[block_number]=dataword;
+ offset_chars[block_number] = offset_char;
+ group_good_blocks_counter++;
+ }
+ if (group_good_blocks_counter==5) decode_group(group);
+ }
+ block_bit_counter=0;
+ block_number=(block_number+1) % 4;
+ blocks_counter++;
+/* 1187.5 bps / 104 bits = 11.4 groups/sec, or 45.7 blocks/sec */
+ if (blocks_counter==50) {
+ last_wrong_blocks_counter=wrong_blocks_counter;
+ if (wrong_blocks_counter>35) {
+ lout << "@@@@@ Lost Sync (Got " << wrong_blocks_counter
+ << " bad blocks on " << blocks_counter
+ << " total)" << std::endl;
+ enter_no_sync();
+ } else {
+ lout << "@@@@@ Still Sync-ed (Got " << wrong_blocks_counter
+ << " bad blocks on " << blocks_counter
+ << " total)" << std::endl;
+ }
+ blocks_counter=0;
+ wrong_blocks_counter=0;
+ }
+ }
+ break;
+ default:
+ d_state=NO_SYNC;
+ break;
+ }
+ i++;
+ bit_counter++;
+ }
+ return noutput_items;
+ }/*end of work function*/
+
+
+ } /* namespace crfa */
+} /* namespace gr */
+
diff --git a/lib/rds_decoder_redsea_impl.h b/lib/rds_decoder_redsea_impl.h
new file mode 100644
index 0000000..252f37f
--- /dev/null
+++ b/lib/rds_decoder_redsea_impl.h
@@ -0,0 +1,79 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 <+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.
+ */
+
+#ifndef INCLUDED_CRFA_RDS_DECODER_IMPL_H
+#define INCLUDED_CRFA_RDS_DECODER_IMPL_H
+
+#include
+
+namespace gr {
+ namespace crfa {
+
+ class rds_decoder_redsea_impl : public rds_decoder_redsea
+ {
+public:
+ rds_decoder_redsea_impl(bool log, bool debug);
+
+private:
+ ~rds_decoder_redsea_impl();
+
+ // Where all the action really happens
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ void enter_no_sync();
+ void enter_sync(unsigned int);
+ unsigned int calc_syndrome(unsigned long, unsigned char);
+ void decode_group(unsigned int*);
+
+ unsigned long bit_counter;
+ unsigned long lastseen_offset_counter, reg;
+ unsigned int block_bit_counter;
+ unsigned int wrong_blocks_counter;
+ unsigned int blocks_counter;
+ unsigned int group_good_blocks_counter;
+ unsigned int group[4];
+ unsigned char offset_chars[4]; // [ABCcDEx] (x=error)
+ bool debug;
+ bool log;
+ bool presync;
+ bool good_block;
+ bool group_assembly_started;
+ unsigned char last_wrong_blocks_counter;
+ unsigned char lastseen_offset;
+ unsigned char block_number;
+ enum { NO_SYNC, SYNC } d_state;
+ //below copied from redsea
+ enum eOffset {
+ OFFSET_A, OFFSET_B, OFFSET_C, OFFSET_CI, OFFSET_D, OFFSET_INVALID
+ } ;
+ uint32_t calcSyndrome(uint32_t vec);
+ eOffset offsetForSyndrome(uint16_t syndrome);
+ eOffset nextOffsetFor(eOffset o);
+ uint32_t correctBurstErrors(uint32_t block, eOffset offset);
+
+
+ };
+
+ } // namespace crfa
+} // namespace gr
+
+#endif /* INCLUDED_CRFA_RDS_DECODER_IMPL_H */
+
diff --git a/python/rds_parser_table_qt.py b/python/rds_parser_table_qt.py
index 74d7033..1f92c06 100644
--- a/python/rds_parser_table_qt.py
+++ b/python/rds_parser_table_qt.py
@@ -320,34 +320,39 @@ class tmc_dict:
return retStr
def getMarkerString(self):
markerstring=""
- for lcn in self.messages:
- loc=None
- endloc=None
- map_tag=''
- for updateClass in self.messages[lcn]:
- message=self.messages[lcn][updateClass]
- if message.cancellation_time==None:
- color="black"
- else:
- color="gray"
- if message.location.has_koord:
- if loc==None:#first message at this location
- map_tag+='
'
- map_tag+=message.location_text()
- map_tag+=' '
- if message.cancellation_time==None:
- endloc=message.end_loc()#line displays length of 1st message (lowest class), that is not cancelled
- loc=message.location
- map_tag+=''%color
- map_tag+=message.map_string()
- map_tag+=' '
- map_tag+='
'
- map_tag+='
'
- if not loc==None:
- if endloc==None or not endloc.is_valid:
- endloc=loc#creates line of 0 length (dot)
- markerstring+=tmc_dict.marker_template.format(loc=loc.koord_str_google,text=map_tag,endloc=endloc.koord_str_google)
- markerstring+="\n"
+ try:
+ for lcn in self.messages:
+ loc=None
+ endloc=None
+ map_tag=''
+ for updateClass in self.messages[lcn]:
+ message=self.messages[lcn][updateClass]
+ if message.cancellation_time==None:
+ color="black"
+ else:
+ color="gray"
+ if message.location.has_koord:
+ if loc==None:#first message at this location
+ map_tag+='
'
+ map_tag+=message.location_text()
+ map_tag+=' '
+ if message.cancellation_time==None:
+ endloc=message.end_loc()#line displays length of 1st message (lowest class), that is not cancelled
+ loc=message.location
+ map_tag+=''%color
+ map_tag+=message.map_string()
+ map_tag+=' '
+ map_tag+='
'
+ map_tag+=''
+ if not loc==None:
+ if endloc==None or not endloc.is_valid:
+ endloc=loc#creates line of 0 length (dot)
+ markerstring+=tmc_dict.marker_template.format(loc=loc.koord_str_google,text=map_tag,endloc=endloc.koord_str_google)
+ markerstring+="\n"
+ except UnicodeDecodeError as e:
+ print(e)
+ code.interact(local=locals())
+ pass
return markerstring
@@ -445,11 +450,12 @@ class tmc_message:
str_list=[str(elem) for elem in self.events]
return str(", ".join(str_list))
def log_string(self):
- return str(self.event.updateClass)+": "+self.getTime()+": "+self.location_text()+": "+self.events_string()+"; "+self.info_str()+"; "+self.psn
+ return str(self.event.updateClass)+": "+self.getTime()+": "+self.location_text()+": "+self.events_string()+"; "+self.info_str()+"; "+self.psn.encode("utf-8")
+ #2017-03-16 fix:self.psn.encode("utf-8"), utf8 decoding happens later
def db_string(self):
return str(self.location)+": "+str(self.event.updateClass)+": "+self.events_string()+"; "+self.info_str()
def map_string(self):
- return ''%self.multi_str()+str(self.event.updateClass)+": "+self.getTime()+": "+self.events_string()+self.info_str()+"; "+self.psn+" "
+ return ''%self.multi_str()+str(self.event.updateClass)+": "+self.getTime()+": "+self.events_string()+self.info_str()+"; "+self.psn.encode("utf-8")+" "
def end_loc(self):
return self.location.get_extent_location(self.location,self.tmc_extent,self.tmc_dir)
def location_text(self):
@@ -489,7 +495,8 @@ class tmc_message:
#E
#EventCode: EventText
#F
- return str(text)
+ #return unicode(text,encoding="utf-8")
+ return text
def __str__(self):
return str(self.event.updateClass)+": "+self.getTime()+": "+self.events_string()+"; "+self.multi_str()
def __repr__(self):
@@ -904,6 +911,22 @@ class rds_parser_table_qt(gr.sync_block):#START
self.RDS_data[PI]={}
#self.RDS_data[PI]["blockcounts"]={}# no defaults (works aswell)
#defaults are to keep colors in piechart consistent between stations:
+
+ coverage_area={"0":"local,","1":"international,","2":"national,","3":"supranational,"}
+ pi_str=""
+ if list(PI)[1] in "456789ABCDEF":
+ pi_str+="regional, "
+ else:
+ pi_str+=coverage_area[list(PI)[1]]
+ bundeslaender={"0":"Baden-Württemberg","1":"Bayern","2":"Berlin","3":"Brandenburg","4":"Bremen und Bremerhaven",
+ "5":"Hamburg","6":"Hessen","7":"Mecklenburg-Vorpommern","8":"Niedersachsen","9":"Nordrhein-Westfalen","A":"Rheinland-Pfalz",
+ "B":"Saarland","C":"Sachsen","D":"Sachsen-Anhalt","E":"Schleswig-Holstein","F":"Thüringen"}
+ if list(PI)[0] in "D1":
+ pi_str+="germany?, "
+ pi_str+=bundeslaender[list(PI)[2]]+", "
+ pi_str+="NR:"+list(PI)[3]
+ self.RDS_data[PI]["CC"]=list(PI)[0]
+ self.RDS_data[PI]["PI-meaning"]=pi_str
self.RDS_data[PI]["blockcounts"]={"0A":0,"1A":0,"2A":0,"3A":0,"4A":0,"6A":0,"8A":0,"12A":0,"14A":0}
self.RDS_data[PI]["blockcounts"]["any"]=0
self.RDS_data[PI]["AID_list"]={}
@@ -1661,10 +1684,21 @@ class rds_parser_table_qt(gr.sync_block):#START
def decode_chars(self,charstring):
alphabet={
+ 0b0010:u" !\#¤%&'()*+,-./",
+ 0b0011:u"0123456789:;<=>?",
+ 0b0100:u"@ABCDEFGHIJKLMNO",
+ 0b0101:u"PQRSTUVWXYZ[\]―_",
+ 0b0110:u"‖abcdefghijklmno",
+ 0b0111:u"pqrstuvwxyz{|}¯ ",
0b1000:u"áàéèíìóòúùÑÇŞßiIJ",
- 0b1001:u"âäêëîïôöûüñçş??ij",
+ 0b1001:u"âäêëîïôöûüñçşǧıij",
+ 0b1010:u"ªα©‰Ǧěňőπ€£$←↑→↓",
+ 0b1011:u"º¹²³±İńűµ¿÷°¼½¾§",
0b1100:u"ÁÀÉÈÍÌÓÒÚÙŘČŠŽĐĿ",
- 0b1101:u"ÂÄÊËÎÏÔÖÛÜřčšžđŀ"}
+ 0b1101:u"ÂÄÊËÎÏÔÖÛÜřčšžđŀ",
+ 0b1110:u"ÃÅÆŒŷÝÕØÞŊŔĆŚŹŦð",
+ 0b1111:u"ãåæœŵýõøþŋŕćśźŧ"}#0xff should not occur (not in standard)
+
#charlist=list(charstring)
return_string=""
for i,char in enumerate(charstring):
@@ -1677,20 +1711,16 @@ class rds_parser_table_qt(gr.sync_block):#START
return_string+=char
else:
return_string+="{%02X}"%ord(char)#output control code
- elif ord(char)<= 0b01111111:
- #charlist[i]=char #use ascii
- return_string+=char
+# elif ord(char)<= 0b01111111: #real encoding slightly different from ascii
+# return_string+=char#use ascii
else:
try:
- #charlist[i]=alphabet[alnr][index]
return_string+=alphabet[alnr][index]
- return_string+=unichr(ord(char))#TODO remove test code and properly decide for UTF8 or EBU charset
+ #return_string+=unichr(ord(char))#TODO: properly decide for UTF8 or EBU charset
except KeyError:
- return_string+="?%02X?"%ord(char)
+ return_string+="?%02X?"%ord(char)#symbol not decoded
print("symbol not decoded: "+"?%02X?"%ord(char)+"in string:"+return_string)
- #charlist[i]='?'#symbol not decoded #TODO
pass
- #return "".join(charlist)
return return_string
def color_text(self, text, start,end,textcolor,segmentcolor):
#formatted_text="%s %s %s "% (textcolor,text[:start],segmentcolor,text[start:end],textcolor,text[end:])
diff --git a/swig/crfa_swig.i b/swig/crfa_swig.i
index cfc0b0c..606ab65 100644
--- a/swig/crfa_swig.i
+++ b/swig/crfa_swig.i
@@ -11,6 +11,7 @@
#include "crfa/rds_decoder.h"
#include "crfa/diff_add_sync_decim.h"
#include "crfa/sync_decim.h"
+#include "crfa/rds_decoder_redsea.h"
%}
%include "crfa/rds_decoder.h"
@@ -19,3 +20,5 @@ GR_SWIG_BLOCK_MAGIC2(crfa, rds_decoder);
GR_SWIG_BLOCK_MAGIC2(crfa, diff_add_sync_decim);
%include "crfa/sync_decim.h"
GR_SWIG_BLOCK_MAGIC2(crfa, sync_decim);
+%include "crfa/rds_decoder_redsea.h"
+GR_SWIG_BLOCK_MAGIC2(crfa, rds_decoder_redsea);