diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 203134f..eec0d11 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -26,5 +26,7 @@ install(FILES crfa_smooth_vectors.xml crfa_stream_selector.xml crfa_vector_cutter.xml - crfa_decoder_compare.xml DESTINATION share/gnuradio/grc/blocks + crfa_decoder_compare.xml + crfa_diff_add_sync_decim.xml + crfa_sync_decim.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/crfa_diff_add_sync_decim.xml b/grc/crfa_diff_add_sync_decim.xml new file mode 100644 index 0000000..dc61390 --- /dev/null +++ b/grc/crfa_diff_add_sync_decim.xml @@ -0,0 +1,60 @@ + + + diff_add_sync_decim + crfa_diff_add_sync_decim + [crfa] + import crfa + crfa.diff_add_sync_decim($threshold,$max_ratio_below_threshold, $log) + + + Log + log + False + bool + + + + + Threshold + threshold + 0.5 + float + + + max_ratio_below_threshold + max_ratio_below_threshold + 0.8 + float + + 0 < $max_ratio_below_threshold < 1 + + + + in + float + + + + + out + float + + diff --git a/grc/crfa_sync_decim.xml b/grc/crfa_sync_decim.xml new file mode 100644 index 0000000..2e94b31 --- /dev/null +++ b/grc/crfa_sync_decim.xml @@ -0,0 +1,65 @@ + + + sync_decim + crfa_sync_decim + [crfa] + import crfa + crfa.sync_decim($threshold, $min_diff, $log) + + + Log + log + False + bool + + + + + Threshold + threshold + 0.25 + float + + + min_diff + min_diff + 0.2 + float + + 0 < $min_diff < 1 + + + + in + float + + + ctrl + message + 1 + + + + + out + float + + diff --git a/include/crfa/CMakeLists.txt b/include/crfa/CMakeLists.txt index 5743aa6..80deb04 100644 --- a/include/crfa/CMakeLists.txt +++ b/include/crfa/CMakeLists.txt @@ -22,5 +22,7 @@ ######################################################################## install(FILES api.h - rds_decoder.h DESTINATION include/crfa + rds_decoder.h + diff_add_sync_decim.h + sync_decim.h DESTINATION include/crfa ) diff --git a/include/crfa/diff_add_sync_decim.h b/include/crfa/diff_add_sync_decim.h new file mode 100644 index 0000000..a3bb88b --- /dev/null +++ b/include/crfa/diff_add_sync_decim.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_DIFF_ADD_SYNC_DECIM_H +#define INCLUDED_CRFA_DIFF_ADD_SYNC_DECIM_H + +#include +#include + +namespace gr { + namespace crfa { + + /*! + * \brief <+description of block+> + * \ingroup crfa + * + */ + class CRFA_API diff_add_sync_decim : virtual public gr::sync_decimator + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of crfa::diff_add_sync_decim. + * + * To avoid accidental use of raw pointers, crfa::diff_add_sync_decim's + * constructor is in a private implementation + * class. crfa::diff_add_sync_decim::make is the public interface for + * creating new instances. + */ + static sptr make(float threshold,float max_ratio_below_threshold,bool log); + }; + + } // namespace crfa +} // namespace gr + +#endif /* INCLUDED_CRFA_DIFF_ADD_SYNC_DECIM_H */ + diff --git a/include/crfa/sync_decim.h b/include/crfa/sync_decim.h new file mode 100644 index 0000000..816ff14 --- /dev/null +++ b/include/crfa/sync_decim.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_SYNC_DECIM_H +#define INCLUDED_CRFA_SYNC_DECIM_H + +#include +#include + +namespace gr { + namespace crfa { + + /*! + * \brief <+description of block+> + * \ingroup crfa + * + */ + class CRFA_API sync_decim : virtual public gr::sync_decimator + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of crfa::sync_decim. + * + * To avoid accidental use of raw pointers, crfa::sync_decim's + * constructor is in a private implementation + * class. crfa::sync_decim::make is the public interface for + * creating new instances. + */ + static sptr make(float threshold,float min_diff,bool log); + }; + + } // namespace crfa +} // namespace gr + +#endif /* INCLUDED_CRFA_SYNC_DECIM_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 385b6c2..91f8e20 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -25,7 +25,9 @@ include(GrPlatform) #define LIB_SUFFIX include_directories(${Boost_INCLUDE_DIR}) link_directories(${Boost_LIBRARY_DIRS}) list(APPEND crfa_sources - rds_decoder_impl.cc ) + rds_decoder_impl.cc + diff_add_sync_decim_impl.cc + sync_decim_impl.cc ) set(crfa_sources "${crfa_sources}" PARENT_SCOPE) if(NOT crfa_sources) diff --git a/lib/diff_add_sync_decim_impl.cc b/lib/diff_add_sync_decim_impl.cc new file mode 100644 index 0000000..fa147af --- /dev/null +++ b/lib/diff_add_sync_decim_impl.cc @@ -0,0 +1,142 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "diff_add_sync_decim_impl.h" +#define DECIM 2 +#define lout log && std::cout + +namespace gr { + namespace crfa { + + diff_add_sync_decim::sptr + diff_add_sync_decim::make(float threshold,float max_ratio_below_threshold,bool log) + { + return gnuradio::get_initial_sptr + (new diff_add_sync_decim_impl(threshold,max_ratio_below_threshold,log)); + } + + /* + * The private constructor + */ + diff_add_sync_decim_impl::diff_add_sync_decim_impl(float threshold,float max_ratio_below_threshold,bool log) + : gr::sync_decimator("diff_add_sync_decim", + gr::io_signature::make(1, 1, sizeof(float)), + gr::io_signature::make(1, 1, sizeof(float)), DECIM), + threshold(threshold), + max_ratio_below_threshold(max_ratio_below_threshold), + log(log) + + { + //nothing to do? + + //init persistant vars + last_input=0; + skip=0; + } + + /* + * Our virtual destructor. + */ + diff_add_sync_decim_impl::~diff_add_sync_decim_impl() + { + } + + int + diff_add_sync_decim_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + int values_below_threshold=0; + int values_below_threshold_skip=0; + int values_below_threshold_noskip=0; + float out_noskip; + float out_skip; + for (int i = 0; i < noutput_items; i++) { + //out[i]=in[DECIM*i];// keep 1 in DECIM + if(i==0){ + out_skip=last_input-in[DECIM*i];} + else{ + out_skip=in[DECIM*i-1]-in[DECIM*i];} + + out_noskip=in[DECIM*i]-in[DECIM*i+1]; + + switch(skip){ + case 0: + out[i]=out_noskip; + break; + case 1: + out[i]=out_skip; + break; + default: + out[i]=out_noskip; + break; + } + + if(abs(out[i])0.5) + if ((float)values_below_threshold / (float)noutput_items >max_ratio_below_threshold && values_below_threshold>8)//2/2(=100%) below threshold is not significant + { + //lout<<"resync:"<9){ +// if(values_below_threshold_noskip>values_below_threshold_skip){ +// skip=1; +// } +// else{ +// skip=0; +// } +// } + //lout << "noutput_items:"<< noutput_items <<", threshold:"<. + * + * 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_DIFF_ADD_SYNC_DECIM_IMPL_H +#define INCLUDED_CRFA_DIFF_ADD_SYNC_DECIM_IMPL_H + +#include + +namespace gr { + namespace crfa { + + class diff_add_sync_decim_impl : public diff_add_sync_decim + { + private: + // Nothing to declare in this block. + + public: + diff_add_sync_decim_impl(float threshold,float max_ratio_below_threshold,bool log); + ~diff_add_sync_decim_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); + bool log; + float threshold; + float max_ratio_below_threshold; + float last_input; + //enum { SKIP, NOSKIP } d_state; + unsigned int skip; + }; + + } // namespace crfa +} // namespace gr + +#endif /* INCLUDED_CRFA_DIFF_ADD_SYNC_DECIM_IMPL_H */ + diff --git a/lib/sync_decim_impl.cc b/lib/sync_decim_impl.cc new file mode 100644 index 0000000..77145e3 --- /dev/null +++ b/lib/sync_decim_impl.cc @@ -0,0 +1,149 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "sync_decim_impl.h" +#define DECIM 2 +#define lout log && std::cout +//#include +namespace gr { + namespace crfa { + + sync_decim::sptr + sync_decim::make(float threshold,float min_diff,bool log) + { + return gnuradio::get_initial_sptr + (new sync_decim_impl(threshold, min_diff, log)); + } + + /* + * The private constructor + */ + sync_decim_impl::sync_decim_impl(float threshold,float min_diff,bool log) + : gr::sync_decimator("sync_decim", + gr::io_signature::make(1, 1, sizeof(float)), + gr::io_signature::make(1, 1, sizeof(float)), DECIM), + threshold(threshold), + min_diff(min_diff), + log(log) + + { + message_port_register_in(pmt::mp("ctrl")); + set_msg_handler(pmt::mp("ctrl"), boost::bind(&sync_decim_impl::parse_ctrl_msg, this, _1)); + //init persistant vars + last_input=0; + mode=COPY; + } + /* + * Our virtual destructor. + */ + sync_decim_impl::~sync_decim_impl() + { + } + + void sync_decim_impl::parse_ctrl_msg(pmt::pmt_t pdu) { + if(!pmt::is_pair(pdu)) { + lout << "wrong input message (not a PDU)" << std::endl; + return; + } + pmt::pmt_t meta = pmt::car(pdu); // meta declares type 0:RDS, 1:sync/nosync + pmt::pmt_t sync = pmt::cdr(pdu); + if(1L==pmt::to_long(meta) && pmt::eqv(sync,pmt::PMT_F)){ + lout<< "entered nosync"<8)//TODO: what if there are never more than 9 outputs requested + { + for (int i = 0; i < noutput_items; i++) { + if(i==0){ + out_skip=last_input-in[DECIM*i];} + else{ + out_skip=in[DECIM*i-1]-in[DECIM*i];} + + out_noskip=in[DECIM*i]-in[DECIM*i+1]; + if (std::abs(out_skip)>std::abs(out_noskip)){ + skip_is_better_counter++; + } + else{ + skip_is_better_counter--; + } + //lout<<"state:"<< mode; + //lout<<"\t,out_noskip:"<6){ + mode=SKIP; + lout<<"switched to skip"<< std::endl; + } + else if (skip_is_better_counter<-6){ + mode=NOSKIP; + lout<<"switched to noskip"<< std::endl; + } + } + } + + + + // Tell runtime system how many output items we produced. + return noutput_items; + }/*end of work*/ + } /* namespace crfa */ +} /* namespace gr */ + diff --git a/lib/sync_decim_impl.h b/lib/sync_decim_impl.h new file mode 100644 index 0000000..3f07f83 --- /dev/null +++ b/lib/sync_decim_impl.h @@ -0,0 +1,55 @@ +/* -*- 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_SYNC_DECIM_IMPL_H +#define INCLUDED_CRFA_SYNC_DECIM_IMPL_H + +#include + +namespace gr { + namespace crfa { + + class sync_decim_impl : public sync_decim + { + private: + // Nothing to declare in this block. + + public: + sync_decim_impl(float threshold,float min_diff,bool log); + ~sync_decim_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); + bool log; + float threshold; + float min_diff; + float last_input; + enum {COPY, SKIP, NOSKIP } mode; + unsigned int skip; + void parse_ctrl_msg(pmt::pmt_t pdu); + }; + + } // namespace crfa +} // namespace gr + +#endif /* INCLUDED_CRFA_SYNC_DECIM_IMPL_H */ + diff --git a/python/rds_parser_table_qt.py b/python/rds_parser_table_qt.py index 1ace89a..6697fda 100644 --- a/python/rds_parser_table_qt.py +++ b/python/rds_parser_table_qt.py @@ -394,13 +394,13 @@ class tmc_message: #datetime.timedelta(hours=0.25) def getDuration(self):#returns string if "D" in self.event.durationType and not self.event.nature=="F": - return tmc_message.duration_dict["Info_dyn"][self.tmc_DP] + return ", "+tmc_message.duration_dict["Info_dyn"][self.tmc_DP] elif "L" in self.event.durationType and not self.event.nature=="F": - return tmc_message.duration_dict["Info_long"][self.tmc_DP] + return ", "+tmc_message.duration_dict["Info_long"][self.tmc_DP] elif "D" in self.event.durationType and self.event.nature=="F": - return tmc_message.duration_dict["Forecast_dyn"][self.tmc_DP] + return ", "+tmc_message.duration_dict["Forecast_dyn"][self.tmc_DP] elif "L" in self.event.durationType and self.event.nature=="F": - return tmc_message.duration_dict["Forecast_long"][self.tmc_DP] + return ", "+tmc_message.duration_dict["Forecast_long"][self.tmc_DP] else: return "" #self.event.durationType #D,(D),L,(L) @@ -429,28 +429,27 @@ class tmc_message: else: try: multi="%i:%s"%(self.length,str(self.mgm_list)) - #multi+=";events:" - #for i,event in enumerate(self.events): - #if not i==0: - #multi+=str(event)+"," except AttributeError: multi="[multi incomplete]" + return str(multi) + def info_str(self): + info="" + info+=self.getDuration() if not self.cancellation_time==None: if language=="de": - multi+=" (aufgehoben um %s)"%self.cancellation_time + info+=" (aufgehoben um %s)"%self.cancellation_time else: - multi+=" (cancelled at %s)"%self.cancellation_time - multi+="; "+self.getDuration() - return str(multi) + info+=" (cancelled at %s)"%self.cancellation_time + return info def events_string(self): 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.psn + return str(self.event.updateClass)+": "+self.getTime()+": "+self.location_text()+": "+self.events_string()+"; "+self.info_str()+"; "+self.psn def db_string(self): - return str(self.location)+": "+str(self.event.updateClass)+": "+self.events_string() + return str(self.location)+": "+str(self.event.updateClass)+": "+self.events_string()+"; "+self.info_str() def map_string(self): - return str(self.event.updateClass)+": "+self.getTime()+": "+self.events_string()+"; "+self.multi_str()+"; "+self.psn + return ''%self.multi_str()+str(self.event.updateClass)+": "+self.getTime()+": "+self.events_string()+self.info_str()+"; "+self.psn+"" def end_loc(self): return self.location.get_extent_location(self.location,self.tmc_extent,self.tmc_dir) def location_text(self): @@ -508,8 +507,8 @@ class tmc_message: try: msg_ltn=tableobj.RDS_data[PI]["AID_list"][52550]["LTN"] table_ltn=1#german table - if msg_ltn != table_ltn and tableobj.debug: - print("msg_ltn:%i does not match given table (1) on station: %s"%(msg_ltn,self.psn)) + if msg_ltn != table_ltn and tableobj.debug and False:#disabled, spams log + print("msg_ltn:%i does not match expected table (1) on station: %s"%(msg_ltn,self.psn)) except KeyError: if tableobj.debug: print("no LTN found") @@ -648,6 +647,14 @@ class mgm_tag:#mgm=multi group message ,5:" Equivalent of diversion bit set to '1'." ,6:" Increase the number of steps in the problem extent by 8." ,7:" Increase the number of steps in the problem extent by 16."} + control_codes_short={0:"urgency+=1" + ,1:" urgency-=1" + ,2:" directionality changed" + ,3:" dynamic/longer-lasting changed" + ,4:" spoken/unspoken duration changed" + ,5:" diversion=1" + ,6:" extent+=8" + ,7:" extent+=16"} @staticmethod def decode_time_date(raw):#label7/8 raw to datestring if raw<=95: @@ -680,7 +687,7 @@ class mgm_tag:#mgm=multi group message if(self.label==0): return "duration: %i"%self.data.uint elif(self.label==1): - return "control code: %i"%self.data.uint + return "control code %i: %s"%(self.data.uint,mgm_tag.control_codes_short[self.data.uint]) elif(self.label==2): return "length affected: %i km"%self.length_to_km(self.data.uint) elif(self.label==3): @@ -923,11 +930,12 @@ class rds_parser_table_qt(gr.sync_block):#START if time.time()-self.minute_count_timer > 3:#every 3 second self.minute_count_max=self.minute_count + self.signals.DataUpdateEvent.emit({'group_count':self.minute_count,'group_count_max':self.minute_count_max}) self.minute_count=0 self.minute_count_timer=time.time() - pr.enable()#disabled-internal-profiling + #pr.enable()#disabled-internal-profiling self.minute_count+=1 - self.signals.DataUpdateEvent.emit({'group_count':self.minute_count,'group_count_max':self.minute_count_max}) + #self.signals.DataUpdateEvent.emit({'group_count':self.minute_count,'group_count_max':self.minute_count_max}) if self.writeDB: #db=sqlite3.connect(self.db_name) db=self.db @@ -1135,7 +1143,8 @@ class rds_parser_table_qt(gr.sync_block):#START paging=array[4]&0xf extended_country_code=array[5] self.RDS_data[PI]["ECC"]=extended_country_code - #print("ECC:%s"%hex(extended_country_code)) + if self.debug: + print("PI:%s PSN:%s,ECC:%s"%(PI,self.RDS_data[PI]["PSN"],hex(extended_country_code))) elif variant==1: TMC_info=SLC elif variant==2: @@ -1143,7 +1152,7 @@ class rds_parser_table_qt(gr.sync_block):#START elif variant==3: language_codes=SLC if self.debug: - print("language_codes:%s"%hex(language_codes)) + print("PI:%s PSN:%s,language_codes:%s"%(PI,self.RDS_data[PI]["PSN"],hex(language_codes))) elif variant==6: #for use by broadcasters if self.debug: @@ -1214,7 +1223,7 @@ class rds_parser_table_qt(gr.sync_block):#START textcolor=""#use default color (white if background is black) l=list(self.RDS_data[PI]["RT_"+str(ab_flag)]["RT"]) rt="".join(l[0:text_end])#remove underscores(default symbol) after line end marker - if not self.RDS_data[PI]["internals"]["last_valid_rt"]==rt:#ignore duplicates + if not self.RDS_data[PI]["internals"]["last_valid_rt"]==rt:#ignore duplicates #TODO add 2nd order duplicates ABAB self.RDS_data[PI]["internals"]["RT_history"].append(l) if len(self.RDS_data[PI]["internals"]["RT_history"])>10:#only store last 10 RTs self.RDS_data[PI]["internals"]["RT_history"].pop(0) @@ -1254,20 +1263,31 @@ class rds_parser_table_qt(gr.sync_block):#START self.RDS_data[PI]["AID_list"][AID]["groupType"]=app_group self.RDS_data[PI]["AID_list"][AID]["app_name"]=app_name self.RDS_data[PI]["AID_list"][AID]["app_data"]=app_data + if AID==52550:#TMC alert-c initialize + self.RDS_data[PI]["AID_list"][AID]["provider name"]="________" if self.log: - print("new ODA: AID:%i, name:%s, app_group:%s, station:%s" %(AID,app_name,app_group,PI)) + print("new ODA: AID:%i, name:'%s', app_group:%s, station:%s" %(AID,app_name,app_group,PI)) #decode 3A group of TMC - if AID==52550:#TMC alert-c - variant=app_data>>14 + if AID==52550:#TMC alert-c (continuously update) + variant=app_data>>14 if variant==0: - self.RDS_data[PI]["AID_list"][AID]["LTN"]=(app_data>>6)&0x3f#location table number + self.RDS_data[PI]["AID_list"][AID]["LTN"]=(app_data>>6)&0x3f#location table number (6 bits) self.RDS_data[PI]["AID_list"][AID]["AFI"]=(app_data>>5)&0x1#alternative frequency indicator self.RDS_data[PI]["AID_list"][AID]["M"]=(app_data>>4)&0x1#transmission mode indicator #Message Geographical Scope: - self.RDS_data[PI]["AID_list"][AID]["I"]=(app_data>>3)&0x1#international (EUROROAD) - self.RDS_data[PI]["AID_list"][AID]["N"]=(app_data>>2)&0x1#national - self.RDS_data[PI]["AID_list"][AID]["R"]=(app_data>>1)&0x1#regional - self.RDS_data[PI]["AID_list"][AID]["U"]=(app_data>>0)&0x1#urban + self.RDS_data[PI]["AID_list"][AID]["scope"]="" + if (app_data>>3)&0x1==1: + self.RDS_data[PI]["AID_list"][AID]["scope"]+="I"#international (EUROROAD) + if (app_data>>2)&0x1==1: + self.RDS_data[PI]["AID_list"][AID]["scope"]+="N"#national + if (app_data>>1)&0x1==1: + self.RDS_data[PI]["AID_list"][AID]["scope"]+="R"#regional + if (app_data>>0)&0x1==1: + self.RDS_data[PI]["AID_list"][AID]["scope"]+="U"#urban + #self.RDS_data[PI]["AID_list"][AID]["I"]=(app_data>>3)&0x1#international (EUROROAD) + #self.RDS_data[PI]["AID_list"][AID]["N"]=(app_data>>2)&0x1#national + #self.RDS_data[PI]["AID_list"][AID]["R"]=(app_data>>1)&0x1#regional + #self.RDS_data[PI]["AID_list"][AID]["U"]=(app_data>>0)&0x1#urban elif variant==1: self.RDS_data[PI]["AID_list"][AID]["SID"]=(app_data>>6)&0x3f#service identifier #timing parameters (used to switch away from TMC station without missing messages): @@ -1373,18 +1393,23 @@ class rds_parser_table_qt(gr.sync_block):#START if adr==4 or adr==5:#service provider name segment=self.decode_chars(chr(array[4])+chr(array[5])+chr(array[6])+chr(array[7])) if self.debug: - print("TMC-info adr:%i (provider name), segment:%s"%(adr,segment)) + print("TMC-info adr:%i (provider name), segment:%s, station:%s"%(adr,segment,self.RDS_data[PI]["PSN"])) + if self.RDS_data[PI]["AID_list"].has_key(52550): + text_list=list(self.RDS_data[PI]["AID_list"][52550]["provider name"]) + seg_adr_start=(adr-4)*4#start of segment + text_list[seg_adr_start:seg_adr_start+4]=segment + self.RDS_data[PI]["AID_list"][52550]["provider name"]="".join(text_list) if adr== 7:#freq of tuned an mapped station (not seen yet) freq_TN=tmc_y>>8 freq_ON=tmc_y&0xff#mapped frequency if self.debug: - print("TMC-info: TN:%i"%freq_TN) + print("TMC-info: TN:%i, station:%s"%(freq_TN,self.RDS_data[PI]["PSN"])) self.RDS_data[PI]["TMC_TN"]=freq_TN else: if self.debug: - print("alert plus")#(not seen yet) + print("alert plus on station %s (%s)"%(PI,self.RDS_data[PI]["PSN"]))#(not seen yet) - + #self.tableobj.RDS_data["D301"]["AID_list"][52550]["provider name"]="test____" #RadioText+ (grouptype mostly 12A): elif self.RDS_data[PI]["AID_list"].has_key(19415) and self.RDS_data[PI]["AID_list"][19415]["groupType"]==groupType:#RT+ if not self.RDS_data[PI].has_key("RT+"): @@ -1528,12 +1553,14 @@ class rds_parser_table_qt(gr.sync_block):#START #lock in tuned network if freq_TN matches decoder frequency if(self.RDS_data[PI].has_key("tuned_freq") and freq_TN==self.RDS_data[PI]["tuned_freq"]and not self.RDS_data[PI]["AF"].has_key("main")): if self.log: - print("main frequency found: station:%s, freq:%0.1fM"% (self.RDS_data[PI]["PSN"],freq_TN/1e6)) + print("main frequency found in 14A: station:%s, freq:%0.1fM"% (self.RDS_data[PI]["PSN"],freq_TN/1e6)) self.RDS_data[PI]["AF"]["main"]=freq_TN + freq_str="EON_TN:%0.1fM"% (freq_TN/1e6) + self.signals.DataUpdateEvent.emit({'PI':PI,'freq':freq_str}) #lock in ON if TN is locked in if(self.RDS_data[PI]["AF"].has_key("main") and self.RDS_data[PI]["AF"]["main"]==freq_TN and not self.RDS_data[PI_ON]["AF"].has_key("main")): if self.log: - print("mapped frequency found: station:%s, freq:%0.1fM"% (self.RDS_data[PI_ON]["PSN"],freq_ON/1e6)) + print("mapped frequency found in 14A: station:%s, freq:%0.1fM"% (self.RDS_data[PI_ON]["PSN"],freq_ON/1e6)) self.RDS_data[PI_ON]["AF"]["main"]=freq_ON freq_str="EON:%0.1fM"% (freq_ON/1e6) self.signals.DataUpdateEvent.emit({'PI':PI_ON,'freq':freq_str}) @@ -1651,6 +1678,7 @@ class rds_parser_table_qt(gr.sync_block):#START return_string+=alphabet[alnr][index] except KeyError: return_string+="?%02X?"%ord(char) + print("symbol not decoded: "+"?%02X?"%ord(char)+"in string:"+return_string) #charlist[i]='?'#symbol not decoded #TODO pass #return "".join(charlist) @@ -1716,7 +1744,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget): label_layout.addWidget(self.count_label) layout.addLayout(label_layout) #TODO set different minsize if TMC is shown - self.setMinimumSize(Qt.QSize(500,50*self.tableobj.nPorts)) + self.setMinimumSize(Qt.QSize(500,40*self.tableobj.nPorts)) if self.showTMC: self.tmc_message_label=QtGui.QLabel("TMC messages:") self.event_filter=QtGui.QLineEdit()#QPlainTextEdit ? @@ -1933,6 +1961,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget): scrollArea.setWidgetResizable(True) scrollArea.setWidget(l) view.layout().addWidget(scrollArea) + view.setWindowTitle(self.tableobj.RDS_data[PI]["PSN"]) view.exec_() def onCLick(self): print("button clicked") diff --git a/swig/crfa_swig.i b/swig/crfa_swig.i index 273d991..cfc0b0c 100644 --- a/swig/crfa_swig.i +++ b/swig/crfa_swig.i @@ -9,7 +9,13 @@ %{ #include "crfa/rds_decoder.h" +#include "crfa/diff_add_sync_decim.h" +#include "crfa/sync_decim.h" %} %include "crfa/rds_decoder.h" GR_SWIG_BLOCK_MAGIC2(crfa, rds_decoder); +%include "crfa/diff_add_sync_decim.h" +GR_SWIG_BLOCK_MAGIC2(crfa, diff_add_sync_decim); +%include "crfa/sync_decim.h" +GR_SWIG_BLOCK_MAGIC2(crfa, sync_decim);