Browse Source

completed EBU carset, fixed mapstring+psn unicode error, added PI region info, experimented with redsea decoder

master
Clemens Richter 9 years ago
parent
commit
bbd8b06aaa
  1. 3
      grc/CMakeLists.txt
  2. 45
      grc/crfa_rds_decoder_redsea.xml
  3. 3
      include/crfa/CMakeLists.txt
  4. 56
      include/crfa/rds_decoder_redsea.h
  5. 3
      lib/CMakeLists.txt
  6. 6
      lib/rds_decoder_impl.cc
  7. 9
      lib/rds_decoder_impl.h
  8. 334
      lib/rds_decoder_redsea_impl.cc
  9. 79
      lib/rds_decoder_redsea_impl.h
  10. 112
      python/rds_parser_table_qt.py
  11. 3
      swig/crfa_swig.i

3
grc/CMakeLists.txt

@ -28,5 +28,6 @@ install(FILES
crfa_vector_cutter.xml crfa_vector_cutter.xml
crfa_decoder_compare.xml crfa_decoder_compare.xml
crfa_diff_add_sync_decim.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
) )

45
grc/crfa_rds_decoder_redsea.xml

@ -0,0 +1,45 @@
<?xml version="1.0"?>
<block>
<name>RDS Decoder (redsea)</name>
<key>crfa_rds_decoder_redsea</key>
<category>[crfa]</category>
<import>import crfa</import>
<make>crfa.rds_decoder($log, $debug)</make>
<param>
<name>Log</name>
<key>log</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<param>
<name>Debug</name>
<key>debug</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<sink>
<name>in</name>
<type>byte</type>
</sink>
<source>
<name>out</name>
<type>message</type>
<optional>1</optional>
</source>
</block>

3
include/crfa/CMakeLists.txt

@ -24,5 +24,6 @@ install(FILES
api.h api.h
rds_decoder.h rds_decoder.h
diff_add_sync_decim.h diff_add_sync_decim.h
sync_decim.h DESTINATION include/crfa sync_decim.h
rds_decoder_redsea.h DESTINATION include/crfa
) )

56
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 <crfa/api.h>
#include <gnuradio/sync_block.h>
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<rds_decoder_redsea> 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 */

3
lib/CMakeLists.txt

@ -27,7 +27,8 @@ link_directories(${Boost_LIBRARY_DIRS})
list(APPEND crfa_sources list(APPEND crfa_sources
rds_decoder_impl.cc rds_decoder_impl.cc
diff_add_sync_decim_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) set(crfa_sources "${crfa_sources}" PARENT_SCOPE)
if(NOT crfa_sources) if(NOT crfa_sources)

6
lib/rds_decoder_impl.cc

@ -28,6 +28,8 @@
#include <gnuradio/io_signature.h> #include <gnuradio/io_signature.h>
#include "constants.h" #include "constants.h"
#include "rds_decoder_impl.h" #include "rds_decoder_impl.h"
#include <map>
#include <vector>
namespace gr { namespace gr {
namespace crfa { namespace crfa {
@ -260,7 +262,9 @@ int rds_decoder_impl::work (int noutput_items,
bit_counter++; bit_counter++;
} }
return noutput_items; return noutput_items;
}/*work function*/ }/*end of work function*/
} /* namespace crfa */ } /* namespace crfa */
} /* namespace gr */ } /* namespace gr */

9
lib/rds_decoder_impl.h

@ -60,6 +60,15 @@ private:
unsigned char lastseen_offset; unsigned char lastseen_offset;
unsigned char block_number; unsigned char block_number;
enum { NO_SYNC, SYNC } d_state; 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);*/
}; };

334
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 <gnuradio/io_signature.h>
#include "constants.h"
#include "rds_decoder_redsea_impl.h"
#include <map>
#include <vector>
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<<plen)) reg = reg ^ poly;
}
return (reg & ((1<<plen)-1)); // select the bottom plen bits of reg
}
void rds_decoder_redsea_impl::decode_group(unsigned int *group) {
// raw data bytes, as received from RDS.
// 8 info bytes, followed by 4 RDS offset chars: ABCD/ABcD/EEEE (in US)
unsigned char bytes[13];
// RDS information words
bytes[0] = (group[0] >> 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<noutput_items) {
reg=(reg<<1)|in[i]; // reg contains the last 26 rds bits
switch (d_state) {
case NO_SYNC:
reg_syndrome = calc_syndrome(reg,26);
for (j=0;j<5;j++) {
if (reg_syndrome==syndrome[j]) {
if (!presync) {
lastseen_offset=j;
lastseen_offset_counter=bit_counter;
presync=true;
}
else {
bit_distance=bit_counter-lastseen_offset_counter;
if (offset_pos[lastseen_offset]>=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 */

79
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 <crfa/rds_decoder_redsea.h>
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 */

112
python/rds_parser_table_qt.py

@ -320,34 +320,39 @@ class tmc_dict:
return retStr return retStr
def getMarkerString(self): def getMarkerString(self):
markerstring="" markerstring=""
for lcn in self.messages: try:
loc=None for lcn in self.messages:
endloc=None loc=None
map_tag='<p>' endloc=None
for updateClass in self.messages[lcn]: map_tag='<p>'
message=self.messages[lcn][updateClass] for updateClass in self.messages[lcn]:
if message.cancellation_time==None: message=self.messages[lcn][updateClass]
color="black" if message.cancellation_time==None:
else: color="black"
color="gray" else:
if message.location.has_koord: color="gray"
if loc==None:#first message at this location if message.location.has_koord:
map_tag+='<h3 style="padding: 0px;margin: 0px;">' if loc==None:#first message at this location
map_tag+=message.location_text() map_tag+='<h3 style="padding: 0px;margin: 0px;">'
map_tag+='</h3>' map_tag+=message.location_text()
if message.cancellation_time==None: map_tag+='</h3>'
endloc=message.end_loc()#line displays length of 1st message (lowest class), that is not cancelled if message.cancellation_time==None:
loc=message.location endloc=message.end_loc()#line displays length of 1st message (lowest class), that is not cancelled
map_tag+='<div style="color: %s;">'%color loc=message.location
map_tag+=message.map_string() map_tag+='<div style="color: %s;">'%color
map_tag+='<br />' map_tag+=message.map_string()
map_tag+='</div>' map_tag+='<br />'
map_tag+='</p>' map_tag+='</div>'
if not loc==None: map_tag+='</p>'
if endloc==None or not endloc.is_valid: if not loc==None:
endloc=loc#creates line of 0 length (dot) if endloc==None or not endloc.is_valid:
markerstring+=tmc_dict.marker_template.format(loc=loc.koord_str_google,text=map_tag,endloc=endloc.koord_str_google) endloc=loc#creates line of 0 length (dot)
markerstring+="\n" 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 return markerstring
@ -445,11 +450,12 @@ class tmc_message:
str_list=[str(elem) for elem in self.events] str_list=[str(elem) for elem in self.events]
return str(", ".join(str_list)) return str(", ".join(str_list))
def log_string(self): 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): def db_string(self):
return str(self.location)+": "+str(self.event.updateClass)+": "+self.events_string()+"; "+self.info_str() return str(self.location)+": "+str(self.event.updateClass)+": "+self.events_string()+"; "+self.info_str()
def map_string(self): def map_string(self):
return '<span title="%s">'%self.multi_str()+str(self.event.updateClass)+": "+self.getTime()+": "+self.events_string()+self.info_str()+"; "+self.psn+"</span>" return '<span title="%s">'%self.multi_str()+str(self.event.updateClass)+": "+self.getTime()+": "+self.events_string()+self.info_str()+"; "+self.psn.encode("utf-8")+"</span>"
def end_loc(self): def end_loc(self):
return self.location.get_extent_location(self.location,self.tmc_extent,self.tmc_dir) return self.location.get_extent_location(self.location,self.tmc_extent,self.tmc_dir)
def location_text(self): def location_text(self):
@ -489,7 +495,8 @@ class tmc_message:
#E #E
#EventCode: EventText #EventCode: EventText
#F #F
return str(text) #return unicode(text,encoding="utf-8")
return text
def __str__(self): def __str__(self):
return str(self.event.updateClass)+": "+self.getTime()+": "+self.events_string()+"; "+self.multi_str() return str(self.event.updateClass)+": "+self.getTime()+": "+self.events_string()+"; "+self.multi_str()
def __repr__(self): def __repr__(self):
@ -904,6 +911,22 @@ class rds_parser_table_qt(gr.sync_block):#START
self.RDS_data[PI]={} self.RDS_data[PI]={}
#self.RDS_data[PI]["blockcounts"]={}# no defaults (works aswell) #self.RDS_data[PI]["blockcounts"]={}# no defaults (works aswell)
#defaults are to keep colors in piechart consistent between stations: #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"]={"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]["blockcounts"]["any"]=0
self.RDS_data[PI]["AID_list"]={} self.RDS_data[PI]["AID_list"]={}
@ -1661,10 +1684,21 @@ class rds_parser_table_qt(gr.sync_block):#START
def decode_chars(self,charstring): def decode_chars(self,charstring):
alphabet={ alphabet={
0b0010:u" !\%&'()*+,-./",
0b0011:u"0123456789:;<=>?",
0b0100:u"@ABCDEFGHIJKLMNO",
0b0101:u"PQRSTUVWXYZ[\]―_",
0b0110:u"‖abcdefghijklmno",
0b0111:u"pqrstuvwxyz{|}¯ ",
0b1000:u"áàéèíìóòúùÑÇŞßiIJ", 0b1000:u"áàéèíìóòúùÑÇŞßiIJ",
0b1001:u"âäêëîïôöûüñçş??ij", 0b1001:u"âäêëîïôöûüñçşǧıij",
0b1010:u"ªα©‰Ǧěňőπ€£$←↑→↓",
0b1011:u"º¹²³±İńűµ¿÷°¼½¾§",
0b1100:u"ÁÀÉÈÍÌÓÒÚÙŘČŠŽĐĿ", 0b1100:u"ÁÀÉÈÍÌÓÒÚÙŘČŠŽĐĿ",
0b1101:u"ÂÄÊËÎÏÔÖÛÜřčšžđŀ"} 0b1101:u"ÂÄÊËÎÏÔÖÛÜřčšžđŀ",
0b1110:u"ÃÅÆŒŷÝÕØÞŊŔĆŚŹŦð",
0b1111:u"ãåæœŵýõøþŋŕćśźŧ"}#0xff should not occur (not in standard)
#charlist=list(charstring) #charlist=list(charstring)
return_string="" return_string=""
for i,char in enumerate(charstring): for i,char in enumerate(charstring):
@ -1677,20 +1711,16 @@ class rds_parser_table_qt(gr.sync_block):#START
return_string+=char return_string+=char
else: else:
return_string+="{%02X}"%ord(char)#output control code return_string+="{%02X}"%ord(char)#output control code
elif ord(char)<= 0b01111111: # elif ord(char)<= 0b01111111: #real encoding slightly different from ascii
#charlist[i]=char #use ascii # return_string+=char#use ascii
return_string+=char
else: else:
try: try:
#charlist[i]=alphabet[alnr][index]
return_string+=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: 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) print("symbol not decoded: "+"?%02X?"%ord(char)+"in string:"+return_string)
#charlist[i]='?'#symbol not decoded #TODO
pass pass
#return "".join(charlist)
return return_string return return_string
def color_text(self, text, start,end,textcolor,segmentcolor): def color_text(self, text, start,end,textcolor,segmentcolor):
#formatted_text="<font face='Courier New' color='%s'>%s</font><font face='Courier New' color='%s'>%s</font><font face='Courier New' color='%s'>%s</font>"% (textcolor,text[:start],segmentcolor,text[start:end],textcolor,text[end:]) #formatted_text="<font face='Courier New' color='%s'>%s</font><font face='Courier New' color='%s'>%s</font><font face='Courier New' color='%s'>%s</font>"% (textcolor,text[:start],segmentcolor,text[start:end],textcolor,text[end:])

3
swig/crfa_swig.i

@ -11,6 +11,7 @@
#include "crfa/rds_decoder.h" #include "crfa/rds_decoder.h"
#include "crfa/diff_add_sync_decim.h" #include "crfa/diff_add_sync_decim.h"
#include "crfa/sync_decim.h" #include "crfa/sync_decim.h"
#include "crfa/rds_decoder_redsea.h"
%} %}
%include "crfa/rds_decoder.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); GR_SWIG_BLOCK_MAGIC2(crfa, diff_add_sync_decim);
%include "crfa/sync_decim.h" %include "crfa/sync_decim.h"
GR_SWIG_BLOCK_MAGIC2(crfa, sync_decim); GR_SWIG_BLOCK_MAGIC2(crfa, sync_decim);
%include "crfa/rds_decoder_redsea.h"
GR_SWIG_BLOCK_MAGIC2(crfa, rds_decoder_redsea);

Loading…
Cancel
Save