Browse Source

table: multistr in map-string as tooltip only -> cleaner ; sync_decim: redesigned: 3 modes (copy skip noskip), copy mode: throw half away and synchronize, skip/noskip: stay there until reset, message input to reset)

master
Clemens Richter 9 years ago
parent
commit
df886a7c99
  1. 4
      grc/CMakeLists.txt
  2. 60
      grc/crfa_diff_add_sync_decim.xml
  3. 65
      grc/crfa_sync_decim.xml
  4. 4
      include/crfa/CMakeLists.txt
  5. 56
      include/crfa/diff_add_sync_decim.h
  6. 56
      include/crfa/sync_decim.h
  7. 4
      lib/CMakeLists.txt
  8. 142
      lib/diff_add_sync_decim_impl.cc
  9. 54
      lib/diff_add_sync_decim_impl.h
  10. 149
      lib/sync_decim_impl.cc
  11. 55
      lib/sync_decim_impl.h
  12. 105
      python/rds_parser_table_qt.py
  13. 6
      swig/crfa_swig.i

4
grc/CMakeLists.txt

@ -26,5 +26,7 @@ install(FILES
crfa_smooth_vectors.xml crfa_smooth_vectors.xml
crfa_stream_selector.xml crfa_stream_selector.xml
crfa_vector_cutter.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
) )

60
grc/crfa_diff_add_sync_decim.xml

@ -0,0 +1,60 @@
<?xml version="1.0"?>
<block>
<name>diff_add_sync_decim</name>
<key>crfa_diff_add_sync_decim</key>
<category>[crfa]</category>
<import>import crfa</import>
<make>crfa.diff_add_sync_decim($threshold,$max_ratio_below_threshold, $log)</make>
<!-- Make one 'param' node for every Parameter you want settable from the GUI.
Sub-nodes:
* name
* key (makes the value accessible as $keyname, e.g. in the make node)
* type -->
<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>Threshold</name>
<key>threshold</key>
<value>0.5</value>
<type>float</type>
</param>
<param>
<name>max_ratio_below_threshold</name>
<key>max_ratio_below_threshold</key>
<value>0.8</value>
<type>float</type>
</param>
<check>0 &lt; $max_ratio_below_threshold &lt; 1</check>
<!-- Make one 'sink' node per input. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<sink>
<name>in</name>
<type>float</type>
</sink>
<!-- Make one 'source' node per output. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<source>
<name>out</name>
<type>float</type>
</source>
</block>

65
grc/crfa_sync_decim.xml

@ -0,0 +1,65 @@
<?xml version="1.0"?>
<block>
<name>sync_decim</name>
<key>crfa_sync_decim</key>
<category>[crfa]</category>
<import>import crfa</import>
<make>crfa.sync_decim($threshold, $min_diff, $log)</make>
<!-- Make one 'param' node for every Parameter you want settable from the GUI.
Sub-nodes:
* name
* key (makes the value accessible as $keyname, e.g. in the make node)
* type -->
<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>Threshold</name>
<key>threshold</key>
<value>0.25</value>
<type>float</type>
</param>
<param>
<name>min_diff</name>
<key>min_diff</key>
<value>0.2</value>
<type>float</type>
</param>
<check>0 &lt; $min_diff &lt; 1</check>
<!-- Make one 'sink' node per input. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<sink>
<name>in</name>
<type>float</type>
</sink>
<sink>
<name>ctrl</name>
<type>message</type>
<optional>1</optional>
</sink>
<!-- Make one 'source' node per output. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<source>
<name>out</name>
<type>float</type>
</source>
</block>

4
include/crfa/CMakeLists.txt

@ -22,5 +22,7 @@
######################################################################## ########################################################################
install(FILES install(FILES
api.h api.h
rds_decoder.h DESTINATION include/crfa rds_decoder.h
diff_add_sync_decim.h
sync_decim.h DESTINATION include/crfa
) )

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

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

4
lib/CMakeLists.txt

@ -25,7 +25,9 @@ include(GrPlatform) #define LIB_SUFFIX
include_directories(${Boost_INCLUDE_DIR}) include_directories(${Boost_INCLUDE_DIR})
link_directories(${Boost_LIBRARY_DIRS}) 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
sync_decim_impl.cc )
set(crfa_sources "${crfa_sources}" PARENT_SCOPE) set(crfa_sources "${crfa_sources}" PARENT_SCOPE)
if(NOT crfa_sources) if(NOT crfa_sources)

142
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 <gnuradio/io_signature.h>
#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])<threshold){
values_below_threshold++;
}
if(abs(out_noskip)<threshold){
values_below_threshold_noskip++;
}
if(abs(out_skip)<threshold){
values_below_threshold_skip++;
}
}
last_input=in[(noutput_items-1)*DECIM+1];//to use for next iteration of work
//if ((float)values_below_threshold / (float)noutput_items >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:"<<values_below_threshold<<"/"<<noutput_items<<", skip:"<<skip<<", last_input:"<<last_input<<std::endl;
lout<<"out_skip:"<<values_below_threshold_skip<<"/"<<noutput_items;
lout<<", out_noskip:"<<values_below_threshold_noskip<<"/"<<noutput_items;
lout<<", skip:"<<skip <<std::endl;
switch(skip){
case 0:skip=1;break;
case 1:skip=0;break;
default:skip=0;break;
}
}
// if(noutput_items>9){
// if(values_below_threshold_noskip>values_below_threshold_skip){
// skip=1;
// }
// else{
// skip=0;
// }
// }
//lout << "noutput_items:"<< noutput_items <<", threshold:"<<threshold << std::endl;
//lout << "out[0]:"<< out[0] <<", threshold:"<<threshold << std::endl;
// Tell runtime system how many output items we produced.
return noutput_items;
}
} /* namespace crfa */
} /* namespace gr */

54
lib/diff_add_sync_decim_impl.h

@ -0,0 +1,54 @@
/* -*- 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_IMPL_H
#define INCLUDED_CRFA_DIFF_ADD_SYNC_DECIM_IMPL_H
#include <crfa/diff_add_sync_decim.h>
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 */

149
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 <gnuradio/io_signature.h>
#include "sync_decim_impl.h"
#define DECIM 2
#define lout log && std::cout
//#include <pmt.h>
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"<<std::endl;
lout<<"mode: "<<mode<<std::endl;
mode=COPY;
lout<<"mode: "<<mode<<std::endl;
}
}
int
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];
for (int i = 0; i < noutput_items; i++) {
if(mode==COPY){
out[i]=in[DECIM*i];
}
else if(mode==SKIP){
if(i==0){
out[i]=last_input-in[DECIM*i];}
else{
out[i]=in[DECIM*i-1]-in[DECIM*i];}
}
else if(mode==NOSKIP){
out[i]=in[DECIM*i]-in[DECIM*i+1];
}
}
last_input=in[(noutput_items-1)*DECIM+1];//to use for next iteration of work
//lout<<noutput_items<<std::endl;
/*SYNC:*/
if(mode==COPY){
float out_noskip;
float out_skip;
int skip_is_better_counter=0;
if (noutput_items>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:"<<out_noskip;
//lout<<"\t,out_skip:"<<out_skip<<std::endl;
}
if (skip_is_better_counter>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 */

55
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 <crfa/sync_decim.h>
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 */

105
python/rds_parser_table_qt.py

@ -394,13 +394,13 @@ class tmc_message:
#datetime.timedelta(hours=0.25) #datetime.timedelta(hours=0.25)
def getDuration(self):#returns string def getDuration(self):#returns string
if "D" in self.event.durationType and not self.event.nature=="F": 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": 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": 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": 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: else:
return "" return ""
#self.event.durationType #D,(D),L,(L) #self.event.durationType #D,(D),L,(L)
@ -429,28 +429,27 @@ class tmc_message:
else: else:
try: try:
multi="%i:%s"%(self.length,str(self.mgm_list)) 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: except AttributeError:
multi="[multi incomplete]" multi="[multi incomplete]"
return str(multi)
def info_str(self):
info=""
info+=self.getDuration()
if not self.cancellation_time==None: if not self.cancellation_time==None:
if language=="de": if language=="de":
multi+=" (aufgehoben um %s)"%self.cancellation_time info+=" (aufgehoben um %s)"%self.cancellation_time
else: else:
multi+=" (cancelled at %s)"%self.cancellation_time info+=" (cancelled at %s)"%self.cancellation_time
multi+="; "+self.getDuration() return info
return str(multi)
def events_string(self): def events_string(self):
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.psn return str(self.event.updateClass)+": "+self.getTime()+": "+self.location_text()+": "+self.events_string()+"; "+self.info_str()+"; "+self.psn
def db_string(self): 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): def map_string(self):
return str(self.event.updateClass)+": "+self.getTime()+": "+self.events_string()+"; "+self.multi_str()+"; "+self.psn return '<span title="%s">'%self.multi_str()+str(self.event.updateClass)+": "+self.getTime()+": "+self.events_string()+self.info_str()+"; "+self.psn+"</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):
@ -508,8 +507,8 @@ class tmc_message:
try: try:
msg_ltn=tableobj.RDS_data[PI]["AID_list"][52550]["LTN"] msg_ltn=tableobj.RDS_data[PI]["AID_list"][52550]["LTN"]
table_ltn=1#german table table_ltn=1#german table
if msg_ltn != table_ltn and tableobj.debug: if msg_ltn != table_ltn and tableobj.debug and False:#disabled, spams log
print("msg_ltn:%i does not match given table (1) on station: %s"%(msg_ltn,self.psn)) print("msg_ltn:%i does not match expected table (1) on station: %s"%(msg_ltn,self.psn))
except KeyError: except KeyError:
if tableobj.debug: if tableobj.debug:
print("no LTN found") print("no LTN found")
@ -648,6 +647,14 @@ class mgm_tag:#mgm=multi group message
,5:" Equivalent of diversion bit set to '1'." ,5:" Equivalent of diversion bit set to '1'."
,6:" Increase the number of steps in the problem extent by 8." ,6:" Increase the number of steps in the problem extent by 8."
,7:" Increase the number of steps in the problem extent by 16."} ,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 @staticmethod
def decode_time_date(raw):#label7/8 raw to datestring def decode_time_date(raw):#label7/8 raw to datestring
if raw<=95: if raw<=95:
@ -680,7 +687,7 @@ class mgm_tag:#mgm=multi group message
if(self.label==0): if(self.label==0):
return "duration: %i"%self.data.uint return "duration: %i"%self.data.uint
elif(self.label==1): 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): elif(self.label==2):
return "length affected: %i km"%self.length_to_km(self.data.uint) return "length affected: %i km"%self.length_to_km(self.data.uint)
elif(self.label==3): 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 if time.time()-self.minute_count_timer > 3:#every 3 second
self.minute_count_max=self.minute_count 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=0
self.minute_count_timer=time.time() self.minute_count_timer=time.time()
pr.enable()#disabled-internal-profiling #pr.enable()#disabled-internal-profiling
self.minute_count+=1 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: if self.writeDB:
#db=sqlite3.connect(self.db_name) #db=sqlite3.connect(self.db_name)
db=self.db db=self.db
@ -1135,7 +1143,8 @@ class rds_parser_table_qt(gr.sync_block):#START
paging=array[4]&0xf paging=array[4]&0xf
extended_country_code=array[5] extended_country_code=array[5]
self.RDS_data[PI]["ECC"]=extended_country_code 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: elif variant==1:
TMC_info=SLC TMC_info=SLC
elif variant==2: elif variant==2:
@ -1143,7 +1152,7 @@ class rds_parser_table_qt(gr.sync_block):#START
elif variant==3: elif variant==3:
language_codes=SLC language_codes=SLC
if self.debug: 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: elif variant==6:
#for use by broadcasters #for use by broadcasters
if self.debug: 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) textcolor=""#use default color (white if background is black)
l=list(self.RDS_data[PI]["RT_"+str(ab_flag)]["RT"]) 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 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) self.RDS_data[PI]["internals"]["RT_history"].append(l)
if len(self.RDS_data[PI]["internals"]["RT_history"])>10:#only store last 10 RTs if len(self.RDS_data[PI]["internals"]["RT_history"])>10:#only store last 10 RTs
self.RDS_data[PI]["internals"]["RT_history"].pop(0) 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]["groupType"]=app_group
self.RDS_data[PI]["AID_list"][AID]["app_name"]=app_name self.RDS_data[PI]["AID_list"][AID]["app_name"]=app_name
self.RDS_data[PI]["AID_list"][AID]["app_data"]=app_data 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: 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 #decode 3A group of TMC
if AID==52550:#TMC alert-c if AID==52550:#TMC alert-c (continuously update)
variant=app_data>>14 variant=app_data>>14
if variant==0: 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]["AFI"]=(app_data>>5)&0x1#alternative frequency indicator
self.RDS_data[PI]["AID_list"][AID]["M"]=(app_data>>4)&0x1#transmission mode indicator self.RDS_data[PI]["AID_list"][AID]["M"]=(app_data>>4)&0x1#transmission mode indicator
#Message Geographical Scope: #Message Geographical Scope:
self.RDS_data[PI]["AID_list"][AID]["I"]=(app_data>>3)&0x1#international (EUROROAD) self.RDS_data[PI]["AID_list"][AID]["scope"]=""
self.RDS_data[PI]["AID_list"][AID]["N"]=(app_data>>2)&0x1#national if (app_data>>3)&0x1==1:
self.RDS_data[PI]["AID_list"][AID]["R"]=(app_data>>1)&0x1#regional self.RDS_data[PI]["AID_list"][AID]["scope"]+="I"#international (EUROROAD)
self.RDS_data[PI]["AID_list"][AID]["U"]=(app_data>>0)&0x1#urban 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: elif variant==1:
self.RDS_data[PI]["AID_list"][AID]["SID"]=(app_data>>6)&0x3f#service identifier 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): #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 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])) segment=self.decode_chars(chr(array[4])+chr(array[5])+chr(array[6])+chr(array[7]))
if self.debug: 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) if adr== 7:#freq of tuned an mapped station (not seen yet)
freq_TN=tmc_y>>8 freq_TN=tmc_y>>8
freq_ON=tmc_y&0xff#mapped frequency freq_ON=tmc_y&0xff#mapped frequency
if self.debug: 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 self.RDS_data[PI]["TMC_TN"]=freq_TN
else: else:
if self.debug: 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): #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+ 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+"): 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 #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.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: 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 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 #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.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: 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 self.RDS_data[PI_ON]["AF"]["main"]=freq_ON
freq_str="EON:%0.1fM"% (freq_ON/1e6) freq_str="EON:%0.1fM"% (freq_ON/1e6)
self.signals.DataUpdateEvent.emit({'PI':PI_ON,'freq':freq_str}) 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] return_string+=alphabet[alnr][index]
except KeyError: except KeyError:
return_string+="?%02X?"%ord(char) return_string+="?%02X?"%ord(char)
print("symbol not decoded: "+"?%02X?"%ord(char)+"in string:"+return_string)
#charlist[i]='?'#symbol not decoded #TODO #charlist[i]='?'#symbol not decoded #TODO
pass pass
#return "".join(charlist) #return "".join(charlist)
@ -1716,7 +1744,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
label_layout.addWidget(self.count_label) label_layout.addWidget(self.count_label)
layout.addLayout(label_layout) layout.addLayout(label_layout)
#TODO set different minsize if TMC is shown #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: if self.showTMC:
self.tmc_message_label=QtGui.QLabel("TMC messages:") self.tmc_message_label=QtGui.QLabel("TMC messages:")
self.event_filter=QtGui.QLineEdit()#QPlainTextEdit ? self.event_filter=QtGui.QLineEdit()#QPlainTextEdit ?
@ -1933,6 +1961,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
scrollArea.setWidgetResizable(True) scrollArea.setWidgetResizable(True)
scrollArea.setWidget(l) scrollArea.setWidget(l)
view.layout().addWidget(scrollArea) view.layout().addWidget(scrollArea)
view.setWindowTitle(self.tableobj.RDS_data[PI]["PSN"])
view.exec_() view.exec_()
def onCLick(self): def onCLick(self):
print("button clicked") print("button clicked")

6
swig/crfa_swig.i

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

Loading…
Cancel
Save