Browse Source

Fixed decode freq jumping back and forth,fixed rt+ history (deepcopy), consistant piechart colors via defaults, debud and log parameters, fixed unknown symbol crash, fixed smooth_vectors decimation

master
Clemens Richter 9 years ago
parent
commit
4477d3f926
  1. 4
      cmake/Modules/.directory
  2. 18
      grc/crfa_max_freq.xml
  3. 31
      grc/crfa_rds_parser_table_qt.xml
  4. 21
      python/max_freq.py
  5. 67
      python/rds_parser_table_qt.py
  6. 17
      python/smooth_vectors.py

4
cmake/Modules/.directory

@ -0,0 +1,4 @@
[Dolphin]
Timestamp=2016,12,6,13,18,42
Version=3
ViewMode=2

18
grc/crfa_max_freq.xml

@ -4,7 +4,7 @@
<key>crfa_max_freq</key>
<category>[crfa]</category>
<import>import crfa</import>
<make>crfa.max_freq($fft_len, $num_decoders, $center_freq, $samp_rate,$round_to)</make>
<make>crfa.max_freq($fft_len, $num_decoders, $center_freq, $samp_rate,$round_to,$debug)</make>
<!-- Make one 'param' node for every Parameter you want settable from the GUI.
Sub-nodes:
* name
@ -25,6 +25,7 @@
<name>number of decoders</name>
<key>num_decoders</key>
<type>int</type>
<hide>part</hide>
</param>
<param>
<name>center frequency</name>
@ -36,6 +37,21 @@
<key>samp_rate</key>
<type>int</type>
</param>
<param>
<name>Debug</name>
<key>debug</key>
<value>False</value>
<type>bool</type>
<hide>part</hide>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<!-- Make one 'sink' node per input. Sub-nodes:

31
grc/crfa_rds_parser_table_qt.xml

@ -12,9 +12,10 @@
#set $label = '"%s"'%$id
#end if
$(signals) = rds_parser_table_qt_Signals()
self.$(id) = crfa.rds_parser_table_qt($(signals),$nPorts,self.set_$(freq_tune),$freq_tune)
self.$(id) = crfa.rds_parser_table_qt($(signals),$nPorts,self.set_$(freq_tune),$freq_tune,$log, $debug)
$(win) = rds_parser_table_qt_Widget($signals, $label,self.$(id))
$(gui_hint()($win))</make>
<callback>set_freq_tune($freq_tune);</callback>
<param>
<name>tuned frequency</name>
<key>freq_tune</key>
@ -42,6 +43,34 @@ $(gui_hint()($win))</make>
<type>int</type>
<hide>part</hide>
</param>
<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>message</type>

21
python/max_freq.py

@ -27,7 +27,7 @@ class max_freq(gr.sync_block):
"""
docstring for block max_freq
"""
def __init__(self, fft_len=1024,num_decoders=4,center_freq=0,samp_rate=0,round_to=100e3):
def __init__(self, fft_len=1024,num_decoders=4,center_freq=0,samp_rate=0,round_to=100e3,debug=False):
gr.sync_block.__init__(self,
name="max_freq",
in_sig=[(np.float32,fft_len)],
@ -37,6 +37,8 @@ class max_freq(gr.sync_block):
self.center_freq=center_freq
self.samp_rate=samp_rate
self.snapto=round_to
self.debug=debug
self.last_station_freqs=[]
self.message_port_register_out(pmt.intern('out'))
def set_center_freq(self, freq=None):
if freq is not None:
@ -90,23 +92,34 @@ class max_freq(gr.sync_block):
if count>=min_consec_max_threshold:
threshold_reached=True
last_index=i
#sort station_indices by signal strength
station_indices_sorted=sorted(station_indices,key=lambda elem:numbers[elem],reverse=True)
#sort station_indices by signal strength (dont bother decoding quiet stations)
station_indices_sorted=sorted(station_indices,reverse=True,key=lambda elem:numbers[elem])
#prevents back and forth switching if two station have similar signal strength
station_indices_tune=list(station_indices_sorted)#copy list
del station_indices_tune[self.num_decoders:]#remove non decodable incidices
station_indices_tune.sort()
station_strength=[]
station_freqs=[]
#index to freq:
for index in station_indices_sorted:
for index in station_indices_tune:
startfreq=self.center_freq-self.samp_rate/2
freq=self.samp_rate*index/self.fft_len+startfreq
num_decimals=int(round(math.log(self.snapto,10)))
station_freqs.append(round(freq,-num_decimals))
station_strength.append(round(numbers[index],-2))
for i in range(0,min(self.num_decoders,len(station_freqs))):
msg_string=str(i+1)+" "+str(station_freqs[i])
send_pmt = pmt.string_to_symbol(msg_string)
self.message_port_pub(pmt.intern('out'), send_pmt)
if self.debug:
print(max_indices)
print(station_indices_sorted)
print(station_indices_tune)
print(station_strength)
print(station_freqs)
self.last_station_freqs=station_freqs
return len(input_items[0])

67
python/rds_parser_table_qt.py

@ -21,7 +21,7 @@
from __future__ import print_function#print without newline print('.', end="")
import numpy
from gnuradio import gr
import pmt,functools,csv,md5,collections
import pmt,functools,csv,md5,collections,copy
from datetime import datetime
import crfa.chart as chart
@ -40,7 +40,7 @@ class rds_parser_table_qt(gr.sync_block):
"""
docstring for block qtguitest
"""
def __init__(self,signals,nPorts,slot,freq):
def __init__(self,signals,nPorts,slot,freq,log,debug):
#QObject.__init__()
gr.sync_block.__init__(self,
name="RDS Table",
@ -51,6 +51,8 @@ class rds_parser_table_qt(gr.sync_block):
self.set_msg_handler(pmt.intern('in%d'%i), functools.partial(self.handle_msg, port=i))
self.message_port_register_in(pmt.intern('freq'))
self.set_msg_handler(pmt.intern('freq'), self.set_freq)
self.log=log
self.debug=debug
self.signals=signals
self.RDS_data={}
self.change_freq_tune=slot
@ -60,9 +62,10 @@ class rds_parser_table_qt(gr.sync_block):
self.TMC_data={}
self.decoder_frequencies={}
self.colorder=['ID','freq','name','PTY','AF','time','text','quality','buttons']
#workdir="/user/wire2/richter/hackrf_prototypes/"
workdir="/media/clemens/intdaten/uni_bulk/forschungsarbeit/hackrf_prototypes/"
reader = csv.reader(open(workdir+'RDS_ODA AIDs_names_only.csv'), delimiter=',', quotechar='"')
#workdir=""
workdir="/user/wire2/richter/hackrf_prototypes/"
#workdir="/media/clemens/intdaten/uni_bulk/forschungsarbeit/hackrf_prototypes/"
reader = csv.reader(open(workdir+'RDS_ODA-AIDs_names_only.csv'), delimiter=',', quotechar='"')
reader.next()#skip header
for row in reader:
self.ODA_application_names[int(row[0])]=row[1]
@ -84,6 +87,14 @@ class rds_parser_table_qt(gr.sync_block):
reader.next()#skip header
self.pty_dict=dict((int(rows[0]),rows[1]) for rows in reader)
f.close()
def set_freq_tune(self,freq):
self.tuning_frequency=int(freq)
message_string="decoder frequencies:"
for num in self.decoder_frequencies:
freq=self.decoder_frequencies[num]
message_string+="\t %i:%0.1fM"% (num,freq/1e6)
message_string+="\t tuned frequency:%0.1fM"%(self.tuning_frequency/1e6)
self.signals.DataUpdateEvent.emit({'decoder_frequencies':message_string})
def set_freq(self,msg):
m = pmt.symbol_to_string(msg)
decoder_num=int(m.split()[0])-1#msgs are 1-indexed, decoder_num is 0-indexed
@ -104,7 +115,9 @@ class rds_parser_table_qt(gr.sync_block):
#print("nr:%i freq:%s"%(tgtnum,freq_str))
def init_data_for_PI(self,PI):
self.RDS_data[PI]={}
self.RDS_data[PI]["blockcounts"]={}
#self.RDS_data[PI]["blockcounts"]={}# no defaults (works aswell)
#defaults are to keep colors in piechart consistent between stations:
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"]={}
self.RDS_data[PI]["PSN"]="_"*8
@ -132,6 +145,7 @@ class rds_parser_table_qt(gr.sync_block):
#initialize dict 1st packet from station:
if not self.RDS_data.has_key(PI):
self.init_data_for_PI(PI)
if self.log:
print("found station %s"%PI)
if self.decoder_frequencies.has_key(port):
@ -169,12 +183,14 @@ class rds_parser_table_qt(gr.sync_block):
freq=self.decode_AF_freq(array[4])
if freq==self.RDS_data[PI]["tuned_freq"]:
self.RDS_data[PI]["AF"]["main"]=freq
if self.log:
print("main frequency found in 0A: station:%s, freq:%0.1fM"% (self.RDS_data[PI]["PSN"],freq/1e6))
freq_str="0A:%0.1fM"% (freq/1e6)
self.signals.DataUpdateEvent.emit({'PI':PI,'freq':freq_str})
freq=self.decode_AF_freq(array[5])
if freq==self.RDS_data[PI]["tuned_freq"]:
self.RDS_data[PI]["AF"]["main"]=freq
if self.log:
print("main frequency found in 0A: station:%s, freq:%0.1fM"% (self.RDS_data[PI]["PSN"],freq/1e6))
freq_str="0A:%0.1fM"% (freq/1e6)
self.signals.DataUpdateEvent.emit({'PI':PI,'freq':freq_str})
@ -229,6 +245,7 @@ class rds_parser_table_qt(gr.sync_block):
language_codes=SLC
elif variant==6:
#for use by broadcasters
if self.debug:
print("PI:%s PSN:%s uses variant 6 of 1A"%(PI,self.RDS_data[PI]["PSN"]))
elif variant==7:
ESW_channel_identification=SLC
@ -298,11 +315,17 @@ class rds_parser_table_qt(gr.sync_block):
app_group=str(app_group_raw >> 1)+"B"
if not self.RDS_data[PI]["AID_list"].has_key(AID):#new ODA found
try:
app_name=self.ODA_application_names[AID]
except KeyError:
if self.debug:
print("ERROR: ODA-app-id (AID) '%i' not found in list on station %s, app group:%s"%(AID,app_group,PI))
app_name="unknown"
self.RDS_data[PI]["AID_list"][AID]={}
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 self.log:
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
@ -321,7 +344,7 @@ class rds_parser_table_qt(gr.sync_block):
activity_time=(app_data>>4)&0x3
window_time=(app_data>>2)&0x3
delay_time=(app_data>>0)&0x3
else:
elif self.debug:
print("unknown variant %i in TMC 3A group"%variant)
elif (groupType == "4A"):#CT clock time
datecode=((array[3] & 0x03) << 15) | (array[4] <<7)|((array[5] >> 1) & 0x7f)
@ -393,13 +416,16 @@ class rds_parser_table_qt(gr.sync_block):
if 4 <= adr and adr <= 9:
#seen variants 4569, 6 most often
#print("TMC-info variant:%i"%adr)
if adr== 7:
freq=tmc_y>>8
print("TMC-info: TN:%i"%freq)
self.RDS_data[PI]["TMC_TN"]=freq
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)
self.RDS_data[PI]["TMC_TN"]=freq_TN
else:
a=0
print("alert plus")
if self.debug:
print("alert plus")#(not seen yet)
#RadioText+ (grouptype mostly 12A):
@ -426,9 +452,10 @@ class rds_parser_table_qt(gr.sync_block):
tag2_len=int(tag2&(2**5-1))
if not self.RDS_data[PI]["RT+"]["last_item_toggle_bit"] == item_toggle_bit: #new item
#self.RDS_data[PI]["RT+"]["history"][str(datetime.now())]=self.RDS_data[PI]["internals"]["last_rt_tooltip"]
self.RDS_data[PI]["RT+_history"][str(datetime.now())]=self.RDS_data[PI]["RT+"]#save old item
self.RDS_data[PI]["RT+_history"][str(datetime.now())]=copy.deepcopy(self.RDS_data[PI]["RT+"])#save old item
self.RDS_data[PI]["RT+"]["last_item_toggle_bit"] = item_toggle_bit
rtcol=self.colorder.index('text')
if self.debug:
print("toggle bit changed on PI:%s, cleared RT-tt"%PI)
self.signals.DataUpdateEvent.emit({'col':rtcol,'row':port,'PI':PI,'tooltip':""})
if self.RDS_data[PI].has_key("RT"):
@ -470,6 +497,7 @@ class rds_parser_table_qt(gr.sync_block):
if not self.RDS_data.has_key(PI_ON):
self.init_data_for_PI(PI_ON)
self.RDS_data[PI_ON]["TP"]=TP_ON
if self.log:
print("found station %s via EON on station %s"%(PI_ON,PI))
if not self.RDS_data[PI]["EON"].has_key(PI_ON):
self.RDS_data[PI]["EON"][PI_ON]={}
@ -510,16 +538,19 @@ class rds_parser_table_qt(gr.sync_block):
#formatted_text="<font face='Courier New' color='%s'>%s</font>"%("purple",PS_ON_str)
self.signals.DataUpdateEvent.emit({'PI':PI_ON,'PSN':formatted_text})
if variant==4:#AF_ON
if self.debug:
print("AF_ON method A")#TODO
if variant in range(5,10):#variant 5..9 -> mapped freqs
freq_TN=self.decode_AF_freq(array[4])
freq_ON=self.decode_AF_freq(array[5])
#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))
self.RDS_data[PI]["AF"]["main"]=freq_TN
#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))
self.RDS_data[PI_ON]["AF"]["main"]=freq_ON
freq_str="EON:%0.1fM"% (freq_ON/1e6)
@ -538,15 +569,15 @@ class rds_parser_table_qt(gr.sync_block):
PIN_ON=(array[4]<<8)|(array[5])
#else:#other group
if 1==1:
#printdelay=50
printdelay=500
self.printcounter+=0#printing disabled
if self.RDS_data[PI]["blockcounts"].has_key(groupType):
self.RDS_data[PI]["blockcounts"][groupType] +=1 #increment
else:
self.RDS_data[PI]["blockcounts"][groupType] = 1 #initialize (1st group of this type)
if self.printcounter == printdelay:
#printdelay=50
printdelay=500
self.printcounter+=0#printing disabled
if self.printcounter == printdelay and self.debug:
#code.interact(local=locals())
for key in self.RDS_data:
if self.RDS_data[key].has_key("PSN"):
@ -598,7 +629,7 @@ class rds_parser_table_qt(gr.sync_block):
try:
charlist[i]=alphabet[alnr][index]
except KeyError:
charlist[i]=char
charlist[i]='?'#symbol not decoded #TODO
pass
return "".join(charlist)
def color_text(self, text, start,end,textcolor,segmentcolor):

17
python/smooth_vectors.py

@ -21,6 +21,7 @@
import numpy as np
from gnuradio import gr
import code
class smooth_vectors(gr.decim_block):
"""
@ -30,22 +31,30 @@ class smooth_vectors(gr.decim_block):
gr.decim_block.__init__(self,
name="smooth_vectors",
in_sig=[(np.float32,vec_len)],
out_sig=[(np.float32,vec_len)], decim=decim)
out_sig=[(np.float32,vec_len)],
decim=decim)
self.vec_len=vec_len
self.decim=decim
self.moving_avg_len=moving_avg_len
self.last_inputs=[]
self.count=0
#self.count=1
def work(self, input_items, output_items):
in0 = input_items[0]
in0 = input_items[0]#0th input port?
out = output_items[0]
self.last_inputs.insert(0,in0)
#self.last_inputs.insert(0,in0)
#code.interact(local=locals())
for i in range(0,self.decim):
self.last_inputs.insert(0,in0[i])
out[:] =np.mean( np.array(self.last_inputs), axis=0 )
# <+signal processing here+>
if len(self.last_inputs)>self.moving_avg_len:
self.last_inputs.pop(len(self.last_inputs)-1)#remove last
#out[:] = in0
#self.count += 1
return len(output_items[0])

Loading…
Cancel
Save