Added option for pulse matched filtering

Pulse matched filtering places a boxcar filter upstream of the
averager and preamble detector.  The filter length is equivalent
to the number of samples in one Mode S chip (0.5us).  This
technique enhances operation when using sample rates > 4Msps.

* rx_path.py now takes 'use_pmf', defaults to False

* modes_rx has new CLI option '-p' or '--pmf' to turn on PMF

* modes_gui has new checkbox on Setup tab
This commit is contained in:
Johnathan Corgan 2012-10-27 11:28:06 -07:00
parent 1adbf81950
commit 686078bf72
4 changed files with 34 additions and 12 deletions

View File

@ -239,6 +239,7 @@ class mainwindow(QtGui.QMainWindow):
options["gain"] = float(self.ui.line_gain.text()) options["gain"] = float(self.ui.line_gain.text())
options["threshold"] = float(self.ui.line_threshold.text()) options["threshold"] = float(self.ui.line_threshold.text())
options["filename"] = str(self.ui.line_inputfile.text()) options["filename"] = str(self.ui.line_inputfile.text())
options["pmf"] = self.ui.check_pmf.checkState()
self.fg = adsb_rx_block(options, self.queue) #create top RX block self.fg = adsb_rx_block(options, self.queue) #create top RX block
self.runner = top_block_runner(self.fg) #spawn new thread to do RX self.runner = top_block_runner(self.fg) #spawn new thread to do RX
@ -409,7 +410,7 @@ class adsb_rx_block (gr.top_block):
else: else:
raise NotImplementedError raise NotImplementedError
self.rx_path = air_modes.rx_path(rate, options["threshold"], queue) self.rx_path = air_modes.rx_path(rate, options["threshold"], queue, options["pmf"])
if use_resampler: if use_resampler:
self.lpfiltcoeffs = gr.firdes.low_pass(1, 5*3.2e6, 1.6e6, 300e3) self.lpfiltcoeffs = gr.firdes.low_pass(1, 5*3.2e6, 1.6e6, 300e3)

View File

@ -110,7 +110,7 @@ class adsb_rx_block (gr.top_block):
if options.output_all : if options.output_all :
pass_all = 1 pass_all = 1
self.rx_path = air_modes.rx_path(rate, options.threshold, queue) self.rx_path = air_modes.rx_path(rate, options.threshold, queue, options.pmf)
if use_resampler: if use_resampler:
self.lpfiltcoeffs = gr.firdes.low_pass(1, 5*3.2e6, 1.6e6, 300e3) self.lpfiltcoeffs = gr.firdes.low_pass(1, 5*3.2e6, 1.6e6, 300e3)
@ -163,6 +163,8 @@ if __name__ == '__main__':
help="FlightGear server to send aircraft data, in format host:port") help="FlightGear server to send aircraft data, in format host:port")
parser.add_option("-d","--rtlsdr", action="store_true", default=False, parser.add_option("-d","--rtlsdr", action="store_true", default=False,
help="Use RTLSDR dongle instead of UHD source") help="Use RTLSDR dongle instead of UHD source")
parser.add_option("-p","--pmf", action="store_true", default=False,
help="Use pulse matched filtering")
(options, args) = parser.parse_args() (options, args) = parser.parse_args()

View File

@ -24,7 +24,7 @@ import air_modes_swig
class rx_path(gr.hier_block2): class rx_path(gr.hier_block2):
def __init__(self, rate, threshold, queue): def __init__(self, rate, threshold, queue, use_pmf=False):
gr.hier_block2.__init__(self, "modes_rx_path", gr.hier_block2.__init__(self, "modes_rx_path",
gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_gr_complex),
gr.io_signature(0,0,0)) gr.io_signature(0,0,0))
@ -32,12 +32,20 @@ class rx_path(gr.hier_block2):
self._rate = int(rate) self._rate = int(rate)
self._threshold = threshold self._threshold = threshold
self._queue = queue self._queue = queue
self._spc = int(rate/2e6)
# Convert incoming I/Q baseband to amplitude # Convert incoming I/Q baseband to amplitude
self._demod = gr.complex_to_mag() self._demod = gr.complex_to_mag()
self._bb = self._demod
# Pulse matched filter for 0.5us pulses
if use_pmf:
self._pmf = gr.moving_average_ff(self._spc, 1.0/self._spc, self._rate)
self.connect(self._demod, self._pmf)
self._bb = self._pmf
# Establish baseline amplitude (noise, interference) # Establish baseline amplitude (noise, interference)
self._avg = gr.moving_average_ff(100, 1.0/100, 400) # FIXME self._avg = gr.moving_average_ff(48*self._spc, 1.0/(48*self._spc), self._rate) # 3 preambles
# Synchronize to Mode-S preamble # Synchronize to Mode-S preamble
self._sync = air_modes_swig.modes_preamble(self._rate, self._threshold) self._sync = air_modes_swig.modes_preamble(self._rate, self._threshold)
@ -45,6 +53,8 @@ class rx_path(gr.hier_block2):
# Slice Mode-S bits and send to message queue # Slice Mode-S bits and send to message queue
self._slicer = air_modes_swig.modes_slicer(self._rate, self._queue) self._slicer = air_modes_swig.modes_slicer(self._rate, self._queue)
self.connect(self, self._demod, (self._sync, 0)) # Wire up the flowgraph
self.connect(self._demod, self._avg, (self._sync, 1)) self.connect(self, self._demod)
self.connect(self._bb, (self._sync, 0))
self.connect(self._bb, self._avg, (self._sync, 1))
self.connect(self._sync, self._slicer) self.connect(self._sync, self._slicer)

View File

@ -24,7 +24,7 @@
</rect> </rect>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>1</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="tab"> <widget class="QWidget" name="tab">
<attribute name="title"> <attribute name="title">
@ -147,7 +147,7 @@
</rect> </rect>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>1</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="page_rf"> <widget class="QWidget" name="page_rf">
<widget class="QComboBox" name="combo_ant"> <widget class="QComboBox" name="combo_ant">
@ -234,10 +234,6 @@
<string>Filename</string> <string>Filename</string>
</property> </property>
</widget> </widget>
<zorder>line_inputfile</zorder>
<zorder>label_13</zorder>
<zorder>combo_rate</zorder>
<zorder>label_27</zorder>
</widget> </widget>
</widget> </widget>
</widget> </widget>
@ -460,6 +456,19 @@
</property> </property>
</widget> </widget>
</widget> </widget>
<widget class="QCheckBox" name="check_pmf">
<property name="geometry">
<rect>
<x>20</x>
<y>210</y>
<width>221</width>
<height>22</height>
</rect>
</property>
<property name="text">
<string>Use Pulse Matched Filtering</string>
</property>
</widget>
</widget> </widget>
<widget class="QWidget" name="dashboard"> <widget class="QWidget" name="dashboard">
<attribute name="title"> <attribute name="title">