diff --git a/grc/crfa_rds_parser_table_qt.xml b/grc/crfa_rds_parser_table_qt.xml
index 4422c6d..d1e819e 100644
--- a/grc/crfa_rds_parser_table_qt.xml
+++ b/grc/crfa_rds_parser_table_qt.xml
@@ -12,9 +12,15 @@
#set $label = '"%s"'%$id
#end if
$(signals) = rds_parser_table_qt_Signals()
-self.$(id) = crfa.rds_parser_table_qt($(signals),$nPorts)
+self.$(id) = crfa.rds_parser_table_qt($(signals),$nPorts,self.set_$(freq_tune),$freq_tune)
$(win) = rds_parser_table_qt_Widget($signals, $label,self.$(id))
$(gui_hint()($win))
+
+ tuned frequency
+ freq_tune
+
+ float
+
Label
label
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index a9cb4a4..a2dae5d 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -36,7 +36,8 @@ GR_PYTHON_INSTALL(
rds_table_qt.py
rds_parser_table_qt.py
max_freq.py
- smooth_vectors.py DESTINATION ${GR_PYTHON_DIR}/crfa
+ smooth_vectors.py
+ chart.py DESTINATION ${GR_PYTHON_DIR}/crfa
)
########################################################################
diff --git a/python/__init__.py b/python/__init__.py
index 520d1fd..4e4e423 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -37,4 +37,5 @@ from rds_table_qt import rds_table_qt
from rds_parser_table_qt import rds_parser_table_qt
from max_freq import max_freq
from smooth_vectors import smooth_vectors
+from chart import Chart
#
diff --git a/python/chart.py b/python/chart.py
index ce2132a..0bb97a4 100644
--- a/python/chart.py
+++ b/python/chart.py
@@ -1,3 +1,6 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+from gnuradio import gr
from itertools import cycle
from PyQt4.Qt import *
@@ -353,6 +356,9 @@ class DialogViewer(QDialog):
def __init__(self):
QDialog.__init__(self)
self.viewer = Viewer()
+ #self.viewer.resize(360, 240)
+ self.viewer.setMinimumSize(360,240)
+ #self.setMinimumSize(100,100)
self.setLayout(QVBoxLayout())
self.layout().setContentsMargins(0, 0, 0, 0)
self.layout().addWidget(self.viewer)
diff --git a/python/max_freq.py b/python/max_freq.py
index d8c2874..144c228 100644
--- a/python/max_freq.py
+++ b/python/max_freq.py
@@ -49,12 +49,15 @@ class max_freq(gr.sync_block):
#ii=input_items
carrier_width=2
carrier=self.fft_len/2
- numbers=np.delete(input_items[0][0],range(carrier-carrier_width,carrier+carrier_width+1))#reads input and disregards center
- #threshold=100 uni
+ numbers=np.delete(input_items[0][0],range(carrier-carrier_width,carrier+carrier_width+1))#read input and disregard center (hackrf LO)
+ #threshold=100# uni
threshold=80#home
#minimum number of consecutive maximums (in fft domain) to consider signal as station:
-# min_consec_max_threshold=1#uni
+ #min_consec_max_threshold=1#uni
min_consec_max_threshold=5#home
+ #fuzzyness=2#uni
+ fuzzyness=10#home
+
#TODO: what if no numbers over threshold?
#TODO auto threshold
#max_indices=[[421, 428, 429, 430, 431, 432, 433, 434, 436, 437, 438, 831, 832, 837, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851,852, 853, 854, 855, 856, 857]]
@@ -65,8 +68,7 @@ class max_freq(gr.sync_block):
#last_index=0
count=1#counts number of consecutive maximums
threshold_reached=False
- #fuzzyness=2#uni
- fuzzyness=10#home
+
# max_indices[0].append(0)#to detect last station
max_indices=np.append(max_indices,0)#to detect last station
#try:
diff --git a/python/rds_parser_table_qt.py b/python/rds_parser_table_qt.py
index 1e67cc2..3b5a7f4 100644
--- a/python/rds_parser_table_qt.py
+++ b/python/rds_parser_table_qt.py
@@ -23,7 +23,8 @@ import numpy
from gnuradio import gr
import pmt,functools,csv,md5,collections
from datetime import datetime
-import chart#local file
+import crfa.chart as chart
+
from PyQt4 import Qt, QtCore, QtGui
import pprint,code#for easier testing
pp = pprint.PrettyPrinter()
@@ -39,7 +40,7 @@ class rds_parser_table_qt(gr.sync_block):
"""
docstring for block qtguitest
"""
- def __init__(self,signals,nPorts):
+ def __init__(self,signals,nPorts,slot,freq):
#QObject.__init__()
gr.sync_block.__init__(self,
name="RDS Table",
@@ -52,6 +53,8 @@ class rds_parser_table_qt(gr.sync_block):
self.set_msg_handler(pmt.intern('freq'), self.set_freq)
self.signals=signals
self.RDS_data={}
+ self.change_freq_tune=slot
+ self.tuning_frequency=int(freq)
self.printcounter=0
self.ODA_application_names={}
self.TMC_data={}
@@ -91,9 +94,27 @@ class rds_parser_table_qt(gr.sync_block):
freq_str="%i:%0.1fM"% (decoder_num,freq/1e6)
except ValueError:
pass#leave string as is
+ 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})
#self.signals.DataUpdateEvent.emit({'row':decoder_num,'freq':freq_str})
#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"]["any"]=0
+ self.RDS_data[PI]["AID_list"]={}
+ self.RDS_data[PI]["PSN"]="_"*8
+ self.RDS_data[PI]["PSN_valid"]=[False]*8
+ self.RDS_data[PI]["AF"]={}
+ self.RDS_data[PI]["TP"]=-1
+ self.RDS_data[PI]["TA"]=-1
+ self.RDS_data[PI]["PTY"]=""
+ self.RDS_data[PI]["DI"]=[2,2,2,2]
+ self.RDS_data[PI]["internals"]={"last_rt_tooltip":""}
def handle_msg(self, msg, port):#port from 0 to 3
#code.interact(local=locals())
array=pmt.to_python(msg)[1]
@@ -108,26 +129,22 @@ class rds_parser_table_qt(gr.sync_block):
block2=(array[2]<<8)|(array[3]) #block2
PTY=(block2>>5)&0x1F
wrong_blocks=int(array[12])
- if self.decoder_frequencies.has_key(port):
- freq=self.decoder_frequencies[port]
- freq_str="%i:%0.1fM"% (port,freq/1e6)
- self.signals.DataUpdateEvent.emit({'PI':PI,'freq':freq_str})
#initialize dict 1st packet from station:
if not self.RDS_data.has_key(PI):
- self.RDS_data[PI]={}
- self.RDS_data[PI]["blockcounts"]={}
- self.RDS_data[PI]["blockcounts"]["any"]=0
- self.RDS_data[PI]["AID_list"]={}
- self.RDS_data[PI]["PSN"]="_"*8
- self.RDS_data[PI]["PSN_valid"]=[False]*8
- self.RDS_data[PI]["AF"]={}
- self.RDS_data[PI]["DI"]=[2,2,2,2]
- self.RDS_data[PI]["internals"]={"last_rt_tooltip":""}
+ self.init_data_for_PI(PI)
print("found station %s"%PI)
+
+ if self.decoder_frequencies.has_key(port):
+ freq=self.decoder_frequencies[port]
+ freq_str="%i:%0.1fM"% (port,freq/1e6)
+ self.RDS_data[PI]["tuned_freq"]=freq
+ #self.signals.DataUpdateEvent.emit({'PI':PI,'freq':freq_str})
self.RDS_data[PI]["blockcounts"]["any"]+=1
if self.RDS_data[PI]["blockcounts"]["any"]==5:
self.RDS_data[PI]["blockcounts"]["any"]=0
dots="."*self.RDS_data[PI]["blockcounts"]["any"]
+ self.RDS_data[PI]["TP"]=TP
+ self.RDS_data[PI]["PTY"]=self.pty_dict[PTY]
self.signals.DataUpdateEvent.emit({'row':port,'PI':PI,'PTY':self.pty_dict[PTY],'TP':TP,'wrong_blocks':wrong_blocks,'dots':dots})
if (groupType == "0A"):#AF PSN
adr=array[3]&0b00000011
@@ -140,6 +157,7 @@ class rds_parser_table_qt(gr.sync_block):
#d3 Static PTY Dynamic PTY
TA=(array[3]>>4)&0x1
MS=(array[3]>>3)&0x1
+ self.RDS_data[PI]["TA"]=TA
flag_string="TP:%i, TA:%i, MS:%i, DI:%s"%(TP,TA,MS,str(self.RDS_data[PI]["DI"]))
self.signals.DataUpdateEvent.emit({'row':port,'PI':PI,'flags':flag_string})
@@ -147,10 +165,23 @@ class rds_parser_table_qt(gr.sync_block):
#225 1110 0001 = 1AF
#249 1111 1001 = 25AF
fillercode=205#1100 1101
-
+ if not self.RDS_data[PI]["AF"].has_key("main") and self.RDS_data[PI].has_key("tuned_freq"):
+ freq=self.decode_AF_freq(array[4])
+ if freq==self.RDS_data[PI]["tuned_freq"]:
+ self.RDS_data[PI]["AF"]["main"]=freq
+ 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
+ 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})
if(array[4]>= 224 and array[4]<= 249):
#print("AF1 detected")
self.RDS_data[PI]["AF"]['number']=array[4]-224
+ #self.RDS_data[PI]["AF"]['main']=self.decode_AF_freq(array[5])
self.signals.DataUpdateEvent.emit({'row':port,'PI':PI,'AF':self.RDS_data[PI]["AF"]})
if(array[5]>= 224 and array[5]<= 249):
print("AF2 detected (shouldn't happen)")
@@ -435,19 +466,73 @@ class rds_parser_table_qt(gr.sync_block):
TP_ON=(array[3]>>4)&0x1
PI_ON="%02X%02X" %(array[6],array[7])
variant=array[3]&0xf
+ self.signals.DataUpdateEvent.emit({'PI':PI_ON,'TP':TP_ON})
+ if not self.RDS_data.has_key(PI_ON):
+ self.init_data_for_PI(PI_ON)
+ self.RDS_data[PI_ON]["TP"]=TP_ON
+ 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]={}
self.RDS_data[PI]["EON"][PI_ON]["PSN"]="_"*8
if variant in range(4):#variant 0..3 -> PS_ON
segment=self.decode_chars(chr(array[4])+chr(array[5]))
- name_list=list(self.RDS_data[PI]["EON"][PI_ON]["PSN"])
+ name_list=list(self.RDS_data[PI_ON]["PSN"])
+ #name_list=list(self.RDS_data[PI]["EON"][PI_ON]["PSN"])
name_list[variant*2:variant*2+2]=segment
- self.RDS_data[PI]["EON"][PI_ON]["PSN"]="".join(name_list)
+ if (name_list[variant*2:variant*2+2]==list(segment)):#segment already there
+ segmentcolor="purple"
+ elif(name_list[variant*2:variant*2+2]==['_']*2): #segment new
+ segmentcolor="purple"
+ name_list[variant*2:variant*2+2]=segment
+ else:#name changed (böse)
+ segmentcolor="red"
+ name_list=['_']*8 #reset name
+ name_list[variant*2:variant*2+2]=segment
+ #reset stored text:
+ self.RDS_data[PI_ON]["PSN"]="_"*8
+ self.RDS_data[PI_ON]["PSN_valid"]=[False]*8
+ self.RDS_data[PI_ON]["PSN_valid"][variant*2:variant*2+2]=[True] *2
+ PS_ON_str="".join(name_list)
+ self.RDS_data[PI_ON]["PSN"]=PS_ON_str
+ self.RDS_data[PI]["EON"][PI_ON]["PSN"]=PS_ON_str
+ #determine if text is valid
+ valid=True
+ for i in range(0,8):
+ if (not self.RDS_data[PI_ON]["PSN_valid"][i]):
+ valid = False
+ if(valid):
+ textcolor="black"
+ else:
+ textcolor="gray"
+ formatted_text=self.color_text(self.RDS_data[PI_ON]["PSN"],variant*2,variant*2+2,textcolor,segmentcolor)
+ self.RDS_data[PI]["EON"][PI_ON]["PSN"]=PS_ON_str
+ self.RDS_data[PI_ON]["PSN"]=PS_ON_str
+ #formatted_text="%s"%("purple",PS_ON_str)
+ self.signals.DataUpdateEvent.emit({'PI':PI_ON,'PSN':formatted_text})
+ if variant==4:#AF_ON
+ 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")):
+ 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")):
+ 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)
+ self.signals.DataUpdateEvent.emit({'PI':PI_ON,'freq':freq_str})
+ #print("mapped freq in variant %i:, %i->%i"%(variant,freq_TN,freq_ON))
if variant==13:#PTY and TA of ON
PTY_ON=array[4]>>3
TA_ON=array[5]&0x1
self.RDS_data[PI]["EON"][PI_ON]["TA_ON"]=TA_ON
self.RDS_data[PI]["EON"][PI_ON]["PTY_ON"]=PTY_ON
+ self.RDS_data[PI_ON]["TA"]=TA_ON
+ self.RDS_data[PI_ON]["PTY"]=self.pty_dict[PTY_ON]
+ self.signals.DataUpdateEvent.emit({'PI':PI_ON,'PTY':self.pty_dict[PTY_ON],'TA':TA_ON})
#rest is reserved
if variant==14:#programme item number of ON
PIN_ON=(array[4]<<8)|(array[5])
@@ -474,7 +559,13 @@ class rds_parser_table_qt(gr.sync_block):
print("RT+:",end="")
pp.pprint(self.RDS_data[key]["RT+"])
self.printcounter=0
- #print("group of type %s not decoded on station %s"% (groupType,PI))
+ #print("group of type %s not decoded on station %s"% (groupType,PI))
+ def decode_AF_freq(self,freq_raw):
+ if freq_raw in range(1,205):#1..204
+ return(87500000+freq_raw*100000)#returns int
+ #return(87.5e6+freq_raw*0.1e6)#returns float
+ else:
+ return(0)
def ref_locs(self,loc,name_string):
if(loc==34196):#europe
return(name_string)
@@ -570,7 +661,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
layout.addWidget(self.table)
self.table.setHorizontalHeaderLabels(horHeaders)
- self.table.setMaximumHeight(250)#TODO use dynamic value
+ #self.table.setMaximumHeight(300)#TODO use dynamic value
self.tmc_message_label=QtGui.QLabel("TMC messages:")
@@ -581,7 +672,8 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
button = QtGui.QPushButton("code.interact")
button.clicked.connect(self.onCLick)
layout.addWidget(button)
-
+ self.freq_label=QtGui.QLabel("decoder frequencies:")
+ layout.addWidget(self.freq_label)
filter_layout = Qt.QHBoxLayout()
filter_layout.addWidget(QtGui.QLabel("event filter:"))
filter_layout.addWidget(self.event_filter)
@@ -593,7 +685,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
self.logOutput = Qt.QTextEdit()
self.logOutput.setReadOnly(True)
self.logOutput.setLineWrapMode(Qt.QTextEdit.NoWrap)
- #self.logOutput.setMaximumHeight(100)
+ self.logOutput.setMaximumHeight(150)
font = self.logOutput.font()
font.setFamily("Courier")
font.setPointSize(10)
@@ -608,7 +700,8 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
button.clicked.connect(functools.partial(self.getDetails, row=rowPosition))
def display_data(self, event):
#pp.pprint(event)
-
+ if type(event)==dict and event.has_key('decoder_frequencies'):
+ self.freq_label.setText(event['decoder_frequencies'])
if type(event)==dict and event.has_key('TMC_log'):
ef=unicode(self.event_filter.text().toUtf8(), encoding="UTF-8").lower()
lf=unicode(self.location_filter.text().toUtf8(), encoding="UTF-8").lower()
@@ -686,7 +779,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
view = chart.DialogViewer()
view.setGraph(mychart)
#view.resize(360, 240)
- view.resize(380, 500)
+ #view.resize(380, 550)
rds_data=self.tableobj.RDS_data[PI].copy()
try:
del rds_data['blockcounts']
@@ -699,10 +792,12 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
l.setWordWrap(True)
#l=QtGui.QLabel("Data:")
view.layout().addWidget(l)
+ #code.interact(local=locals())
view.exec_()
def onCLick(self):
print("button clicked")
code.interact(local=locals())
+ #self.logOutput.clear()
#self.reset_color()
#pp.pprint(event)
if __name__ == "__main__":