Browse Source

max freq block test, rt+ item_toggle_bit clears data

master
Clemens Richter 9 years ago
parent
commit
dc2059f448
  1. 3
      grc/CMakeLists.txt
  2. 51
      grc/crfa_max_freq.xml
  3. 45
      grc/rds_decoder.xml
  4. 3
      python/CMakeLists.txt
  5. 1
      python/__init__.py
  6. 119
      python/max_freq.py
  7. 35
      python/qtguitest.py
  8. 28
      python/rds_parser_table_qt.py

3
grc/CMakeLists.txt

@ -21,5 +21,6 @@ install(FILES
crfa_qtguitest.xml crfa_qtguitest.xml
crfa_rds_table_qt.xml crfa_rds_table_qt.xml
crfa_rds_parser_table_qt.xml crfa_rds_parser_table_qt.xml
crfa_rds_decoder.xml DESTINATION share/gnuradio/grc/blocks crfa_rds_decoder.xml
crfa_max_freq.xml DESTINATION share/gnuradio/grc/blocks
) )

51
grc/crfa_max_freq.xml

@ -0,0 +1,51 @@
<?xml version="1.0"?>
<block>
<name>max_freq</name>
<key>crfa_max_freq</key>
<category>[crfa]</category>
<import>import crfa</import>
<make>crfa.max_freq($fft_len, $num_decoders, $center_freq, $samp_rate)</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>fft_len</name>
<key>fft_len</key>
<type>int</type>
</param>
<param>
<name>num_decoders</name>
<key>num_decoders</key>
<type>int</type>
</param>
<param>
<name>center_freq</name>
<key>center_freq</key>
<type>float</type>
</param>
<param>
<name>samp_rate</name>
<key>samp_rate</key>
<type>int</type>
</param>
<!-- 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>
<vlen>$fft_len</vlen>
</sink>
<source>
<name>out</name>
<type>message</type>
<optional>1</optional>
</source>
</block>

45
grc/rds_decoder.xml

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

3
python/CMakeLists.txt

@ -34,7 +34,8 @@ GR_PYTHON_INSTALL(
multi_rds_printer.py multi_rds_printer.py
qtguitest.py qtguitest.py
rds_table_qt.py rds_table_qt.py
rds_parser_table_qt.py DESTINATION ${GR_PYTHON_DIR}/crfa rds_parser_table_qt.py
max_freq.py DESTINATION ${GR_PYTHON_DIR}/crfa
) )
######################################################################## ########################################################################

1
python/__init__.py

@ -35,4 +35,5 @@ from multi_rds_printer import multi_rds_printer
from qtguitest import qtguitest from qtguitest import qtguitest
from rds_table_qt import rds_table_qt from rds_table_qt import rds_table_qt
from rds_parser_table_qt import rds_parser_table_qt from rds_parser_table_qt import rds_parser_table_qt
from max_freq import max_freq
# #

119
python/max_freq.py

@ -0,0 +1,119 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2016 <+YOU OR YOUR COMPANY+>.
#
# This is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
import numpy as np
from gnuradio import gr
import code
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):
gr.sync_block.__init__(self,
name="max_freq",
in_sig=[(np.float32,fft_len)],
out_sig=None)
self.fft_len=fft_len
self.num_decoders=num_decoders
self.center_freq=center_freq
self.samp_rate=samp_rate
self.num_averages=5
self.avg_counter=-1
self.numbers_avg=[]
def work(self, input_items, output_items):
#in0 = input_items[0]
#ii=input_items
numbers=abs(input_items[0][0])
threshold=6
if self.avg_counter == -1: #init
self.numbers_avg=numbers
self.avg_counter=0
elif self.avg_counter <= self.num_averages:
#np.mean( np.array([ old_set, new_set ]), axis=0 )
self.numbers_avg=np.mean( np.array([ self.numbers_avg, numbers ]), axis=0 )
self.avg_counter+=1
elif len(np.where(self.numbers_avg>threshold)[0]) >0:
self.avg_counter=0
numbers=self.numbers_avg
min_consec_max_threshold=4#minimum number of consecutive maximums (in fft domain) to consider signal as station
#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]]
max_indices=np.where(numbers>threshold)
station_indices=[]
last_index=max_indices[0][0]
#last_index=0
count=1#counts number of consecutive maximums
threshold_reached=False
fuzzyness=10
# max_indices[0].append(0)#to detect last station
max_indices=np.append(max_indices,0)#to detect last station
for i in max_indices:
if abs(i-last_index) <= fuzzyness:
count+=i-last_index
else:#last streak ended
if(threshold_reached):
station_indices.append(last_index-int(count/2))#use center of max-streak
threshold_reached=False
count=1
else:#last streak didn't reach threshold -> no station
count=1
if count==min_consec_max_threshold:
threshold_reached=True
last_index=i
station_freqs=[]
#index to freq:
for index in station_indices:
startfreq=self.center_freq-self.samp_rate/2
freq=self.samp_rate*index/self.fft_len+startfreq
station_freqs.append(freq)
"""
[422 423 426 427 428 430 431 432 433 434 435 436 437 836 837 838 842 843
844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 861 862
0]
[]
[]
[423 424 425 426 427 428 429 430 431 432 433 434 842 843 844 845 848 849
850 851 852 853 854 855 858 859 860 0]
[428, 851]
[101303125.0, 102294531.0]
[415 416 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
844 845 846 847 848 849 850 851 852 853 854 855 856 861 862 863 0]
[853]
[102299218.0]
"""
#f=open("/tmp/obj","r")
#import pickle
#pickle.load(ii,f)
#(array([431, 433, 437, 439, 849, 854, 856, 858, 861, 862]),)
#code.interact(local=locals())
# <+signal processing here+>
print(max_indices)
print(station_indices)
print(station_freqs)
return len(input_items[0])

35
python/qtguitest.py

@ -99,7 +99,28 @@ class CRWidget(QtGui.QWidget):
layout.addWidget(self.table) layout.addWidget(self.table)
self.table.setHorizontalHeaderLabels(horHeaders) self.table.setHorizontalHeaderLabels(horHeaders)
self.table.setMaximumHeight(250)#TODO use dynamic value
test="""
adkasldjkasd
#ad
asd
as
d
asd
asdas
d
as
f
as
fa
sfasfasfasfasofsa
afasfasf
"""
self.tmc_message_label=QtGui.QLabel("TMC messages:") self.tmc_message_label=QtGui.QLabel("TMC messages:")
#self.tmc_message_label.setTextInteractionFlags(QtCore.Qt.TextSelectableByKeyboard|QtCore.Qt.TextSelectableByMouse)
#self.tmc_message_label.setMaximumHeight(100)
self.event_filter=QtGui.QLineEdit()#QPlainTextEdit ? self.event_filter=QtGui.QLineEdit()#QPlainTextEdit ?
self.location_filter=QtGui.QLineEdit() self.location_filter=QtGui.QLineEdit()
@ -113,10 +134,20 @@ class CRWidget(QtGui.QWidget):
filter_layout.addWidget(QtGui.QLabel("location filter:")) filter_layout.addWidget(QtGui.QLabel("location filter:"))
filter_layout.addWidget(self.location_filter) filter_layout.addWidget(self.location_filter)
#self.filter_label.setLayout(filter_layout) #self.filter_label.setLayout(filter_layout)
self.tmc_message_label.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)
#self.tmc_message_label.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
layout.addLayout(filter_layout) layout.addLayout(filter_layout)
layout.addWidget(self.tmc_message_label) layout.addWidget(self.tmc_message_label)
self.logOutput = Qt.QTextEdit(test)
self.logOutput.setReadOnly(True)
self.logOutput.setLineWrapMode(Qt.QTextEdit.NoWrap)
self.logOutput.setMaximumHeight(100)
font = self.logOutput.font()
font.setFamily("Courier")
font.setPointSize(10)
layout.addWidget(self.logOutput)
def display_data(self, event): def display_data(self, event):

28
python/rds_parser_table_qt.py

@ -102,6 +102,7 @@ class rds_parser_table_qt(gr.sync_block):
self.RDS_data[PI]["PSN_valid"]=[False]*8 self.RDS_data[PI]["PSN_valid"]=[False]*8
self.RDS_data[PI]["AF"]={} self.RDS_data[PI]["AF"]={}
self.RDS_data[PI]["DI"]=[2,2,2,2] self.RDS_data[PI]["DI"]=[2,2,2,2]
self.RDS_data[PI]["last_item_toggle_bit"]=2
print("found station %s"%PI) print("found station %s"%PI)
self.RDS_data[PI]["blockcounts"]["any"]+=1 self.RDS_data[PI]["blockcounts"]["any"]+=1
if self.RDS_data[PI]["blockcounts"]["any"]==5: if self.RDS_data[PI]["blockcounts"]["any"]==5:
@ -285,7 +286,8 @@ class rds_parser_table_qt(gr.sync_block):
if not self.TMC_data.has_key(tmc_hash):#if message new if not self.TMC_data.has_key(tmc_hash):#if message new
message_string="TMC-message,event:%s location:%i,reflocs:%s, station:%s"%(event_name,tmc_location,self.ref_locs(tmc_location,""),self.RDS_data[PI]["PSN"]) message_string="TMC-message,event:%s location:%i,reflocs:%s, station:%s"%(event_name,tmc_location,self.ref_locs(tmc_location,""),self.RDS_data[PI]["PSN"])
self.TMC_data[tmc_hash]={"PI":PI,"string":message_string} self.TMC_data[tmc_hash]={"PI":PI,"string":message_string}
print(message_string) self.signals.DataUpdateEvent.emit({'TMC_log':message_string})
#print(message_string)
except KeyError: except KeyError:
#print("location '%i' not found"%tmc_location) #print("location '%i' not found"%tmc_location)
pass pass
@ -330,12 +332,16 @@ class rds_parser_table_qt(gr.sync_block):
rt=self.RDS_data[PI]["RT"] rt=self.RDS_data[PI]["RT"]
artist=rt[tag1_start:tag1_start+tag1_len+1] artist=rt[tag1_start:tag1_start+tag1_len+1]
song=rt[tag2_start:tag2_start+tag2_len+1] song=rt[tag2_start:tag2_start+tag2_len+1]
formatted_text="%s by %s"%(song,artist) formatted_text="%s by %s %i"%(song,artist,item_running_bit)
rtcol=self.colorder.index('text') rtcol=self.colorder.index('text')
self.signals.DataUpdateEvent.emit({'col':rtcol,'row':port,'PI':PI,'tooltip':formatted_text}) self.signals.DataUpdateEvent.emit({'col':rtcol,'row':port,'PI':PI,'tooltip':formatted_text})
#self.signals.DataUpdateEvent.emit({'col':8,'row':port,'PI':PI,'string':formatted_text}) #self.signals.DataUpdateEvent.emit({'col':8,'row':port,'PI':PI,'string':formatted_text})
elif(not tag1_type=="ITEM.ARTIST" and not tag1_type=="DUMMY_CLASS"): elif(not tag1_type=="ITEM.ARTIST" and not tag1_type=="DUMMY_CLASS"):
print("%s:RT+: tag1_type:%s, tag2_type:%s"%(PI,tag1_type,tag2_type)) print("%s:RT+: tag1_type:%s, tag2_type:%s"%(PI,tag1_type,tag2_type))
if not self.RDS_data[PI]["last_item_toggle_bit"] == item_toggle_bit: #new item
self.RDS_data[PI]["last_item_toggle_bit"] = item_toggle_bit
rtcol=self.colorder.index('text')
self.signals.DataUpdateEvent.emit({'col':rtcol,'row':port,'PI':PI,'tooltip':""})
else:#other group else:#other group
printdelay=50 printdelay=50
self.printcounter+=1 self.printcounter+=1
@ -450,7 +456,11 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
layout.addWidget(self.table) layout.addWidget(self.table)
self.table.setHorizontalHeaderLabels(horHeaders) self.table.setHorizontalHeaderLabels(horHeaders)
self.table.setMaximumHeight(250)#TODO use dynamic value
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 ?
self.location_filter=QtGui.QLineEdit() self.location_filter=QtGui.QLineEdit()
@ -465,11 +475,20 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
layout.addLayout(filter_layout) layout.addLayout(filter_layout)
layout.addWidget(self.tmc_message_label) layout.addWidget(self.tmc_message_label)
self.logOutput = Qt.QTextEdit()
self.logOutput.setReadOnly(True)
self.logOutput.setLineWrapMode(Qt.QTextEdit.NoWrap)
#self.logOutput.setMaximumHeight(100)
font = self.logOutput.font()
font.setFamily("Courier")
font.setPointSize(10)
layout.addWidget(self.logOutput)
def display_data(self, event): def display_data(self, event):
#pp.pprint(event) #pp.pprint(event)
if type(event)==dict and event.has_key('TMC_log'):
self.logOutput.append(Qt.QString.fromUtf8(event['TMC_log']))
if type(event)==dict and event.has_key('row'): if type(event)==dict and event.has_key('row'):
if event.has_key('wrong_blocks'): if event.has_key('wrong_blocks'):
item=self.table.cellWidget(event['row'],self.colorder.index('quality')) item=self.table.cellWidget(event['row'],self.colorder.index('quality'))
@ -508,6 +527,7 @@ class rds_parser_table_qt_Widget(QtGui.QWidget):
self.table.resizeColumnsToContents() self.table.resizeColumnsToContents()
def onCLick(self): def onCLick(self):
print("button clicked") print("button clicked")
code.interact(local=locals())
#self.reset_color() #self.reset_color()
#pp.pprint(event) #pp.pprint(event)
if __name__ == "__main__": if __name__ == "__main__":

Loading…
Cancel
Save