From 9d6ed6dc64c125c103cf9219883e26902d491a02 Mon Sep 17 00:00:00 2001 From: yakup Date: Tue, 21 Jan 2020 09:23:13 -0300 Subject: [PATCH 01/41] Small changes to adapt to Python 3 on GNURadio 3.8 --- apps/cursesgui.py | 12 ++++++------ apps/estimate.py | 26 +++++++++++++------------- apps/ham2mon.py | 8 ++++---- apps/parser.py | 36 ++++++++++++++++++------------------ apps/receiver.py | 18 +++++++++--------- apps/scanner.py | 16 ++++++++-------- 6 files changed, 58 insertions(+), 58 deletions(-) diff --git a/apps/cursesgui.py b/apps/cursesgui.py index 2896f70..77c2b4f 100755 --- a/apps/cursesgui.py +++ b/apps/cursesgui.py @@ -89,7 +89,7 @@ def draw_spectrum(self, data): # Clear previous contents, draw border, and title self.win.clear() self.win.border(0) - self.win.addnstr(0, self.dims[1]/2-4, "SPECTRUM", 8, + self.win.addnstr(0, int(self.dims[1]/2-4), "SPECTRUM", 8, curses.color_pair(4)) # Draw the bars @@ -191,7 +191,7 @@ def draw_channels(self, gui_tuned_channels): # Clear previous contents, draw border, and title self.win.clear() self.win.border(0) - self.win.addnstr(0, self.dims[1]/2-4, "CHANNELS", 8, + self.win.addnstr(0, int(self.dims[1]/2-4), "CHANNELS", 8, curses.color_pair(4)) # Limit the displayed channels to no more than two rows @@ -247,7 +247,7 @@ def draw_channels(self, gui_lockout_channels): # Clear previous contents, draw border, and title self.win.clear() self.win.border(0) - self.win.addnstr(0, self.dims[1]/2-3, "LOCKOUT", 7, + self.win.addnstr(0, int(self.dims[1]/2-3), "LOCKOUT", 7, curses.color_pair(4)) # Draw the lockout channels @@ -354,7 +354,7 @@ def draw_rx(self): # Clear previous contents, draw border, and title self.win.clear() self.win.border(0) - self.win.addnstr(0, self.dims[1]/2-4, "RECEIVER", 8, + self.win.addnstr(0, int(self.dims[1]/2-4), "RECEIVER", 8, curses.color_pair(4)) # Draw the receiver info prefix fields @@ -380,7 +380,7 @@ def draw_rx(self): self.win.addnstr(10, 1, text, 15) # Draw the receiver info suffix fields - if self.freq_entry <> 'None': + if self.freq_entry != 'None': text = self.freq_entry else: text = '{:.3f}'.format((self.center_freq)/1E6) @@ -471,7 +471,7 @@ def proc_keyb_hard(self, keyb): pass self.freq_entry = 'None' return True - elif self.freq_entry <> 'None' and (keyb - 48 in range (10) or keyb == ord('.')): + elif self.freq_entry != 'None' and (keyb - 48 in range (10) or keyb == ord('.')): # build up frequency from 1-9 and '.' self.freq_entry = self.freq_entry + chr(keyb) return False diff --git a/apps/estimate.py b/apps/estimate.py index 1e597df..f61e96e 100755 --- a/apps/estimate.py +++ b/apps/estimate.py @@ -68,30 +68,30 @@ def main(): """ Tests the functions in this module""" # Test avg_freq() - print "Testing avg_freq()" + print("Testing avg_freq()") data = np.array([0, 1, 1, 0]) - print "Input spectrum data is " + str(data) + print("Input spectrum data is " + str(data)) result = avg_freq(data) - print "Average frequency is " + str(result) + print("Average frequency is " + str(result)) if result == 1.5: - print "Test Pass" + print("Test Pass") else: - print "Test Fail" - print "" + print("Test Fail") + print("") # Test channel_estimate() - print "Testing channel_estimate()" + print("Testing channel_estimate()") data = np.array([0, 1, 1, 0, 0, 1, 1, 1]) threshold = 0.5 - print "Input spectrum data is " + str(data) - print "Threshold is " + str(threshold) + print("Input spectrum data is " + str(data)) + print("Threshold is " + str(threshold)) result = channel_estimate(data, threshold) - print "Channels at " + str(result) + print("Channels at " + str(result)) if result == [1.5, 6.0]: - print "Test Pass" + print("Test Pass") else: - print "Test Fail" - print "" + print("Test Fail") + print("") if __name__ == '__main__': diff --git a/apps/ham2mon.py b/apps/ham2mon.py index 3e2d810..8d89276 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -142,13 +142,13 @@ def main(screen): PARSER = parser.CLParser() if len(PARSER.parser_args) != 0: PARSER.print_help() #pylint: disable=maybe-no-member - raise SystemExit, 1 + raise(SystemExit, 1) else: curses.wrapper(main) except KeyboardInterrupt: pass except RuntimeError: - print "" - print "RuntimeError: SDR hardware not detected or insufficient USB permissions. Try running as root." - print "" + print("") + print("RuntimeError: SDR hardware not detected or insufficient USB permissions. Try running as root.") + print("") diff --git a/apps/parser.py b/apps/parser.py index 43830cf..7f1b4a1 100755 --- a/apps/parser.py +++ b/apps/parser.py @@ -132,24 +132,24 @@ def main(): if len(parser.parser_args) != 0: parser.print_help() #pylint: disable=maybe-no-member - raise SystemExit, 1 - - print "hw_args: " + parser.hw_args - print "num_demod: " + str(parser.num_demod) - print "type_demod: " + str(parser.type_demod) - print "center_freq: " + str(parser.center_freq) - print "ask_samp_rate: " + str(parser.ask_samp_rate) - print "gain_db: " + str(parser.gain_db) - print "if_gain_db: " + str(parser.if_gain_db) - print "bb_gain_db: " + str(parser.bb_gain_db) - print "squelch_db: " + str(parser.squelch_db) - print "volume_db: " + str(parser.volume_db) - print "threshold_db: " + str(parser.threshold_db) - print "record: " + str(parser.record) - print "lockout_file_name: " + str(parser.lockout_file_name) - print "priority_file_name: " + str(parser.priority_file_name) - print "freq_correction: " + str(parser.freq_correction) - print "audio_bps: " + str(parser.audio_bps) + raise(SystemExit, 1) + + print("hw_args: " + parser.hw_args) + print("num_demod: " + str(parser.num_demod)) + print("type_demod: " + str(parser.type_demod)) + print("center_freq: " + str(parser.center_freq)) + print("ask_samp_rate: " + str(parser.ask_samp_rate)) + print("gain_db: " + str(parser.gain_db)) + print("if_gain_db: " + str(parser.if_gain_db)) + print("bb_gain_db: " + str(parser.bb_gain_db)) + print("squelch_db: " + str(parser.squelch_db)) + print("volume_db: " + str(parser.volume_db)) + print("threshold_db: " + str(parser.threshold_db)) + print("record: " + str(parser.record)) + print("lockout_file_name: " + str(parser.lockout_file_name)) + print("priority_file_name: " + str(parser.priority_file_name)) + print("freq_correction: " + str(parser.freq_correction)) + print("audio_bps: " + str(parser.audio_bps)) if __name__ == '__main__': diff --git a/apps/receiver.py b/apps/receiver.py index be6ba2c..83f9fdd 100755 --- a/apps/receiver.py +++ b/apps/receiver.py @@ -601,14 +601,14 @@ def main(): center_freq = 144.5E6 receiver.set_center_freq(center_freq) receiver.set_gain(10) - print "\n" - print "Started %s at %.3f Msps" % (hw_args, receiver.samp_rate/1E6) - print "RX at %.3f MHz with %d dB gain" % (receiver.center_freq/1E6, - receiver.gain_db) + print("\n") + print("Started %s at %.3f Msps" % (hw_args, receiver.samp_rate/1E6)) + print("RX at %.3f MHz with %d dB gain" % (receiver.center_freq/1E6, + receiver.gain_db)) receiver.set_squelch(-60) receiver.set_volume(0) - print "%d demods of type %d at %d dB squelch and %d dB volume" % \ - (num_demod, type_demod, receiver.squelch_db, receiver.volume_db) + print("%d demods of type %d at %d dB squelch and %d dB volume" % \ + (num_demod, type_demod, receiver.squelch_db, receiver.volume_db)) # Create some baseband channels to tune based on 144 MHz center channels = np.zeros(num_demod) @@ -622,9 +622,9 @@ def main(): # Print demodulator info for idx, channel in enumerate(channels): - print "Tuned demod %d to %.3f MHz" % (idx, + print("Tuned demod %d to %.3f MHz" % (idx, (channel+receiver.center_freq) - /1E6) + /1E6)) while 1: # No need to go faster than 10 Hz rate of GNU Radio probe @@ -633,7 +633,7 @@ def main(): # Grab the FFT data and print max value spectrum = receiver.probe_signal_vf.level() - print "Max spectrum of %.3f" % (np.max(spectrum)) + print("Max spectrum of %.3f" % (np.max(spectrum))) # Stop the receiver receiver.stop() diff --git a/apps/scanner.py b/apps/scanner.py index 619f192..fbacdad 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -5,7 +5,7 @@ @author: madengr """ -import __builtin__ +import builtins import receiver as recvr import estimate import parser as prsr @@ -348,7 +348,7 @@ def main(): if len(parser.parser_args) != 0: parser.print_help() #pylint: disable=maybe-no-member - raise SystemExit, 1 + raise(SystemExit, 1) # Create scanner object ask_samp_rate = parser.ask_samp_rate @@ -369,14 +369,14 @@ def main(): scanner.set_gain(parser.gain_db) scanner.set_if_gain(parser.if_gain_db) scanner.set_bb_gain(parser.bb_gain_db) - print "\n" - print "Started %s at %.3f Msps" % (hw_args, scanner.samp_rate/1E6) - print "RX at %.3f MHz with %d dB gain" % (scanner.center_freq/1E6, - scanner.gain_db) + print("\n") + print("Started %s at %.3f Msps" % (hw_args, scanner.samp_rate/1E6)) + print("RX at %.3f MHz with %d dB gain" % (scanner.center_freq/1E6, + scanner.gain_db)) scanner.set_squelch(parser.squelch_db) scanner.set_volume(parser.volume_db) - print "%d demods of type %d at %d dB squelch and %d dB volume" % \ - (num_demod, type_demod, scanner.squelch_db, scanner.volume_db) + print("%d demods of type %d at %d dB squelch and %d dB volume" % \ + (num_demod, type_demod, scanner.squelch_db, scanner.volume_db)) # Create this epmty list to allow printing to screen old_gui_tuned_channels = [] From a8eabf4589738b330c0abf3da4c67132b92be141 Mon Sep 17 00:00:00 2001 From: yakup Date: Tue, 21 Jan 2020 11:51:07 -0300 Subject: [PATCH 02/41] Fixing import command and GRC examples --- apps/am_flow_example.py | 2 +- apps/nbfm_flow_example.py | 2 +- apps/scanner.py | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/am_flow_example.py b/apps/am_flow_example.py index 0517730..d49876e 100755 --- a/apps/am_flow_example.py +++ b/apps/am_flow_example.py @@ -14,7 +14,7 @@ x11 = ctypes.cdll.LoadLibrary('libX11.so') x11.XInitThreads() except: - print "Warning: failed to XInitThreads()" + print("Warning: failed to XInitThreads()") from PyQt4 import Qt from gnuradio import analog diff --git a/apps/nbfm_flow_example.py b/apps/nbfm_flow_example.py index 085c36e..08b4504 100755 --- a/apps/nbfm_flow_example.py +++ b/apps/nbfm_flow_example.py @@ -14,7 +14,7 @@ x11 = ctypes.cdll.LoadLibrary('libX11.so') x11.XInitThreads() except: - print "Warning: failed to XInitThreads()" + print("Warning: failed to XInitThreads()") from PyQt4 import Qt from gnuradio import analog diff --git a/apps/scanner.py b/apps/scanner.py index fbacdad..000d1da 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -5,7 +5,10 @@ @author: madengr """ -import builtins +try: + import builtins +except: + import __builtin__ import receiver as recvr import estimate import parser as prsr From 29660e68cf8b73c1fbe071da3ca34d578f77a05f Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sun, 6 Dec 2020 00:24:25 -0800 Subject: [PATCH 03/41] Committer: Andrew Farris On branch py3-updates Changes to be committed: modified: apps/cursesgui.py modified: apps/ham2mon.py new file: apps/lockout-example.txt modified: apps/parser.py new file: apps/priority-example.txt modified: apps/scanner.py Modified detection of builtins functions for python2 and python3 (only tested on 3 so far). Modified priority and lockout file list parsing for python2 and python3 builtin filter function call. Added params for min_db and max_db as -N and -M respectively set from command line. Revised step size on spectrum min/max to 5, preference take it or leave it, may revise to a command line flag. Created example format file with simple entry set for priority and lockout files. --- apps/cursesgui.py | 8 ++++---- apps/ham2mon.py | 2 ++ apps/lockout-example.txt | 6 ++++++ apps/parser.py | 15 ++++++++++++++ apps/priority-example.txt | 1 + apps/scanner.py | 42 +++++++++++++++++++++++++++++++++------ 6 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 apps/lockout-example.txt create mode 100644 apps/priority-example.txt diff --git a/apps/cursesgui.py b/apps/cursesgui.py index 77c2b4f..f3547d4 100755 --- a/apps/cursesgui.py +++ b/apps/cursesgui.py @@ -149,13 +149,13 @@ def proc_keyb(self, keyb): self.threshold_db -= 1 return True elif keyb == ord('p'): - self.max_db += 10 + self.max_db += 5 elif keyb == ord('o'): - self.max_db -= 10 + self.max_db -= 5 elif keyb == ord('w'): - self.min_db += 10 + self.min_db += 5 elif keyb == ord('q'): - self.min_db -= 10 + self.min_db -= 5 else: pass return False diff --git a/apps/ham2mon.py b/apps/ham2mon.py index 8d89276..38a9b04 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -80,6 +80,8 @@ def main(screen): rxwin.lockout_file_name = scanner.lockout_file_name rxwin.priority_file_name = scanner.priority_file_name + specwin.max_db = PARSER.max_db + specwin.min_db = PARSER.min_db specwin.threshold_db = scanner.threshold_db while 1: diff --git a/apps/lockout-example.txt b/apps/lockout-example.txt new file mode 100644 index 0000000..d4ce1cb --- /dev/null +++ b/apps/lockout-example.txt @@ -0,0 +1,6 @@ +144275000 +144280000 +144285000 +144290000 +144295000 +144300000 diff --git a/apps/parser.py b/apps/parser.py index 7f1b4a1..6c547ee 100755 --- a/apps/parser.py +++ b/apps/parser.py @@ -27,6 +27,8 @@ class CLParser(object): priority_file_name (string): Name of file with channels to for priority freq_correction (int): Frequency correction in ppm audio_bps (int): Audio bit depth in bps + max_db (float): Spectrum max dB for display + min_db (float): Spectrum min dB for display """ # pylint: disable=too-few-public-methods # pylint: disable=too-many-instance-attributes @@ -102,6 +104,15 @@ def __init__(self): parser.add_option("-b", "--bps", type="int", dest="audio_bps", default=8, help="Audio bit depth (bps)") + + parser.add_option("-M", "--max_db", type="float", dest="max_db", + default=50, + help="Spectrum window max dB for display") + + parser.add_option("-N", "--min_db", type="float", dest="min_db", + default=-10, + help="Spectrum window min dB for display (no greater than -10dB from max") + options = parser.parse_args()[0] self.parser_args = parser.parse_args()[1] @@ -123,6 +134,8 @@ def __init__(self): self.priority_file_name = str(options.priority_file_name) self.freq_correction = int(options.freq_correction) self.audio_bps = int(options.audio_bps) + self.max_db = float(options.max_db) + self.min_db = float(options.min_db) def main(): @@ -150,6 +163,8 @@ def main(): print("priority_file_name: " + str(parser.priority_file_name)) print("freq_correction: " + str(parser.freq_correction)) print("audio_bps: " + str(parser.audio_bps)) + print("max_db: " + str(parser.max_db)) + print("min_db: " + str(parser.min_db)) if __name__ == '__main__': diff --git a/apps/priority-example.txt b/apps/priority-example.txt new file mode 100644 index 0000000..f8d1b25 --- /dev/null +++ b/apps/priority-example.txt @@ -0,0 +1 @@ +146520000 diff --git a/apps/scanner.py b/apps/scanner.py index 000d1da..38359b7 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -5,16 +5,40 @@ @author: madengr """ -try: - import builtins -except: - import __builtin__ + import receiver as recvr import estimate import parser as prsr import time import numpy as np import sys +import types + +PY3 = sys.version_info[0] == 3 +PY2 = sys.version_info[0] == 2 + +if PY3: + import builtins + # list-producing versions of the major Python iterating functions + def lrange(*args, **kwargs): + return list(range(*args, **kwargs)) + + def lzip(*args, **kwargs): + return list(zip(*args, **kwargs)) + + def lmap(*args, **kwargs): + return list(map(*args, **kwargs)) + + def lfilter(*args, **kwargs): + return list(filter(*args, **kwargs)) +else: + import __builtin__ + # Python 2-builtin ranges produce lists + lrange = __builtin__.range + lzip = __builtin__.zip + lmap = __builtin__.map + lfilter = __builtin__.filter + class Scanner(object): """Scanner that controls receiver @@ -217,7 +241,10 @@ def clear_lockout(self): with open(self.lockout_file_name) as lockout_file: lines = lockout_file.read().splitlines() lockout_file.close() - lines = __builtin__.filter(None, lines) + if PY3: + lines = builtins.filter(None, lines) + else: + lines = __builtin__.filter(None, lines) # Convert to baseband frequencies, round, and append for freq in lines: bb_freq = float(freq) - self.center_freq @@ -247,7 +274,10 @@ def update_priority(self): with open(self.priority_file_name) as priority_file: lines = priority_file.read().splitlines() priority_file.close() - lines = __builtin__.filter(None, lines) + if PY3: + lines = builtins.filter(None, lines) + else: + lines = __builtin__.filter(None, lines) # Convert to baseband frequencies, round, and append if within BW for freq in lines: bb_freq = float(freq) - self.center_freq From 5b740526617bef5e3bd5e451782587ffb151e05e Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sun, 6 Dec 2020 00:47:49 -0800 Subject: [PATCH 04/41] Committer: Andrew Farris On branch py3-updates Changes to be committed: modified: README.md Revised description to include new min/max spectrum level switches and contributors. --- README.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7480bcd..8f740d5 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,11 @@ madengr: - AM demodulation - Priority channels +lordmorgul: +- min and max spectrum switches +- python3 builtin functions correction for priority and lockout parsing +- example priority and lockout files + ## Console Operation: The following is an example of the option switches for UHD with NBFM demodulation, although omission of any will use default values (shown below) that are optimal for the B200: @@ -62,9 +67,9 @@ Example of reading from an IQ file: `t/r = Detection threshold +/- 5 dB. (T/R for +/- 1dB)` -`p/o = Spectrum upper scale +/- 10 dB` +`p/o = Spectrum upper scale +/- 5 dB` -`w/q = Spectrum lower scale +/- 10 dB` +`w/q = Spectrum lower scale +/- 5 dB` `g/f = RF gain +/- 10 dB (G/F for +/- 1dB)` @@ -149,6 +154,12 @@ Example of reading from an IQ file: ` -b AUDIO_BPS, --bps=AUDIO_BPS` ` Audio bit depth (bps)` +` -M MAX_DB, --max_db=MAX_DB` +` Spectrum window maximum in dB` + +` -N MIN_DB, --min_db=MIN_DB` +` Spectrum window minimum in dB` + ## Description: The high speed signal processing is done in GR and the logic & control in Python. There are no custom GR blocks. The GUI is written in Curses and is meant to be lightweight. See the video for a basic overview. I attempted to make the program very object oriented and “Pythonic”. Each module runs on it's own for testing purposes. From 18b64ac6ab5b29fcc9325f46e09fcd2b6299dade Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sun, 6 Dec 2020 00:54:01 -0800 Subject: [PATCH 05/41] Committer: Andrew Farris Changes to be committed: modified: README.md Attribution for ta6o python3 fixes adopted in pull request --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 8f740d5..839934c 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,9 @@ madengr: - AM demodulation - Priority channels +ta6o: +- initial python3 fixes for syntax + lordmorgul: - min and max spectrum switches - python3 builtin functions correction for priority and lockout parsing From 9aa26c624bbb675a7a8e7fdadff1efaa2319fb4a Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Mon, 21 Dec 2020 02:10:47 -0800 Subject: [PATCH 06/41] Modified gui to track active channels coming out of scanner and highlight in color (green if tuned, yellow if lockout). modified spectrum display characters used to visually separate under threshold (-), above threshold (*) and above maximum (+) as well as use colors blue, green, and red respectively. Committer: Andrew Farris On branch gui-devel Changes to be committed: modified: cursesgui.py modified: ham2mon.py modified: receiver.py modified: scanner.py --- apps/cursesgui.py | 53 ++++++++++++++++++++++++++++++++++++----------- apps/ham2mon.py | 4 ++-- apps/receiver.py | 2 +- apps/scanner.py | 18 ++++++++++++++++ 4 files changed, 62 insertions(+), 15 deletions(-) diff --git a/apps/cursesgui.py b/apps/cursesgui.py index f3547d4..2226a39 100755 --- a/apps/cursesgui.py +++ b/apps/cursesgui.py @@ -54,6 +54,7 @@ def draw_spectrum(self, data): 1.0E+00 draws 10 rows 1.0E+01 draws 10 rows """ + # Keep min_db to 10 dB below max_db if self.min_db > (self.max_db - 10): self.min_db = self.max_db - 10 @@ -92,11 +93,25 @@ def draw_spectrum(self, data): self.win.addnstr(0, int(self.dims[1]/2-4), "SPECTRUM", 8, curses.color_pair(4)) + # Generate threshold line, clip to window, and convert to int + pos_yt = (self.threshold_db - self.max_db) * scale + pos_yt = np.clip(pos_yt, min_y, max_y-1) + pos_yt = pos_yt.astype(int) + # Draw the bars for pos_x in range(len(pos_y)): # Invert the y fill since we want bars # Offset x (column) by 1 so it does not start on the border - self.win.vline(pos_y[pos_x], pos_x+1, "*", max_y-pos_y[pos_x]) + if pos_y[pos_x] > pos_yt: + # bar is below threshold, use low value color + self.win.vline(pos_y[pos_x], pos_x+1, "-", max_y-pos_y[pos_x],curses.color_pair(3)) + elif pos_y[pos_x] <= min_y: + # bar is above max (clipped to min y), use max value color + self.win.vline(pos_y[pos_x], pos_x+1, "+", max_y-pos_y[pos_x],curses.color_pair(1)) + else: + # bar is between max value and threshold, use threshold color + self.win.vline(pos_y[pos_x], pos_x+1, "*", max_y-pos_y[pos_x],curses.color_pair(2)) + # Draw the max_db and min_db strings string = ">" + "%+03d" % self.max_db @@ -106,11 +121,6 @@ def draw_spectrum(self, data): self.win.addnstr(max_y, 1 + self.dims[1] - self.chars, string, self.chars, curses.color_pair(3)) - # Generate threshold line, clip to window, and convert to int - pos_yt = (self.threshold_db - self.max_db) * scale - pos_yt = np.clip(pos_yt, min_y, max_y-1) - pos_yt = pos_yt.astype(int) - # Draw the theshold line # x=1 start to account for left border self.win.hline(pos_yt, 1, "-", len(pos_y)) @@ -120,12 +130,13 @@ def draw_spectrum(self, data): self.win.addnstr(pos_yt, (1 + self.dims[1] - self.chars), string, self.chars, curses.color_pair(2)) - # Hide cursor + # Hide cursor self.win.leaveok(1) # Update virtual window self.win.noutrefresh() + def proc_keyb(self, keyb): """Process keystrokes @@ -181,7 +192,7 @@ def __init__(self, screen): self.win = curses.newwin(height, width, height + 3, 1) self.dims = self.win.getmaxyx() - def draw_channels(self, gui_tuned_channels): + def draw_channels(self, gui_tuned_channels, gui_active_channels): """Draws tuned channels list Args: @@ -201,15 +212,27 @@ def draw_channels(self, gui_tuned_channels): else: pass + active_channels = set(gui_active_channels) + # Draw the tuned channels prefixed by index in list (demodulator index) + # Use color if tuned channel is in active channel list during this scan_cycle for idx, gui_tuned_channel in enumerate(gui_tuned_channels): text = str(idx) + ": " + gui_tuned_channel if idx < self.dims[0]-2: # Display in first column - self.win.addnstr(idx+1, 1, text, 11) + # text color based on activity + # curses.color_pair(5) + if gui_tuned_channel in active_channels: + self.win.addnstr(idx+1, 1, text, 11, curses.color_pair(2)) + else: + self.win.addnstr(idx+1, 1, text, 11) else: # Display in second column self.win.addnstr(idx-self.dims[0]+3, 13, text, 11) + if gui_tuned_channel in active_channels: + self.win.addnstr(idx-self.dims[0]+3, 13, text, 11, curses.color_pair(2)) + else: + self.win.addnstr(idx-self.dims[0]+3, 13, text, 11) # Hide cursor self.win.leaveok(1) @@ -238,8 +261,8 @@ def __init__(self, screen): self.win = curses.newwin(height, width, height + 3, 26) self.dims = self.win.getmaxyx() - def draw_channels(self, gui_lockout_channels): - """Draws tuned channels list + def draw_channels(self, gui_lockout_channels, gui_active_channels): + """Draws lockout channels list Args: rf_channels [string]: List of strings in MHz @@ -250,12 +273,18 @@ def draw_channels(self, gui_lockout_channels): self.win.addnstr(0, int(self.dims[1]/2-3), "LOCKOUT", 7, curses.color_pair(4)) + active_channels = set(gui_active_channels) + # Draw the lockout channels + # Use color if lockout channel is in active channel list during this scan_cycle for idx, gui_lockout_channel in enumerate(gui_lockout_channels): # Don't draw past height of window if idx <= self.dims[0]-3: text = " " + gui_lockout_channel - self.win.addnstr(idx+1, 1, text, 11) + if gui_lockout_channel in active_channels: + self.win.addnstr(idx+1, 1, text, 11, curses.color_pair(5)) + else: + self.win.addnstr(idx+1, 1, text, 11) else: pass diff --git a/apps/ham2mon.py b/apps/ham2mon.py index 38a9b04..1a4966c 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -93,8 +93,8 @@ def main(screen): # Update the spectrum, channel, and rx displays specwin.draw_spectrum(scanner.spectrum) - chanwin.draw_channels(scanner.gui_tuned_channels) - lockoutwin.draw_channels(scanner.gui_lockout_channels) + chanwin.draw_channels(scanner.gui_tuned_channels, scanner.gui_active_channels) + lockoutwin.draw_channels(scanner.gui_lockout_channels, scanner.gui_active_channels) rxwin.draw_rx() # Update physical screen diff --git a/apps/receiver.py b/apps/receiver.py index 83f9fdd..01a9227 100755 --- a/apps/receiver.py +++ b/apps/receiver.py @@ -576,7 +576,7 @@ def get_demod_freqs(self): def main(): """Test the receiver - Sets up the hadrware + Sets up the hardware Tunes a couple of demodulators Prints the max power spectrum """ diff --git a/apps/scanner.py b/apps/scanner.py index 38359b7..99a1fa2 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -69,6 +69,7 @@ class Scanner(object): lockout_channels [float]: List of baseband lockout channels in Hz priority_channels [float]: List of baseband priority channels in Hz gui_tuned_channels [str] List of tuned RF channels in MHz for GUI + gui_active_channels [str] List of active RF channels in MHz for GUI (currently above threshold) gui_tuned_lockout_channels [str]: List of lockout channels in MHz GUI channel_spacing (float): Spacing that channels will be rounded lockout_file_name (string): Name of file with channels to lockout @@ -94,7 +95,9 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.spectrum = [] self.lockout_channels = [] self.priority_channels = [] + self.active_channels = [] self.gui_tuned_channels = [] + self.gui_active_channels = [] self.gui_lockout_channels = [] self.channel_spacing = 5000 self.lockout_file_name = lockout_file_name @@ -141,6 +144,7 @@ def scan_cycle(self): channels = np.array(estimate.channel_estimate(self.spectrum, threshold)) + # Convert channels from bin indices to baseband frequency in Hz channels = (channels-len(self.spectrum)/2)*\ self.samp_rate/len(self.spectrum) @@ -150,6 +154,9 @@ def scan_cycle(self): # 5000 Hz is adequate for NBFM channels = np.round(channels / self.channel_spacing) * self.channel_spacing + # set active channels for gui highlight before filtering down lockout or adding priority + active_channels = channels + # Remove channels that are already in the priority list temp = [] for channel in channels: @@ -207,6 +214,17 @@ def scan_cycle(self): text = '{:.3f}'.format(gui_tuned_channel) self.gui_tuned_channels.append(text) + # Create an active channel list of strings for the GUI + # This is any channel above threshold + # do not include priority if not above threshold + # do include lockout if above threshold + self.gui_active_channels = [] + for channel in active_channels: + gui_active_channel = (channel + self.center_freq)/1E6 + text = '{:.3f}'.format(gui_active_channel) + self.gui_active_channels.append(text) + + def add_lockout(self, idx): """Adds baseband frequency to lockout channels and updates GUI list From d5152a28291f1cb9273809525fa6679305de2dcb Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Tue, 22 Dec 2020 23:55:31 -0800 Subject: [PATCH 07/41] Modified cursesgui.py with fixes for stability of screen draw, call erase instead of clear and call cursor set no cursor. Committer: Andrew Farris Changes to be committed: modified: cursesgui.py --- apps/cursesgui.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/apps/cursesgui.py b/apps/cursesgui.py index 2226a39..68def4d 100755 --- a/apps/cursesgui.py +++ b/apps/cursesgui.py @@ -88,7 +88,8 @@ def draw_spectrum(self, data): pos_y = pos_y.astype(int) # Clear previous contents, draw border, and title - self.win.clear() +# self.win.clear() + self.win.erase() self.win.border(0) self.win.addnstr(0, int(self.dims[1]/2-4), "SPECTRUM", 8, curses.color_pair(4)) @@ -200,7 +201,8 @@ def draw_channels(self, gui_tuned_channels, gui_active_channels): """ # Clear previous contents, draw border, and title - self.win.clear() +# self.win.clear() + self.win.erase() self.win.border(0) self.win.addnstr(0, int(self.dims[1]/2-4), "CHANNELS", 8, curses.color_pair(4)) @@ -268,7 +270,8 @@ def draw_channels(self, gui_lockout_channels, gui_active_channels): rf_channels [string]: List of strings in MHz """ # Clear previous contents, draw border, and title - self.win.clear() +# self.win.clear() + self.win.erase() self.win.border(0) self.win.addnstr(0, int(self.dims[1]/2-3), "LOCKOUT", 7, curses.color_pair(4)) @@ -381,7 +384,8 @@ def draw_rx(self): """ # Clear previous contents, draw border, and title - self.win.clear() +# self.win.clear() + self.win.erase() self.win.border(0) self.win.addnstr(0, int(self.dims[1]/2-4), "RECEIVER", 8, curses.color_pair(4)) @@ -597,6 +601,9 @@ def setup_screen(screen): # Set screen to getch() is non-blocking screen.nodelay(1) + # hide cursor + curses.curs_set(0) + # Define some colors curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK) curses.init_pair(2, curses.COLOR_GREEN, curses.COLOR_BLACK) From f6fd245b4ee8a6bb51c41815f157600c4426651e Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Wed, 23 Dec 2020 02:22:51 -0800 Subject: [PATCH 08/41] revised use of color with more options to be easily adjusted by other users, bold and dim white window titles, work to be done enumerating the colors better such as 'border_color' and 'text_color' where the color pairs are define so that would change in one location versus every call. Changes to be committed: modified: cursesgui.py --- apps/cursesgui.py | 112 +++++++++++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 45 deletions(-) diff --git a/apps/cursesgui.py b/apps/cursesgui.py index 68def4d..4fcd7e2 100755 --- a/apps/cursesgui.py +++ b/apps/cursesgui.py @@ -91,8 +91,9 @@ def draw_spectrum(self, data): # self.win.clear() self.win.erase() self.win.border(0) - self.win.addnstr(0, int(self.dims[1]/2-4), "SPECTRUM", 8, - curses.color_pair(4)) + self.win.attron(curses.color_pair(6)) + self.win.addnstr(0, int(self.dims[1]/2-6), "SPECTRUM", 8, + curses.color_pair(6) | curses.A_DIM | curses.A_BOLD) # Generate threshold line, clip to window, and convert to int pos_yt = (self.threshold_db - self.max_db) * scale @@ -105,13 +106,13 @@ def draw_spectrum(self, data): # Offset x (column) by 1 so it does not start on the border if pos_y[pos_x] > pos_yt: # bar is below threshold, use low value color - self.win.vline(pos_y[pos_x], pos_x+1, "-", max_y-pos_y[pos_x],curses.color_pair(3)) + self.win.vline(pos_y[pos_x], pos_x+1, "-", max_y-pos_y[pos_x],curses.color_pair(3) | curses.A_BOLD) elif pos_y[pos_x] <= min_y: # bar is above max (clipped to min y), use max value color - self.win.vline(pos_y[pos_x], pos_x+1, "+", max_y-pos_y[pos_x],curses.color_pair(1)) + self.win.vline(pos_y[pos_x], pos_x+1, "+", max_y-pos_y[pos_x],curses.color_pair(1) | curses.A_BOLD) else: # bar is between max value and threshold, use threshold color - self.win.vline(pos_y[pos_x], pos_x+1, "*", max_y-pos_y[pos_x],curses.color_pair(2)) + self.win.vline(pos_y[pos_x], pos_x+1, "*", max_y-pos_y[pos_x],curses.color_pair(2) | curses.A_BOLD) # Draw the max_db and min_db strings @@ -124,7 +125,7 @@ def draw_spectrum(self, data): # Draw the theshold line # x=1 start to account for left border - self.win.hline(pos_yt, 1, "-", len(pos_y)) + self.win.hline(pos_yt, 1, "-", len(pos_y), curses.color_pair(2)) # Draw the theshold string string = ">" + "%+03d" % self.threshold_db @@ -204,8 +205,9 @@ def draw_channels(self, gui_tuned_channels, gui_active_channels): # self.win.clear() self.win.erase() self.win.border(0) - self.win.addnstr(0, int(self.dims[1]/2-4), "CHANNELS", 8, - curses.color_pair(4)) + self.win.attron(curses.color_pair(6)) + self.win.addnstr(0, int(self.dims[1]/3-3), "CHANNELS", 8, + curses.color_pair(6) | curses.A_DIM | curses.A_BOLD) # Limit the displayed channels to no more than two rows max_length = 2*(self.dims[0]-2) @@ -225,9 +227,9 @@ def draw_channels(self, gui_tuned_channels, gui_active_channels): # text color based on activity # curses.color_pair(5) if gui_tuned_channel in active_channels: - self.win.addnstr(idx+1, 1, text, 11, curses.color_pair(2)) + self.win.addnstr(idx+1, 1, text, 11, curses.color_pair(2) | curses.A_BOLD) else: - self.win.addnstr(idx+1, 1, text, 11) + self.win.addnstr(idx+1, 1, text, 11, curses.color_pair(6)) else: # Display in second column self.win.addnstr(idx-self.dims[0]+3, 13, text, 11) @@ -273,8 +275,9 @@ def draw_channels(self, gui_lockout_channels, gui_active_channels): # self.win.clear() self.win.erase() self.win.border(0) + self.win.attron(curses.color_pair(6)) self.win.addnstr(0, int(self.dims[1]/2-3), "LOCKOUT", 7, - curses.color_pair(4)) + curses.color_pair(6) | curses.A_DIM | curses.A_BOLD) active_channels = set(gui_active_channels) @@ -285,9 +288,9 @@ def draw_channels(self, gui_lockout_channels, gui_active_channels): if idx <= self.dims[0]-3: text = " " + gui_lockout_channel if gui_lockout_channel in active_channels: - self.win.addnstr(idx+1, 1, text, 11, curses.color_pair(5)) + self.win.addnstr(idx+1, 1, text, 11, curses.color_pair(5) | curses.A_BOLD) else: - self.win.addnstr(idx+1, 1, text, 11) + self.win.addnstr(idx+1, 1, text, 11, curses.color_pair(6)) else: pass @@ -357,6 +360,8 @@ def __init__(self, screen): # Set default values self.center_freq = 146E6 + self.min_freq = 144E6 + self.max_freq = 148E6 self.samp_rate = 2E6 self.freq_entry = 'None' self.gain_db = 0 @@ -387,55 +392,64 @@ def draw_rx(self): # self.win.clear() self.win.erase() self.win.border(0) + self.win.attron(curses.color_pair(6)) self.win.addnstr(0, int(self.dims[1]/2-4), "RECEIVER", 8, - curses.color_pair(4)) + curses.color_pair(6) | curses.A_DIM | curses.A_BOLD) # Draw the receiver info prefix fields - text = "RF Freq (MHz) : " - self.win.addnstr(1, 1, text, 15) - text = "RF Gain (dB) : " - self.win.addnstr(2, 1, text, 15) - text = "IF Gain (dB) : " - self.win.addnstr(3, 1, text, 15) - text = "BB Gain (dB) : " - self.win.addnstr(4, 1, text, 15) - text = "BB Rate (Msps): " - self.win.addnstr(5, 1, text, 15) - text = "BB Sql (dB) : " - self.win.addnstr(6, 1, text, 15) - text = "AF Vol (dB) : " - self.win.addnstr(7, 1, text, 15) - text = "Record : " - self.win.addnstr(8, 1, text, 15) - text = "Demod Type : " - self.win.addnstr(9, 1, text, 15) - text = "Files : " - self.win.addnstr(10, 1, text, 15) + text = "RF Freq (MHz) : " + self.win.addnstr(1, 1, text, 16, curses.color_pair(6)) + text = "Min Freq (MHz) : " + self.win.addnstr(2, 1, text, 16, curses.color_pair(6)) + text = "Max Freq (MHz) : " + self.win.addnstr(3, 1, text, 16, curses.color_pair(6)) + text = "RF Gain (dB) : " + self.win.addnstr(4, 1, text, 16, curses.color_pair(6)) + text = "IF Gain (dB) : " + self.win.addnstr(5, 1, text, 16, curses.color_pair(6)) + text = "BB Gain (dB) : " + self.win.addnstr(6, 1, text, 16, curses.color_pair(6)) + text = "BB Rate (Msps) : " + self.win.addnstr(7, 1, text, 16, curses.color_pair(6)) + text = "BB Sql (dB) : " + self.win.addnstr(8, 1, text, 16, curses.color_pair(6)) + text = "AF Vol (dB) : " + self.win.addnstr(9, 1, text, 16, curses.color_pair(6)) + text = "Record : " + self.win.addnstr(10, 1, text, 16, curses.color_pair(6)) + text = "Demod Type : " + self.win.addnstr(11, 1, text, 16, curses.color_pair(6)) + text = "Files : " + self.win.addnstr(12, 1, text, 16, curses.color_pair(6)) # Draw the receiver info suffix fields if self.freq_entry != 'None': text = self.freq_entry else: text = '{:.3f}'.format((self.center_freq)/1E6) - self.win.addnstr(1, 17, text, 8, curses.color_pair(5)) + self.win.addnstr(1, 18, text, 8, curses.color_pair(5)) + text = '{:.3f}'.format((self.min_freq)/1E6) + self.win.addnstr(2, 18, text, 8, curses.color_pair(6)) + text = '{:.3f}'.format((self.max_freq)/1E6) + self.win.addnstr(3, 18, text, 8, curses.color_pair(6)) text = str(self.gain_db) - self.win.addnstr(2, 17, text, 8, curses.color_pair(5)) + self.win.addnstr(4, 18, text, 8, curses.color_pair(5)) text = str(self.if_gain_db) - self.win.addnstr(3, 17, text, 8, curses.color_pair(5)) + self.win.addnstr(5, 18, text, 8, curses.color_pair(5)) text = str(self.bb_gain_db) - self.win.addnstr(4, 17, text, 8, curses.color_pair(5)) + self.win.addnstr(6, 18, text, 8, curses.color_pair(5)) text = str(self.samp_rate/1E6) - self.win.addnstr(5, 17, text, 8) + self.win.addnstr(7, 18, text, 8, curses.color_pair(6)) text = str(self.squelch_db) - self.win.addnstr(6, 17, text, 8, curses.color_pair(5)) + self.win.addnstr(8, 18, text, 8, curses.color_pair(5)) text = str(self.volume_db) - self.win.addnstr(7, 17, text, 8, curses.color_pair(5)) + self.win.addnstr(9, 18, text, 8, curses.color_pair(5)) text = str(self.record) - self.win.addnstr(8, 17, text, 8) + self.win.addnstr(10, 18, text, 8, curses.color_pair(6)) text = str(self.type_demod) - self.win.addnstr(9, 17, text, 8) + self.win.addnstr(11, 18, text, 8, curses.color_pair(6)) text = str(self.lockout_file_name) + " " + str(self.priority_file_name) - self.win.addnstr(10, 17, text, 20) + self.win.addnstr(12, 18, text, 20, curses.color_pair(6)) # Hide cursor self.win.leaveok(1) @@ -604,12 +618,20 @@ def setup_screen(screen): # hide cursor curses.curs_set(0) + # do not echo keystrokes + curses.noecho() + + # break on ctrl-c + curses.cbreak() + # Define some colors curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK) curses.init_pair(2, curses.COLOR_GREEN, curses.COLOR_BLACK) curses.init_pair(3, curses.COLOR_CYAN, curses.COLOR_BLACK) curses.init_pair(4, curses.COLOR_MAGENTA, curses.COLOR_BLACK) curses.init_pair(5, curses.COLOR_YELLOW, curses.COLOR_BLACK) + curses.init_pair(6, curses.COLOR_WHITE, curses.COLOR_BLACK) + curses.init_pair(7, curses.COLOR_BLUE, curses.COLOR_BLACK) # Add border screen.border(0) @@ -634,7 +656,7 @@ def main(): # Setup the screen setup_screen(screen) - # Create windows +# Create windows specwin = SpectrumWindow(screen) chanwin = ChannelWindow(screen) lockoutwin = LockoutWindow(screen) From bb64a61d1b305f94f736b870d52377e1c189e312 Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Wed, 30 Dec 2020 16:11:09 -0800 Subject: [PATCH 09/41] Set channel window channel indexes to zero pad to align them. Added min/max frequency calculation to estimate the bandwidth covered by current sample rate and center frequency. Added display for min/max to receiver window. Adjusted alignment in receiver window. Separated lockout and priority file display to two lines in receiver window. Added framework for log file display but currently commented out. Log framework will initially text file note of channel active at time with a min time interval of logging. BUG remaining on Fedora 32 Python 3.8.6 there are randomly printed zeros showing up around the screen, has not been fixed by attempting to move cursor to fixed location after window draw and cannot isolate source of the zeros printed. Seems to print in spectrum and channel windows most but can appear in border, maybe lockout, not sure ever seen in receiver window. On branch gui-devel Changes to be committed: modified: cursesgui.py modified: ham2mon.py modified: receiver.py modified: scanner.py --- apps/cursesgui.py | 83 +++++++++++++++++++++++++++++++---------------- apps/ham2mon.py | 15 +++++++++ apps/receiver.py | 4 +-- apps/scanner.py | 19 +++++++++-- 4 files changed, 88 insertions(+), 33 deletions(-) diff --git a/apps/cursesgui.py b/apps/cursesgui.py index 4fcd7e2..1e21050 100755 --- a/apps/cursesgui.py +++ b/apps/cursesgui.py @@ -89,6 +89,7 @@ def draw_spectrum(self, data): # Clear previous contents, draw border, and title # self.win.clear() + # using erase prevents jitter in some terminals compared to clear() directly self.win.erase() self.win.border(0) self.win.attron(curses.color_pair(6)) @@ -203,10 +204,11 @@ def draw_channels(self, gui_tuned_channels, gui_active_channels): # Clear previous contents, draw border, and title # self.win.clear() + # using erase prevents jitter in some terminals compared to clear() directly self.win.erase() self.win.border(0) self.win.attron(curses.color_pair(6)) - self.win.addnstr(0, int(self.dims[1]/3-3), "CHANNELS", 8, + self.win.addnstr(0, int(self.dims[1]/4), "CHANNELS", 8, curses.color_pair(6) | curses.A_DIM | curses.A_BOLD) # Limit the displayed channels to no more than two rows @@ -221,7 +223,8 @@ def draw_channels(self, gui_tuned_channels, gui_active_channels): # Draw the tuned channels prefixed by index in list (demodulator index) # Use color if tuned channel is in active channel list during this scan_cycle for idx, gui_tuned_channel in enumerate(gui_tuned_channels): - text = str(idx) + ": " + gui_tuned_channel + text = str(idx) + text = text.zfill(2) + ": " + gui_tuned_channel if idx < self.dims[0]-2: # Display in first column # text color based on activity @@ -273,6 +276,7 @@ def draw_channels(self, gui_lockout_channels, gui_active_channels): """ # Clear previous contents, draw border, and title # self.win.clear() + # using erase prevents jitter in some terminals compared to clear() directly self.win.erase() self.win.border(0) self.win.attron(curses.color_pair(6)) @@ -373,6 +377,7 @@ def __init__(self, screen): self.record = True self.lockout_file_name = "" self.priority_file_name = "" +# self.log_file_name = "" # Create a window object in the bottom half of the screen # Make it about 1/3 the screen width @@ -390,6 +395,7 @@ def draw_rx(self): # Clear previous contents, draw border, and title # self.win.clear() + # using erase prevents jitter in some terminals compared to clear() directly self.win.erase() self.win.border(0) self.win.attron(curses.color_pair(6)) @@ -398,58 +404,74 @@ def draw_rx(self): # Draw the receiver info prefix fields text = "RF Freq (MHz) : " - self.win.addnstr(1, 1, text, 16, curses.color_pair(6)) + self.win.addnstr(1, 1, text, 18, curses.color_pair(6)) text = "Min Freq (MHz) : " - self.win.addnstr(2, 1, text, 16, curses.color_pair(6)) + self.win.addnstr(2, 1, text, 18, curses.color_pair(6)) text = "Max Freq (MHz) : " - self.win.addnstr(3, 1, text, 16, curses.color_pair(6)) + self.win.addnstr(3, 1, text, 18, curses.color_pair(6)) text = "RF Gain (dB) : " - self.win.addnstr(4, 1, text, 16, curses.color_pair(6)) + self.win.addnstr(4, 1, text, 18, curses.color_pair(6)) text = "IF Gain (dB) : " - self.win.addnstr(5, 1, text, 16, curses.color_pair(6)) + self.win.addnstr(5, 1, text, 18, curses.color_pair(6)) text = "BB Gain (dB) : " - self.win.addnstr(6, 1, text, 16, curses.color_pair(6)) + self.win.addnstr(6, 1, text, 18, curses.color_pair(6)) text = "BB Rate (Msps) : " - self.win.addnstr(7, 1, text, 16, curses.color_pair(6)) + self.win.addnstr(7, 1, text, 18, curses.color_pair(6)) text = "BB Sql (dB) : " - self.win.addnstr(8, 1, text, 16, curses.color_pair(6)) + self.win.addnstr(8, 1, text, 18, curses.color_pair(6)) text = "AF Vol (dB) : " - self.win.addnstr(9, 1, text, 16, curses.color_pair(6)) + self.win.addnstr(9, 1, text, 18, curses.color_pair(6)) text = "Record : " - self.win.addnstr(10, 1, text, 16, curses.color_pair(6)) + self.win.addnstr(10, 1, text, 18, curses.color_pair(6)) text = "Demod Type : " - self.win.addnstr(11, 1, text, 16, curses.color_pair(6)) - text = "Files : " - self.win.addnstr(12, 1, text, 16, curses.color_pair(6)) + self.win.addnstr(11, 1, text, 18, curses.color_pair(6)) + text = "Lockout File : " + self.win.addnstr(12, 1, text, 18, curses.color_pair(6)) + text = "Priority File : " + self.win.addnstr(13, 1, text, 18, curses.color_pair(6)) +# text = "Log File : " +# self.win.addnstr(14, 1, text, 18, curses.color_pair(6)) +# text = "Log Mode : " +# self.win.addnstr(15, 1, text, 18, curses.color_pair(6)) +# text = "Log Interval : " +# self.win.addnstr(16, 1, text, 18, curses.color_pair(6)) # Draw the receiver info suffix fields if self.freq_entry != 'None': text = self.freq_entry else: text = '{:.3f}'.format((self.center_freq)/1E6) - self.win.addnstr(1, 18, text, 8, curses.color_pair(5)) + self.win.addnstr(1, 20, text, 8, curses.color_pair(5)) text = '{:.3f}'.format((self.min_freq)/1E6) - self.win.addnstr(2, 18, text, 8, curses.color_pair(6)) + self.win.addnstr(2, 20, text, 8, curses.color_pair(6)) text = '{:.3f}'.format((self.max_freq)/1E6) - self.win.addnstr(3, 18, text, 8, curses.color_pair(6)) + self.win.addnstr(3, 20, text, 8, curses.color_pair(6)) text = str(self.gain_db) - self.win.addnstr(4, 18, text, 8, curses.color_pair(5)) + self.win.addnstr(4, 20, text, 8, curses.color_pair(5)) text = str(self.if_gain_db) - self.win.addnstr(5, 18, text, 8, curses.color_pair(5)) + self.win.addnstr(5, 20, text, 8, curses.color_pair(5)) text = str(self.bb_gain_db) - self.win.addnstr(6, 18, text, 8, curses.color_pair(5)) + self.win.addnstr(6, 20, text, 8, curses.color_pair(5)) text = str(self.samp_rate/1E6) - self.win.addnstr(7, 18, text, 8, curses.color_pair(6)) + self.win.addnstr(7, 20, text, 8, curses.color_pair(6)) text = str(self.squelch_db) - self.win.addnstr(8, 18, text, 8, curses.color_pair(5)) + self.win.addnstr(8, 20, text, 8, curses.color_pair(5)) text = str(self.volume_db) - self.win.addnstr(9, 18, text, 8, curses.color_pair(5)) + self.win.addnstr(9, 20, text, 8, curses.color_pair(5)) text = str(self.record) - self.win.addnstr(10, 18, text, 8, curses.color_pair(6)) + self.win.addnstr(10, 20, text, 8, curses.color_pair(6)) text = str(self.type_demod) - self.win.addnstr(11, 18, text, 8, curses.color_pair(6)) - text = str(self.lockout_file_name) + " " + str(self.priority_file_name) - self.win.addnstr(12, 18, text, 20, curses.color_pair(6)) + self.win.addnstr(11, 20, text, 8, curses.color_pair(6)) + text = str(self.lockout_file_name) + self.win.addnstr(12, 20, text, 20, curses.color_pair(6)) + text = str(self.priority_file_name) + self.win.addnstr(13, 20, text, 20, curses.color_pair(6)) +# text = str(self.log_file_name) +# self.win.addnstr(14, 20, text, 20, curses.color_pair(6)) +# text = str(self.log_mode) +# self.win.addnstr(14, 20, text, 20, curses.color_pair(6)) +# text = str(self.log_interval) +# self.win.addnstr(15, 20, text, 20, curses.color_pair(6)) # Hide cursor self.win.leaveok(1) @@ -636,6 +658,7 @@ def setup_screen(screen): # Add border screen.border(0) + def main(): """Test most of the GUI (except lockout processing) @@ -656,6 +679,7 @@ def main(): # Setup the screen setup_screen(screen) + # Create windows specwin = SpectrumWindow(screen) chanwin = ChannelWindow(screen) @@ -689,6 +713,9 @@ def main(): rxwin.proc_keyb_hard(keyb) rxwin.proc_keyb_soft(keyb) + if keyb == ord('Q'): + break + # Sleep to get about a 10 Hz refresh time.sleep(0.1) diff --git a/apps/ham2mon.py b/apps/ham2mon.py index 1a4966c..d53c4f8 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -52,6 +52,7 @@ def main(screen): play = PARSER.play lockout_file_name = PARSER.lockout_file_name priority_file_name = PARSER.priority_file_name + #log_file_name = PARSER.log_file_name freq_correction = PARSER.freq_correction audio_bps = PARSER.audio_bps scanner = scnr.Scanner(ask_samp_rate, num_demod, type_demod, hw_args, @@ -69,6 +70,8 @@ def main(screen): # Get the initial settings for GUI rxwin.center_freq = scanner.center_freq + rxwin.min_freq = scanner.min_freq + rxwin.max_freq = scanner.max_freq rxwin.samp_rate = scanner.samp_rate rxwin.gain_db = scanner.gain_db rxwin.if_gain_db = scanner.if_gain_db @@ -79,6 +82,7 @@ def main(screen): rxwin.type_demod = type_demod rxwin.lockout_file_name = scanner.lockout_file_name rxwin.priority_file_name = scanner.priority_file_name + #rxwin.log_file_name = scanner.log_file_name specwin.max_db = PARSER.max_db specwin.min_db = PARSER.min_db @@ -103,6 +107,9 @@ def main(screen): # Get keystroke keyb = screen.getch() + if keyb == ord('Q'): + break + # Send keystroke to spectrum window and update scanner if True if specwin.proc_keyb(keyb): scanner.set_threshold(specwin.threshold_db) @@ -112,6 +119,8 @@ def main(screen): # Set and update frequency scanner.set_center_freq(rxwin.center_freq) rxwin.center_freq = scanner.center_freq + rxwin.min_freq = scanner.min_freq + rxwin.max_freq = scanner.max_freq if rxwin.proc_keyb_soft(keyb): # Set and update RF gain @@ -154,3 +163,9 @@ def main(screen): print("RuntimeError: SDR hardware not detected or insufficient USB permissions. Try running as root.") print("") + finally: + # --- Cleanup on exit --- + curses.echo() + curses.nocbreak() + curses.endwin() + diff --git a/apps/receiver.py b/apps/receiver.py index 01a9227..295689e 100755 --- a/apps/receiver.py +++ b/apps/receiver.py @@ -405,7 +405,7 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, gr.top_block.__init__(self, "Receiver") # Default values - self.center_freq = 144E6 + self.center_freq = 146E6 self.gain_db = 0 self.if_gain_db = 16 self.bb_gain_db = 16 @@ -582,7 +582,7 @@ def main(): """ # Create receiver object - ask_samp_rate = 4E6 + ask_samp_rate = 2E6 num_demod = 4 type_demod = 0 hw_args = "uhd" diff --git a/apps/scanner.py b/apps/scanner.py index 99a1fa2..e4f7a58 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -111,11 +111,22 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, # Get the hardware sample rate and center frequency self.samp_rate = self.receiver.samp_rate self.center_freq = self.receiver.center_freq + self.min_freq = (self.center_freq - self.samp_rate/2) + self.max_freq = (self.center_freq + self.samp_rate/2) # Start the receiver and wait for samples to accumulate self.receiver.start() time.sleep(1) + self.spectrum = self.receiver.probe_signal_vf.level() + +# # removed this since its essentially the same as above and this required spectrum first +# # estimate min/max frequency based on spectrum length and sample rate +# self.min_freq = ((0 - len(self.spectrum)/2) * (self.samp_rate / len(self.spectrum) \ +# + self.center_freq)) +# self.max_freq = ((len(self.spectrum) - len(self.spectrum)/2) * (self.samp_rate / len(self.spectrum) \ +# + self.center_freq)) + def scan_cycle(self): """Execute one scan cycle @@ -141,9 +152,7 @@ def scan_cycle(self): # Grab the FFT data, set threshold, and estimate baseband channels self.spectrum = self.receiver.probe_signal_vf.level() threshold = 10**(self.threshold_db/10.0) - channels = np.array(estimate.channel_estimate(self.spectrum, - threshold)) - + channels = np.array(estimate.channel_estimate(self.spectrum, threshold)) # Convert channels from bin indices to baseband frequency in Hz channels = (channels-len(self.spectrum)/2)*\ @@ -318,6 +327,10 @@ def set_center_freq(self, center_freq): self.receiver.set_center_freq(center_freq) self.center_freq = self.receiver.center_freq + # reset min/max based on sample rate + self.min_freq = (self.center_freq - self.samp_rate/2) + self.max_freq = (self.center_freq + self.samp_rate/2) + # Update the priority since frequency is changing self.update_priority() From 5128b48a6a24cde9943a80d82404839253a1b34a Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Thu, 31 Dec 2020 00:35:21 -0800 Subject: [PATCH 10/41] Fixed attributions ahead of time in README for pending pull from john (long running demod fix) and kibihrchak (logger) --- README.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 839934c..67de55c 100644 --- a/README.md +++ b/README.md @@ -37,12 +37,24 @@ madengr: - Priority channels ta6o: -- initial python3 fixes for syntax +- Initial python3 fixes for syntax + +kibihrchak: +- Logger branch text file log entries (pending pull into lordmorgul repo) + +john: +- long running file end (pending pull into lordmorgul repo) lordmorgul: -- min and max spectrum switches -- python3 builtin functions correction for priority and lockout parsing -- example priority and lockout files +- Min and max spectrum switches +- Python3 builtin functions correction for priority and lockout parsing +- Example priority and lockout files +- Spectrum bar coloration (min/threshold/max) +- Active channel tracking and coloration +- GUI adjustments in channel and receiver windows, borders and labels +- priority, lockout, and text log file name displays +- log file framework with enable flags (to prepare for multiple loggers implemented, text and database) + ## Console Operation: From f0e49d9d996bc9dbd1b16225c864e9fb02a0fd7f Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Thu, 31 Dec 2020 01:50:23 -0800 Subject: [PATCH 11/41] Initial capture of logger branch manual merge from kibihrchak Changes to be committed: modified: apps/cursesgui.py modified: apps/ham2mon.py modified: apps/parser.py modified: apps/scanner.py --- apps/cursesgui.py | 10 +++++----- apps/ham2mon.py | 6 +++--- apps/parser.py | 7 +++++++ apps/scanner.py | 40 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 52 insertions(+), 11 deletions(-) diff --git a/apps/cursesgui.py b/apps/cursesgui.py index 1e21050..423a6ab 100755 --- a/apps/cursesgui.py +++ b/apps/cursesgui.py @@ -377,7 +377,7 @@ def __init__(self, screen): self.record = True self.lockout_file_name = "" self.priority_file_name = "" -# self.log_file_name = "" + self.channel_log_file_name = "" # Create a window object in the bottom half of the screen # Make it about 1/3 the screen width @@ -429,8 +429,8 @@ def draw_rx(self): self.win.addnstr(12, 1, text, 18, curses.color_pair(6)) text = "Priority File : " self.win.addnstr(13, 1, text, 18, curses.color_pair(6)) -# text = "Log File : " -# self.win.addnstr(14, 1, text, 18, curses.color_pair(6)) + text = "Log File : " + self.win.addnstr(14, 1, text, 18, curses.color_pair(6)) # text = "Log Mode : " # self.win.addnstr(15, 1, text, 18, curses.color_pair(6)) # text = "Log Interval : " @@ -466,8 +466,8 @@ def draw_rx(self): self.win.addnstr(12, 20, text, 20, curses.color_pair(6)) text = str(self.priority_file_name) self.win.addnstr(13, 20, text, 20, curses.color_pair(6)) -# text = str(self.log_file_name) -# self.win.addnstr(14, 20, text, 20, curses.color_pair(6)) + text = str(self.channel_log_file_name) + self.win.addnstr(14, 20, text, 20, curses.color_pair(6)) # text = str(self.log_mode) # self.win.addnstr(14, 20, text, 20, curses.color_pair(6)) # text = str(self.log_interval) diff --git a/apps/ham2mon.py b/apps/ham2mon.py index d53c4f8..6c119b2 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -52,12 +52,12 @@ def main(screen): play = PARSER.play lockout_file_name = PARSER.lockout_file_name priority_file_name = PARSER.priority_file_name - #log_file_name = PARSER.log_file_name + channel_log_file_name = PARSER.channel_log_file_name freq_correction = PARSER.freq_correction audio_bps = PARSER.audio_bps scanner = scnr.Scanner(ask_samp_rate, num_demod, type_demod, hw_args, freq_correction, record, lockout_file_name, - priority_file_name, play, audio_bps) + priority_file_name, channel_log_file_name, play, audio_bps) # Set the paramaters scanner.set_center_freq(PARSER.center_freq) @@ -82,7 +82,7 @@ def main(screen): rxwin.type_demod = type_demod rxwin.lockout_file_name = scanner.lockout_file_name rxwin.priority_file_name = scanner.priority_file_name - #rxwin.log_file_name = scanner.log_file_name + rxwin.channel_log_file_name = scanner.channel_log_file_name specwin.max_db = PARSER.max_db specwin.min_db = PARSER.min_db diff --git a/apps/parser.py b/apps/parser.py index 6c547ee..6d6c5f7 100755 --- a/apps/parser.py +++ b/apps/parser.py @@ -93,6 +93,11 @@ def __init__(self): default="", help="File of EOL delimited priority channels in Hz") + parser.add_option("-L", "--log_file", type="string", + dest="channel_log_file_name", + default="", + help="Log file for channel detection") + parser.add_option("-c", "--correction", type="int", dest="freq_correction", default=0, help="Frequency correction in ppm") @@ -132,6 +137,7 @@ def __init__(self): self.play = bool(options.play) self.lockout_file_name = str(options.lockout_file_name) self.priority_file_name = str(options.priority_file_name) + self.channel_log_file_name = str(options.channel_log_file_name) self.freq_correction = int(options.freq_correction) self.audio_bps = int(options.audio_bps) self.max_db = float(options.max_db) @@ -161,6 +167,7 @@ def main(): print("record: " + str(parser.record)) print("lockout_file_name: " + str(parser.lockout_file_name)) print("priority_file_name: " + str(parser.priority_file_name)) + print("channel_log_file_name: " + str(parser.channel_log_file_name)) print("freq_correction: " + str(parser.freq_correction)) print("audio_bps: " + str(parser.audio_bps)) print("max_db: " + str(parser.max_db)) diff --git a/apps/scanner.py b/apps/scanner.py index e4f7a58..7b04158 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -13,6 +13,7 @@ import numpy as np import sys import types +import datetime PY3 = sys.version_info[0] == 3 PY2 = sys.version_info[0] == 2 @@ -80,7 +81,8 @@ class Scanner(object): def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, hw_args="uhd", freq_correction=0, record=True, - lockout_file_name="", priority_file_name="", play=True, + lockout_file_name="", priority_file_name="", + channel_log_file_name="", play=True, audio_bps=8): # Default values @@ -102,12 +104,19 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.channel_spacing = 5000 self.lockout_file_name = lockout_file_name self.priority_file_name = priority_file_name + self.channel_log_file_name = channel_log_file_name # Create receiver object self.receiver = recvr.Receiver(ask_samp_rate, num_demod, type_demod, hw_args, freq_correction, record, play, audio_bps) + # Open channel log file for appending data, if it is specified + if channel_log_file_name != "": + self.channel_log_file = open(channel_log_file_name, 'a') + else: + self.channel_log_file = None + # Get the hardware sample rate and center frequency self.samp_rate = self.receiver.samp_rate self.center_freq = self.receiver.center_freq @@ -118,15 +127,34 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.receiver.start() time.sleep(1) - self.spectrum = self.receiver.probe_signal_vf.level() + if self.channel_log_file != None : + self.channel_log_file.flush() # # removed this since its essentially the same as above and this required spectrum first +# self.spectrum = self.receiver.probe_signal_vf.level() # # estimate min/max frequency based on spectrum length and sample rate # self.min_freq = ((0 - len(self.spectrum)/2) * (self.samp_rate / len(self.spectrum) \ # + self.center_freq)) # self.max_freq = ((len(self.spectrum) - len(self.spectrum)/2) * (self.samp_rate / len(self.spectrum) \ # + self.center_freq)) + + def __del__(self): + if self.channel_log_file != None : + self.channel_log_file.close() + + def __print_channel_log__(self, freq, state): + if self.channel_log_file is not None: + state_str = {True: "on", False: "off"} + now = datetime.datetime.now() + self.channel_log_file.write( + "{}: {:<4}{:>13}{:>7}{:>7}\n".format( + now.strftime("%Y-%m-%d, %H:%M:%S.%f"), + state_str[state], + self.center_freq + freq, + self.gain_db, + self.threshold_db)) + def scan_cycle(self): """Execute one scan cycle @@ -191,6 +219,10 @@ def scan_cycle(self): for demodulator in self.receiver.demodulators: if demodulator.center_freq not in channels: demodulator.set_center_freq(0, self.center_freq) + # Write in channel log file that the channel is off + demodulator_freq = demodulator.center_freq + self.__print_channel_log__(demodulator_freq, False) + else: pass @@ -203,7 +235,9 @@ def scan_cycle(self): # If demodulator is empty and channel not already there if (demodulator.center_freq == 0) and \ (channel not in self.receiver.get_demod_freqs()): - # Assing channel to empty demodulator + # Write in channel log file that the channel is on + self.__print_channel_log__(channel, True) + # Assigning channel to empty demodulator demodulator.set_center_freq(channel, self.center_freq) else: pass From a12abb1285aebfdc24905c849e65a688cddc37f1 Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 2 Jan 2021 00:51:47 -0800 Subject: [PATCH 12/41] Added documentation from previous work logger branch and added a active channel logging timeout to not flood log file, apparnetly still too frequency so needs fixed, does log active channels as well as demodulators turned on and off Changes to be committed: modified: ../README.md modified: cursesgui.py modified: ham2mon.py modified: parser.py modified: scanner.py --- README.md | 14 +++++++++++++- apps/cursesgui.py | 11 ++++++----- apps/ham2mon.py | 5 ++++- apps/parser.py | 9 +++++++++ apps/scanner.py | 44 ++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 74 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 67de55c..d17e15e 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ ta6o: - Initial python3 fixes for syntax kibihrchak: -- Logger branch text file log entries (pending pull into lordmorgul repo) +- Logger branch text file log entries john: - long running file end (pending pull into lordmorgul repo) @@ -78,6 +78,12 @@ Example of reading from an IQ file: ./ham2mon.py -a "file=gqrx.raw,rate=8E6,repeat=false,throttle=true,freq=466E6" -r 8E6 -w +##Channel Detection Log File + +For console operation, it is possible to specify the log file name, in which channel detection, and removal will be logged. The option is `--log_file=`. + +Whenever a channel appears/dissapears, new line will be written in the log file. For the line format, check `__print_channel_log__()` in `scanner.Scanner`. + ## GUI Controls: `t/r = Detection threshold +/- 5 dB. (T/R for +/- 1dB)` @@ -161,6 +167,12 @@ Example of reading from an IQ file: ` -p PRIORITY_FILE_NAME, --priority=PRIORITY_FILE_NAME` ` File of EOL delimited priority channels in Hz` +` -L CHANNEL_LOG_FILE_NAME, --log-file=CHANNEL_LOG_FILE_NAME` +` File for output of channel activity (demod lock/unlock) and active channels detection` + +` -A LOG_ACTIVE_TIMEOUT, --log_active_timeout=LOG_ACTIVE_TIMEOUT` +` Timeout delay between marking a channel active in the log file in seconds` + ` -c FREQ_CORRECTION, --correction=FREQ_CORRECTION` ` Frequency correction in ppm` diff --git a/apps/cursesgui.py b/apps/cursesgui.py index 423a6ab..fcffab7 100755 --- a/apps/cursesgui.py +++ b/apps/cursesgui.py @@ -378,6 +378,7 @@ def __init__(self, screen): self.lockout_file_name = "" self.priority_file_name = "" self.channel_log_file_name = "" + self.channel_log_timeout = 15 # Create a window object in the bottom half of the screen # Make it about 1/3 the screen width @@ -431,9 +432,9 @@ def draw_rx(self): self.win.addnstr(13, 1, text, 18, curses.color_pair(6)) text = "Log File : " self.win.addnstr(14, 1, text, 18, curses.color_pair(6)) + text = "Log Timeout (s): " + self.win.addnstr(15, 1, text, 18, curses.color_pair(6)) # text = "Log Mode : " -# self.win.addnstr(15, 1, text, 18, curses.color_pair(6)) -# text = "Log Interval : " # self.win.addnstr(16, 1, text, 18, curses.color_pair(6)) # Draw the receiver info suffix fields @@ -468,10 +469,10 @@ def draw_rx(self): self.win.addnstr(13, 20, text, 20, curses.color_pair(6)) text = str(self.channel_log_file_name) self.win.addnstr(14, 20, text, 20, curses.color_pair(6)) + text = str(self.channel_log_timeout) + self.win.addnstr(15, 20, text, 20, curses.color_pair(6)) # text = str(self.log_mode) -# self.win.addnstr(14, 20, text, 20, curses.color_pair(6)) -# text = str(self.log_interval) -# self.win.addnstr(15, 20, text, 20, curses.color_pair(6)) +# self.win.addnstr(16, 20, text, 20, curses.color_pair(6)) # Hide cursor self.win.leaveok(1) diff --git a/apps/ham2mon.py b/apps/ham2mon.py index 6c119b2..475bd1a 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -53,11 +53,13 @@ def main(screen): lockout_file_name = PARSER.lockout_file_name priority_file_name = PARSER.priority_file_name channel_log_file_name = PARSER.channel_log_file_name + channel_log_timeout = PARSER.channel_log_timeout freq_correction = PARSER.freq_correction audio_bps = PARSER.audio_bps scanner = scnr.Scanner(ask_samp_rate, num_demod, type_demod, hw_args, freq_correction, record, lockout_file_name, - priority_file_name, channel_log_file_name, play, audio_bps) + priority_file_name, channel_log_file_name, channel_log_timeout, + play, audio_bps) # Set the paramaters scanner.set_center_freq(PARSER.center_freq) @@ -83,6 +85,7 @@ def main(screen): rxwin.lockout_file_name = scanner.lockout_file_name rxwin.priority_file_name = scanner.priority_file_name rxwin.channel_log_file_name = scanner.channel_log_file_name + rxwin.channel_log_timeout = scanner.channel_log_timeout specwin.max_db = PARSER.max_db specwin.min_db = PARSER.min_db diff --git a/apps/parser.py b/apps/parser.py index 6d6c5f7..4a41c02 100755 --- a/apps/parser.py +++ b/apps/parser.py @@ -25,6 +25,8 @@ class CLParser(object): play (bool): Play audio through speaker if True lockout_file_name (string): Name of file with channels to lockout priority_file_name (string): Name of file with channels to for priority + channel_log_file_name (string): Name of file for channel logging + channel_log_timeout (int): Timeout delay between active channel log entries freq_correction (int): Frequency correction in ppm audio_bps (int): Audio bit depth in bps max_db (float): Spectrum max dB for display @@ -98,6 +100,11 @@ def __init__(self): default="", help="Log file for channel detection") + parser.add_option("-A", "--log_active_timeout", type="int", + dest="channel_log_timeout", + default=15, + help="Timeout delay for active channel log entries") + parser.add_option("-c", "--correction", type="int", dest="freq_correction", default=0, help="Frequency correction in ppm") @@ -138,6 +145,7 @@ def __init__(self): self.lockout_file_name = str(options.lockout_file_name) self.priority_file_name = str(options.priority_file_name) self.channel_log_file_name = str(options.channel_log_file_name) + self.channel_log_timeout = int(options.channel_log_timeout) self.freq_correction = int(options.freq_correction) self.audio_bps = int(options.audio_bps) self.max_db = float(options.max_db) @@ -168,6 +176,7 @@ def main(): print("lockout_file_name: " + str(parser.lockout_file_name)) print("priority_file_name: " + str(parser.priority_file_name)) print("channel_log_file_name: " + str(parser.channel_log_file_name)) + print("channel_log_timeout: " + str(parser.channel_log_timeout)) print("freq_correction: " + str(parser.freq_correction)) print("audio_bps: " + str(parser.audio_bps)) print("max_db: " + str(parser.max_db)) diff --git a/apps/scanner.py b/apps/scanner.py index 7b04158..dc5fc94 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -75,6 +75,9 @@ class Scanner(object): channel_spacing (float): Spacing that channels will be rounded lockout_file_name (string): Name of file with channels to lockout priority_file_name (string): Name of file with channels for priority + channel_log_file_name (string): Name of file with channel log entries + channel_log_timeout (int): Timeout delay between active channel entries in log + log_timeout_last (int): Last timestamp when recently active channels were logged and cleared """ # pylint: disable=too-many-instance-attributes # pylint: disable=too-many-arguments @@ -82,7 +85,8 @@ class Scanner(object): def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, hw_args="uhd", freq_correction=0, record=True, lockout_file_name="", priority_file_name="", - channel_log_file_name="", play=True, + channel_log_file_name="", channel_log_timeout=15, + play=True, audio_bps=8): # Default values @@ -105,6 +109,10 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.lockout_file_name = lockout_file_name self.priority_file_name = priority_file_name self.channel_log_file_name = channel_log_file_name + self.channel_log_timeout = channel_log_timeout + self.log_recent_channels = [] + self.log_timeout_last = int(time.time()) + # Create receiver object self.receiver = recvr.Receiver(ask_samp_rate, num_demod, type_demod, @@ -143,6 +151,19 @@ def __del__(self): if self.channel_log_file != None : self.channel_log_file.close() + def __print_channel_log_active__(self, freq, state): + if self.channel_log_file is not None: + state_str = {True: "active", False: "off"} + now = datetime.datetime.now() + self.channel_log_file.write( + "{}: {:<4}{:>13}{:>7}{:>7}{:>7}\n".format( + now.strftime("%Y-%m-%d, %H:%M:%S.%f"), + state_str[state], + self.center_freq + freq, + self.gain_db, + self.threshold_db, + self.channel_log_timeout)) + def __print_channel_log__(self, freq, state): if self.channel_log_file is not None: state_str = {True: "on", False: "off"} @@ -266,6 +287,23 @@ def scan_cycle(self): gui_active_channel = (channel + self.center_freq)/1E6 text = '{:.3f}'.format(gui_active_channel) self.gui_active_channels.append(text) + self.log_recent_channels.append(gui_active_channel) + + # log recently active channels if we are beyond timeout delay from last logging + cur_timestamp = int(time.time()) + # if cur_timestamp > timeout_timestamp + timeout + if cur_timestamp > (self.log_timeout_last + self.channel_log_timeout): + # iterate all recent channels print to log + for channel in self.log_recent_channels: + text = '{:.3f}'.format(channel) + # Write in channel log file that the channel is on + self.__print_channel_log_active__(channel, True) + + # clear recent channels + self.log_recent_channels = [] + # set last timeout to this timestamp + self.log_timeout_last = cur_timestamp + def add_lockout(self, idx): @@ -457,10 +495,12 @@ def main(): record = parser.record lockout_file_name = parser.lockout_file_name priority_file_name = parser.priority_file_name + channel_log_file_name = parser.channel_log_file_name audio_bps = parser.audio_bps scanner = Scanner(ask_samp_rate, num_demod, type_demod, hw_args, freq_correction, record, lockout_file_name, - priority_file_name, audio_bps) + priority_file_name, channel_log_file_name, + audio_bps) # Set frequency, gain, squelch, and volume scanner.set_center_freq(parser.center_freq) From f838a9eba09cc448e73ccce8857e05906af5b6fe Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 2 Jan 2021 15:47:50 -0800 Subject: [PATCH 13/41] Log file framework improvements, exceptions to raise log error, and active channel outputs reduced to correct excessive active log entries, but still has excess entries for off channels (seems not only when demodulator is cleared but repeats Changes to be committed: new file: errors.py modified: ham2mon.py modified: scanner.py --- apps/errors.py | 16 +++++++++++ apps/ham2mon.py | 6 +++++ apps/scanner.py | 71 ++++++++++++++++++++++++++++++++----------------- 3 files changed, 69 insertions(+), 24 deletions(-) create mode 100644 apps/errors.py diff --git a/apps/errors.py b/apps/errors.py new file mode 100644 index 0000000..4a16dcf --- /dev/null +++ b/apps/errors.py @@ -0,0 +1,16 @@ +class Error(Exception): + """Base class for exceptions in this module.""" + pass + +class LogError(Error): + """Exception raised for errors in the log system. + + Attributes: + expression -- input expression in which the error occurred + message -- explanation of the error + """ + + def __init__(self, expression, message): + self.expression = expression + self.message = message + diff --git a/apps/ham2mon.py b/apps/ham2mon.py index 475bd1a..e571a16 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -11,6 +11,7 @@ import cursesgui import parser import time +import errors as err def main(screen): """Start scanner with GUI interface @@ -165,6 +166,11 @@ def main(screen): print("") print("RuntimeError: SDR hardware not detected or insufficient USB permissions. Try running as root.") print("") + except LogError: + print("") + print("LogError: database logging not active, to be expanded.") + print("") + finally: # --- Cleanup on exit --- diff --git a/apps/scanner.py b/apps/scanner.py index dc5fc94..fd43986 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -14,6 +14,7 @@ import sys import types import datetime +import errors as err PY3 = sys.version_info[0] == 3 PY2 = sys.version_info[0] == 2 @@ -112,7 +113,7 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.channel_log_timeout = channel_log_timeout self.log_recent_channels = [] self.log_timeout_last = int(time.time()) - + self.log_mode = "" # Create receiver object self.receiver = recvr.Receiver(ask_samp_rate, num_demod, type_demod, @@ -122,6 +123,13 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, # Open channel log file for appending data, if it is specified if channel_log_file_name != "": self.channel_log_file = open(channel_log_file_name, 'a') + if self.channel_log_file != None: + self.log_mode = "file" + else: + # Opening log file failed so cannot perform this log mode + # Either raise exception or continue without logging, second preferable + self.log_mode = "" + #raise(LogError("file","Cannot open log file")) else: self.channel_log_file = None @@ -152,29 +160,44 @@ def __del__(self): self.channel_log_file.close() def __print_channel_log_active__(self, freq, state): - if self.channel_log_file is not None: - state_str = {True: "active", False: "off"} + if self.log_mode is not None and state is True: + state_str = {True: "act", False: "off"} now = datetime.datetime.now() - self.channel_log_file.write( - "{}: {:<4}{:>13}{:>7}{:>7}{:>7}\n".format( - now.strftime("%Y-%m-%d, %H:%M:%S.%f"), - state_str[state], - self.center_freq + freq, - self.gain_db, - self.threshold_db, - self.channel_log_timeout)) + if self.log_mode == "file" and self.channel_log_file is not None: + self.channel_log_file.write( + "{}: {:<4}{:>13}{:>7}{:>7}{:>7}\n".format( + now.strftime("%Y-%m-%d, %H:%M:%S.%f"), + state_str[state], + self.center_freq + freq, + self.gain_db, + self.threshold_db, + self.channel_log_timeout)) + elif self.log_mode == "db": + # write log to db + raise(err.LogError("db","no db mode implemented")) + else: + # cannot log unknown mode + raise(err.LogError("unknown","no log mode defined")) def __print_channel_log__(self, freq, state): - if self.channel_log_file is not None: + if self.log_mode is not None: state_str = {True: "on", False: "off"} now = datetime.datetime.now() - self.channel_log_file.write( - "{}: {:<4}{:>13}{:>7}{:>7}\n".format( - now.strftime("%Y-%m-%d, %H:%M:%S.%f"), - state_str[state], - self.center_freq + freq, - self.gain_db, - self.threshold_db)) + if self.log_mode == "file" and self.channel_log_file is not None: + self.channel_log_file.write( + "{}: {:<4}{:>13}{:>7}{:>7}\n".format( + now.strftime("%Y-%m-%d, %H:%M:%S.%f"), + state_str[state], + self.center_freq + freq, + self.gain_db, + self.threshold_db)) + elif self.log_mode == "db": + # write log to db + raise(err.LogError("db","no db mode implemented")) + else: + # cannot log unknown mode + raise(err.LogError("unknown","no log mode defined")) + def scan_cycle(self): """Execute one scan cycle @@ -243,7 +266,6 @@ def scan_cycle(self): # Write in channel log file that the channel is off demodulator_freq = demodulator.center_freq self.__print_channel_log__(demodulator_freq, False) - else: pass @@ -287,22 +309,23 @@ def scan_cycle(self): gui_active_channel = (channel + self.center_freq)/1E6 text = '{:.3f}'.format(gui_active_channel) self.gui_active_channels.append(text) - self.log_recent_channels.append(gui_active_channel) + # Add active channel to recent list for logging if not already there + if gui_active_channel not in self.log_recent_channels: + self.log_recent_channels.append(gui_active_channel) # log recently active channels if we are beyond timeout delay from last logging cur_timestamp = int(time.time()) # if cur_timestamp > timeout_timestamp + timeout if cur_timestamp > (self.log_timeout_last + self.channel_log_timeout): + # set last timeout to this timestamp + self.log_timeout_last = cur_timestamp # iterate all recent channels print to log for channel in self.log_recent_channels: text = '{:.3f}'.format(channel) # Write in channel log file that the channel is on self.__print_channel_log_active__(channel, True) - # clear recent channels self.log_recent_channels = [] - # set last timeout to this timestamp - self.log_timeout_last = cur_timestamp From a1f84a319c107f28cc8db8de8d7bd8255384602d Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 2 Jan 2021 16:34:37 -0800 Subject: [PATCH 14/41] File logging under test but appears stable. Format string edited to add dB, timeout or channel indicator and the demodulator number that is turned on or off. Attempted fix of catch exception correctly for LogError. Changes to be committed: modified: ham2mon.py modified: scanner.py --- apps/ham2mon.py | 2 +- apps/scanner.py | 35 ++++++++++++++++++++++------------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/apps/ham2mon.py b/apps/ham2mon.py index e571a16..2e905e1 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -166,7 +166,7 @@ def main(screen): print("") print("RuntimeError: SDR hardware not detected or insufficient USB permissions. Try running as root.") print("") - except LogError: + except err.LogError: print("") print("LogError: database logging not active, to be expanded.") print("") diff --git a/apps/scanner.py b/apps/scanner.py index fd43986..fce1d96 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -165,10 +165,10 @@ def __print_channel_log_active__(self, freq, state): now = datetime.datetime.now() if self.log_mode == "file" and self.channel_log_file is not None: self.channel_log_file.write( - "{}: {:<4}{:>13}{:>7}{:>7}{:>7}\n".format( + "{}: {:<4}{:>13}{:>7} dB {:>7} dB timeout {:>3}\n".format( now.strftime("%Y-%m-%d, %H:%M:%S.%f"), state_str[state], - self.center_freq + freq, + freq, self.gain_db, self.threshold_db, self.channel_log_timeout)) @@ -179,18 +179,21 @@ def __print_channel_log_active__(self, freq, state): # cannot log unknown mode raise(err.LogError("unknown","no log mode defined")) - def __print_channel_log__(self, freq, state): + def __print_channel_log__(self, freq, state, idx): if self.log_mode is not None: state_str = {True: "on", False: "off"} + if state == False: + freq = 0 now = datetime.datetime.now() if self.log_mode == "file" and self.channel_log_file is not None: self.channel_log_file.write( - "{}: {:<4}{:>13}{:>7}{:>7}\n".format( + "{}: {:<4}{:>13}{:>7} dB {:>7} dB channel {:>3}\n".format( now.strftime("%Y-%m-%d, %H:%M:%S.%f"), state_str[state], - self.center_freq + freq, + freq, self.gain_db, - self.threshold_db)) + self.threshold_db, + idx)) elif self.log_mode == "db": # write log to db raise(err.LogError("db","no db mode implemented")) @@ -260,12 +263,14 @@ def scan_cycle(self): channels = temp # Set demodulators that are no longer in channel list to 0 Hz - for demodulator in self.receiver.demodulators: - if demodulator.center_freq not in channels: + #for demodulator in self.receiver.demodulators: + for idx in range(len(self.receiver.demodulators)): + demodulator = self.receiver.demodulators[idx] + if (demodulator.center_freq != 0) and (demodulator.center_freq not in channels): demodulator.set_center_freq(0, self.center_freq) # Write in channel log file that the channel is off demodulator_freq = demodulator.center_freq - self.__print_channel_log__(demodulator_freq, False) + self.__print_channel_log__(demodulator_freq + self.center_freq, False, idx) else: pass @@ -274,14 +279,17 @@ def scan_cycle(self): # If channel not in demodulators if channel not in self.receiver.get_demod_freqs(): # Sequence through each demodulator - for demodulator in self.receiver.demodulators: + #for demodulator in self.receiver.demodulators: + for idx in range(len(self.receiver.demodulators)): + demodulator = self.receiver.demodulators[idx] # If demodulator is empty and channel not already there if (demodulator.center_freq == 0) and \ (channel not in self.receiver.get_demod_freqs()): # Write in channel log file that the channel is on - self.__print_channel_log__(channel, True) + self.__print_channel_log__(channel + self.center_freq, True, idx) # Assigning channel to empty demodulator demodulator.set_center_freq(channel, self.center_freq) + break else: pass else: @@ -314,6 +322,8 @@ def scan_cycle(self): self.log_recent_channels.append(gui_active_channel) # log recently active channels if we are beyond timeout delay from last logging + # clear list of recently active channels after logging + # reset timeout (a low fidelity/effort timer) cur_timestamp = int(time.time()) # if cur_timestamp > timeout_timestamp + timeout if cur_timestamp > (self.log_timeout_last + self.channel_log_timeout): @@ -321,9 +331,8 @@ def scan_cycle(self): self.log_timeout_last = cur_timestamp # iterate all recent channels print to log for channel in self.log_recent_channels: - text = '{:.3f}'.format(channel) # Write in channel log file that the channel is on - self.__print_channel_log_active__(channel, True) + self.__print_channel_log_active__(float(channel)*1E6, True) # clear recent channels self.log_recent_channels = [] From 42d90d8be637e21673ee644d413f4a0e1e194bb5 Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Mon, 4 Jan 2021 00:11:09 -0800 Subject: [PATCH 15/41] corrections to README and added screenshots for gui and logger updates --- ham2mon_priority_channels_active.png | Bin 0 -> 62207 bytes ham2mon_priority_channels_inactive_noise.png | Bin 0 -> 59624 bytes ham2mon_priority_channels_overmax.png | Bin 0 -> 71725 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 ham2mon_priority_channels_active.png create mode 100644 ham2mon_priority_channels_inactive_noise.png create mode 100644 ham2mon_priority_channels_overmax.png diff --git a/ham2mon_priority_channels_active.png b/ham2mon_priority_channels_active.png new file mode 100644 index 0000000000000000000000000000000000000000..f7fd79bb2d07ae183a5325446c5a246999736e13 GIT binary patch literal 62207 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%0Dlj@>;te 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 RT811TAtrk_Q{>UJ{{?TbL-_yz literal 0 HcmV?d00001 diff --git a/ham2mon_priority_channels_overmax.png b/ham2mon_priority_channels_overmax.png new file mode 100644 index 0000000000000000000000000000000000000000..de3e0a17e22a7e834e744378cabd828da89025a1 GIT binary patch literal 71725 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 Je_?j?k}_xiZ0!AA4m7l$ovb19@lkDQV+ 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 Date: Mon, 4 Jan 2021 00:26:09 -0800 Subject: [PATCH 16/41] Update README.md --- README.md | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index d17e15e..6938976 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,14 @@ This is a GNU Radio (GR) based SDR scanner with a Curses interface, primarily me http://youtu.be/BXptQFSV8E4 -![GUI screenshot](https://github.com/madengr/ham2mon/blob/master/ham2mon.png) +Original screenshot +![GUI screenshot](https://github.com/lordmorgul/ham2mon/blob/master/ham2mon.png) + +Additional screenshots show updated screen color and channel highlighting with +![GUI screenshot](https://github.com/lordmorgul/ham2mon/blob/master/ham2mon_priority_channels_inactive_noise.png) +![GUI screenshot](https://github.com/lordmorgul/ham2mon/blob/master/ham2mon_priority_channels_active.png) +![GUI screenshot](https://github.com/lordmorgul/ham2mon/blob/master/ham2mon_priority_channels_overmax.png) + ## Tested with: - Ettus B200 at 16 Msps (http://www.ettus.com) @@ -13,6 +20,26 @@ http://youtu.be/BXptQFSV8E4 - Ettus UHD 3.10.0 (https://github.com/EttusResearch/uhd) ## Contributors: +lordmorgul: +- Min and max spectrum switches +- Python3 builtin functions correction for priority and lockout parsing +- Example priority and lockout files +- Spectrum bar coloration (min/threshold/max) +- Active channel tracking and coloration +- GUI adjustments in channel and receiver windows, borders and labels +- priority, lockout, and text log file name displays +- pulled logger framework from kibihrchak and revised to python3 +- log file framework with enable flags (to prepare for multiple loggers implemented, text and database) +- log file timeout so active channels are indicated only every TIMEOUT seconds + +john: +- long running file end (pending pull into lordmorgul repo) + +kibihrchak: +- Logger branch text file log entries + +ta6o: +- Initial python3 fixes for syntax m0mik: - Added HackRF IF/BB gain parameters @@ -36,25 +63,6 @@ madengr: - AM demodulation - Priority channels -ta6o: -- Initial python3 fixes for syntax - -kibihrchak: -- Logger branch text file log entries - -john: -- long running file end (pending pull into lordmorgul repo) - -lordmorgul: -- Min and max spectrum switches -- Python3 builtin functions correction for priority and lockout parsing -- Example priority and lockout files -- Spectrum bar coloration (min/threshold/max) -- Active channel tracking and coloration -- GUI adjustments in channel and receiver windows, borders and labels -- priority, lockout, and text log file name displays -- log file framework with enable flags (to prepare for multiple loggers implemented, text and database) - ## Console Operation: From 2ca92104e0ef2076c46cbfb8553fd5607718b31d Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Mon, 4 Jan 2021 12:38:12 -0800 Subject: [PATCH 17/41] cleanup README attempt again --- README.md | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index d17e15e..32d23a6 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,13 @@ This is a GNU Radio (GR) based SDR scanner with a Curses interface, primarily me http://youtu.be/BXptQFSV8E4 -![GUI screenshot](https://github.com/madengr/ham2mon/blob/master/ham2mon.png) +Original screenshot +![GUI screenshot](https://github.com/lordmorgul/ham2mon/blob/master/ham2mon.png) + +Additional screenshots show updated screen color and channel highlighting with +![GUI screenshot](https://github.com/lordmorgul/ham2mon/blob/master/ham2mon_priority_channels_inactive_noise.png) +![GUI screenshot](https://github.com/lordmorgul/ham2mon/blob/master/ham2mon_priority_channels_active.png) +![GUI screenshot](https://github.com/lordmorgul/ham2mon/blob/master/ham2mon_priority_channels_overmax.png) ## Tested with: - Ettus B200 at 16 Msps (http://www.ettus.com) @@ -13,6 +19,26 @@ http://youtu.be/BXptQFSV8E4 - Ettus UHD 3.10.0 (https://github.com/EttusResearch/uhd) ## Contributors: +lordmorgul: +- Min and max spectrum switches +- Python3 builtin functions correction for priority and lockout parsing +- Example priority and lockout files +- Spectrum bar coloration (min/threshold/max) +- Active channel tracking and coloration +- GUI adjustments in channel and receiver windows, borders and labels +- priority, lockout, and text log file name displays +- pulled logger framework from kibihrchak and revised to python3 +- log file framework with enable flags (to prepare for multiple loggers implemented, text and database) +- log file timeout so active channels are indicated only every TIMEOUT seconds + +john: +- long running file end (pending pull into lordmorgul repo) + +kibihrchak: +- Logger branch text file log entries + +ta6o: +- Initial python3 fixes for syntax m0mik: - Added HackRF IF/BB gain parameters @@ -36,25 +62,6 @@ madengr: - AM demodulation - Priority channels -ta6o: -- Initial python3 fixes for syntax - -kibihrchak: -- Logger branch text file log entries - -john: -- long running file end (pending pull into lordmorgul repo) - -lordmorgul: -- Min and max spectrum switches -- Python3 builtin functions correction for priority and lockout parsing -- Example priority and lockout files -- Spectrum bar coloration (min/threshold/max) -- Active channel tracking and coloration -- GUI adjustments in channel and receiver windows, borders and labels -- priority, lockout, and text log file name displays -- log file framework with enable flags (to prepare for multiple loggers implemented, text and database) - ## Console Operation: From 7732aaab161936b5a957ed42a435132d452b45fa Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Tue, 5 Jan 2021 01:23:06 -0800 Subject: [PATCH 18/41] Initial capture of demodulator long runtime kill and gain set and filter based on capabilities changes from john-, minimal testing, from john/gain_changes_and_long_xmit_kill branch with updates for python3, made killed demod resume set frequency so new file is created but assigned channel remains assigned and a demod on it --- apps/cursesgui.py | 105 ++++++++++++++++++++++------------------------ apps/ham2mon.py | 23 ++++------ apps/parser.py | 33 +++++++++++---- apps/receiver.py | 57 ++++++++++++------------- apps/scanner.py | 75 ++++++++++++++++++--------------- 5 files changed, 150 insertions(+), 143 deletions(-) diff --git a/apps/cursesgui.py b/apps/cursesgui.py index fcffab7..d177929 100755 --- a/apps/cursesgui.py +++ b/apps/cursesgui.py @@ -348,9 +348,7 @@ class RxWindow(object): Attributes: center_freq (float): Hardware RF center frequency in Hz samp_rate (float): Hardware sample rate in sps (1E6 min) - gain_db (int): Hardware RF gain in dB - if_gain_db (int): Hardware IF gain in dB - bb_gain_db (int): Hardware BB gain in dB + gains (list): Hardware gains in dB squelch_db (int): Squelch in dB volume_dB (int): Volume in dB record (bool): Record audio to file if True @@ -368,9 +366,6 @@ def __init__(self, screen): self.max_freq = 148E6 self.samp_rate = 2E6 self.freq_entry = 'None' - self.gain_db = 0 - self.if_gain_db = 16 - self.bb_gain_db = 16 self.squelch_db = -60 self.volume_db = 0 self.type_demod = 0 @@ -410,32 +405,31 @@ def draw_rx(self): self.win.addnstr(2, 1, text, 18, curses.color_pair(6)) text = "Max Freq (MHz) : " self.win.addnstr(3, 1, text, 18, curses.color_pair(6)) - text = "RF Gain (dB) : " - self.win.addnstr(4, 1, text, 18, curses.color_pair(6)) - text = "IF Gain (dB) : " - self.win.addnstr(5, 1, text, 18, curses.color_pair(6)) - text = "BB Gain (dB) : " - self.win.addnstr(6, 1, text, 18, curses.color_pair(6)) + + for index, gain in enumerate(self.gains, 2): + text = "{} Gain (dB){} : ".format(gain["name"], (4-len(gain["name"]))*' ') + self.win.addnstr(index+2, 1, text, 15) + text = "BB Rate (Msps) : " - self.win.addnstr(7, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index+3, 1, text, 18, curses.color_pair(6)) text = "BB Sql (dB) : " - self.win.addnstr(8, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index+4, 1, text, 18, curses.color_pair(6)) text = "AF Vol (dB) : " - self.win.addnstr(9, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index+5, 1, text, 18, curses.color_pair(6)) text = "Record : " - self.win.addnstr(10, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index+6, 1, text, 18, curses.color_pair(6)) text = "Demod Type : " - self.win.addnstr(11, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index+7, 1, text, 18, curses.color_pair(6)) text = "Lockout File : " - self.win.addnstr(12, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index+8, 1, text, 18, curses.color_pair(6)) text = "Priority File : " - self.win.addnstr(13, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index+9, 1, text, 18, curses.color_pair(6)) text = "Log File : " - self.win.addnstr(14, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index+10, 1, text, 18, curses.color_pair(6)) text = "Log Timeout (s): " - self.win.addnstr(15, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index+11, 1, text, 18, curses.color_pair(6)) # text = "Log Mode : " -# self.win.addnstr(16, 1, text, 18, curses.color_pair(6)) +# self.win.addnstr(index+12, 1, text, 18, curses.color_pair(6)) # Draw the receiver info suffix fields if self.freq_entry != 'None': @@ -447,32 +441,31 @@ def draw_rx(self): self.win.addnstr(2, 20, text, 8, curses.color_pair(6)) text = '{:.3f}'.format((self.max_freq)/1E6) self.win.addnstr(3, 20, text, 8, curses.color_pair(6)) - text = str(self.gain_db) - self.win.addnstr(4, 20, text, 8, curses.color_pair(5)) - text = str(self.if_gain_db) - self.win.addnstr(5, 20, text, 8, curses.color_pair(5)) - text = str(self.bb_gain_db) - self.win.addnstr(6, 20, text, 8, curses.color_pair(5)) + + for index, gain in enumerate(self.gains, 2): + text = str(gain["value"]) + self.win.addnstr(index+2, 20, text, 8, curses.color_pair(5)) + text = str(self.samp_rate/1E6) - self.win.addnstr(7, 20, text, 8, curses.color_pair(6)) + self.win.addnstr(index+3, 20, text, 8, curses.color_pair(6)) text = str(self.squelch_db) - self.win.addnstr(8, 20, text, 8, curses.color_pair(5)) + self.win.addnstr(index+4, 20, text, 8, curses.color_pair(5)) text = str(self.volume_db) - self.win.addnstr(9, 20, text, 8, curses.color_pair(5)) + self.win.addnstr(index+5, 20, text, 8, curses.color_pair(5)) text = str(self.record) - self.win.addnstr(10, 20, text, 8, curses.color_pair(6)) + self.win.addnstr(index+6, 20, text, 8, curses.color_pair(6)) text = str(self.type_demod) - self.win.addnstr(11, 20, text, 8, curses.color_pair(6)) + self.win.addnstr(index+7, 20, text, 8, curses.color_pair(6)) text = str(self.lockout_file_name) - self.win.addnstr(12, 20, text, 20, curses.color_pair(6)) + self.win.addnstr(index+8, 20, text, 20, curses.color_pair(6)) text = str(self.priority_file_name) - self.win.addnstr(13, 20, text, 20, curses.color_pair(6)) + self.win.addnstr(index+9, 20, text, 20, curses.color_pair(6)) text = str(self.channel_log_file_name) - self.win.addnstr(14, 20, text, 20, curses.color_pair(6)) + self.win.addnstr(index+10, 20, text, 20, curses.color_pair(6)) text = str(self.channel_log_timeout) - self.win.addnstr(15, 20, text, 20, curses.color_pair(6)) + self.win.addnstr(index+11, 20, text, 20, curses.color_pair(6)) # text = str(self.log_mode) -# self.win.addnstr(16, 20, text, 20, curses.color_pair(6)) +# self.win.addnstr(index+12, 20, text, 20, curses.color_pair(6)) # Hide cursor self.win.leaveok(1) @@ -567,52 +560,52 @@ def proc_keyb_soft(self, keyb): # pylint: disable=too-many-return-statements # pylint: disable=too-many-branches - # Tune self.gain_db in 10 dB steps with 'g' and 'f' + # Tune 1st gain element in 10 dB steps with 'g' and 'f' if keyb == ord('g'): - self.gain_db += 10 + self.gains[0]["value"] += 10 return True elif keyb == ord('f'): - self.gain_db -= 10 + self.gains[0]["value"] -= 10 return True - # Tune self.gain_db in 1 dB steps with 'G' and 'F' + # Tune 1st gain element in 1 dB steps with 'G' and 'F' if keyb == ord('G'): - self.gain_db += 1 + self.gains[0]["value"] += 1 return True elif keyb == ord('F'): - self.gain_db -= 1 + self.gains[0]["value"] -= 1 return True - # Tune self.if_gain_db in 10 dB steps with 'u' and 'y' + # Tune 2nd gain element in 10 dB steps with 'u' and 'y' if keyb == ord('u'): - self.if_gain_db += 10 + self.gains[1]["value"] += 10 return True elif keyb == ord('y'): - self.if_gain_db -= 10 + self.gains[1]["value"] -= 10 return True - # Tune self.if_gain_db in 1 dB steps with 'U' and 'Y' + # Tune 2nd gain element in 1 dB steps with 'U' and 'Y' if keyb == ord('U'): - self.if_gain_db += 1 + self.gains[1]["value"] += 1 return True elif keyb == ord('Y'): - self.if_gain_db -= 1 + self.gains[1]["value"] -= 1 return True - # Tune self.bb_gain_db in 10 dB steps with ']' and '[' + # Tune 3rd gain element in 10 dB steps with ']' and '[' if keyb == ord(']'): - self.bb_gain_db += 10 + self.gains[2]["value"] += 10 return True elif keyb == ord('['): - self.bb_gain_db -= 10 + self.gains[2]["value"] -= 10 return True - # Tune self.bb_gain_db in 1 dB steps with '}' and '{' + # Tune 3rd gain element in 1 dB steps with '}' and '{' if keyb == ord('}'): - self.bb_gain_db += 1 + self.gains[2]["value"] += 1 return True elif keyb == ord('{'): - self.bb_gain_db -= 1 + self.gains[2]["value"] -= 1 return True # Tune self.squelch_db in 1 dB steps with 's' and 'a' diff --git a/apps/ham2mon.py b/apps/ham2mon.py index 2e905e1..5225681 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -57,28 +57,26 @@ def main(screen): channel_log_timeout = PARSER.channel_log_timeout freq_correction = PARSER.freq_correction audio_bps = PARSER.audio_bps + max_demod_length = PARSER.max_demod_length scanner = scnr.Scanner(ask_samp_rate, num_demod, type_demod, hw_args, freq_correction, record, lockout_file_name, priority_file_name, channel_log_file_name, channel_log_timeout, - play, audio_bps) + play, audio_bps, max_demod_length) # Set the paramaters scanner.set_center_freq(PARSER.center_freq) - scanner.set_gain(PARSER.gain_db) - scanner.set_if_gain(PARSER.if_gain_db) - scanner.set_bb_gain(PARSER.bb_gain_db) + scanner.set_squelch(PARSER.squelch_db) scanner.set_volume(PARSER.volume_db) scanner.set_threshold(PARSER.threshold_db) + rxwin.gains = scanner.filter_and_set_gains(PARSER.gains) + # Get the initial settings for GUI rxwin.center_freq = scanner.center_freq rxwin.min_freq = scanner.min_freq rxwin.max_freq = scanner.max_freq rxwin.samp_rate = scanner.samp_rate - rxwin.gain_db = scanner.gain_db - rxwin.if_gain_db = scanner.if_gain_db - rxwin.bb_gain_db = scanner.bb_gain_db rxwin.squelch_db = scanner.squelch_db rxwin.volume_db = scanner.volume_db rxwin.record = scanner.record @@ -127,15 +125,8 @@ def main(screen): rxwin.max_freq = scanner.max_freq if rxwin.proc_keyb_soft(keyb): - # Set and update RF gain - scanner.set_gain(rxwin.gain_db) - rxwin.gain_db = scanner.gain_db - # Set and update IF gain - scanner.set_if_gain(rxwin.if_gain_db) - rxwin.if_gain_db = scanner.if_gain_db - # Set and update BB gain - scanner.set_bb_gain(rxwin.bb_gain_db) - rxwin.bb_gain_db = scanner.bb_gain_db + # Set all the gains + rxwin.gains = scanner.filter_and_set_gains(rxwin.gains) # Set and update squelch scanner.set_squelch(rxwin.squelch_db) rxwin.squelch_db = scanner.squelch_db diff --git a/apps/parser.py b/apps/parser.py index 4a41c02..466ad94 100755 --- a/apps/parser.py +++ b/apps/parser.py @@ -60,15 +60,21 @@ def __init__(self): default=4E6, help="Hardware ask sample rate in sps (1E6 minimum)") - parser.add_option("-g", "--gain", type="eng_float", dest="gain_db", + parser.add_option("-g", "--gain", type="eng_float", dest="rf_gain_db", default=0, help="Hardware RF gain in dB") parser.add_option("-i", "--if_gain", type="eng_float", dest="if_gain_db", - default=16, help="Hardware IF gain in dB") + default=16, help="Hardware IF gain in dB or index (driver dependent)") parser.add_option("-o", "--bb_gain", type="eng_float", dest="bb_gain_db", default=16, help="Hardware BB gain in dB") + parser.add_option("-j", "--lna_gain", type="eng_float", dest="lna_gain_db", + default=8, help="Hardware LNA gain index") + + parser.add_option("-x", "--mix_gain", type="eng_float", dest="mix_gain_db", + default=5, help="Hardware MIX gain index") + parser.add_option("-s", "--squelch", type="eng_float", dest="squelch_db", default=-60, help="Squelch in dB") @@ -124,7 +130,10 @@ def __init__(self): parser.add_option("-N", "--min_db", type="float", dest="min_db", default=-10, help="Spectrum window min dB for display (no greater than -10dB from max") - + + parser.add_option("-k", "--max-demod-length", type="int", dest="max_demod_length", + default=0, + help="Maxumum length for a demodulation (sec)") options = parser.parse_args()[0] self.parser_args = parser.parse_args()[1] @@ -134,9 +143,15 @@ def __init__(self): self.type_demod = int(options.type_demod) self.center_freq = float(options.center_freq) self.ask_samp_rate = float(options.ask_samp_rate) - self.gain_db = float(options.gain_db) - self.if_gain_db = float(options.if_gain_db) - self.bb_gain_db = float(options.bb_gain_db) + + self.gains = [ + { "name": "RF", "value": float(options.rf_gain_db), "query": "yes" }, + { "name": "LNA","value": float(options.lna_gain_db), "query": "no" }, + { "name": "MIX","value": float(options.mix_gain_db), "query": "no" }, + { "name": "IF", "value": float(options.if_gain_db), "query": "no" }, + { "name": "BB", "value": float(options.bb_gain_db), "query": "no" } + ] + self.squelch_db = float(options.squelch_db) self.volume_db = float(options.volume_db) self.threshold_db = float(options.threshold_db) @@ -150,6 +165,7 @@ def __init__(self): self.audio_bps = int(options.audio_bps) self.max_db = float(options.max_db) self.min_db = float(options.min_db) + self.max_demod_length = int(options.max_demod_length) def main(): @@ -166,9 +182,8 @@ def main(): print("type_demod: " + str(parser.type_demod)) print("center_freq: " + str(parser.center_freq)) print("ask_samp_rate: " + str(parser.ask_samp_rate)) - print("gain_db: " + str(parser.gain_db)) - print("if_gain_db: " + str(parser.if_gain_db)) - print("bb_gain_db: " + str(parser.bb_gain_db)) + for gain in parser.gains: + print("gain %s at %d dB" % (gain["name"], gain["value"])) print("squelch_db: " + str(parser.squelch_db)) print("volume_db: " + str(parser.volume_db)) print("threshold_db: " + str(parser.threshold_db)) diff --git a/apps/receiver.py b/apps/receiver.py index 295689e..ad031c0 100755 --- a/apps/receiver.py +++ b/apps/receiver.py @@ -407,8 +407,6 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, # Default values self.center_freq = 146E6 self.gain_db = 0 - self.if_gain_db = 16 - self.bb_gain_db = 16 self.squelch_db = -60 self.volume_db = 0 audio_rate = 8000 @@ -416,9 +414,6 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, # Setup the USRP source, or use the USRP sim self.src = osmosdr.source(args="numchan=" + str(1) + " " + hw_args) self.src.set_sample_rate(ask_samp_rate) - self.src.set_gain(self.gain_db) - self.src.set_if_gain(self.if_gain_db) - self.src.set_bb_gain(self.bb_gain_db) self.src.set_center_freq(self.center_freq) self.src.set_freq_corr(freq_correction) @@ -514,32 +509,34 @@ def set_center_freq(self, center_freq): # Do this to account for slight hardware offsets self.center_freq = self.src.get_center_freq() - def set_gain(self, gain_db): - """Sets gain of RF hardware - - Args: - gain_db (float): Hardware RF gain in dB + def get_gain_names(self): + """Get the list of suppoted gain elements """ - self.src.set_gain(gain_db) - self.gain_db = self.src.get_gain() - - def set_if_gain(self, if_gain_db): - """Sets IF gain of RF hardware + return self.src.get_gain_names() + def filter_and_set_gains(self, all_gains): + """Remove unsupported gains and set them Args: - if_gain_db (float): Hardware IF gain in dB + all_gains (list of dictionary): Supported gains in dB """ - self.src.set_if_gain(if_gain_db) - self.if_gain_db = if_gain_db - - def set_bb_gain(self, bb_gain_db): - """Sets BB gain of RF hardware - + gains = [] + names = self.get_gain_names() + for gain in all_gains: + if gain["name"] in names: + gains.append(gain) + return self.set_gains(gains) + + def set_gains(self, gains): + """Set all the gains Args: - bb_gain_db (float): Hardware BB gain in dB + gains (list of dictionary): Supported gains in dB """ - self.src.set_bb_gain(bb_gain_db) - self.bb_gain_db = bb_gain_db + for gain in gains: + self.src.set_gain(gain["value"], gain["name"]) + if gain["query"] == "yes": + gain["value"] = self.src.get_gain(gain["name"]) + self.gains = gains + return self.gains def set_squelch(self, squelch_db): """Sets squelch of all demodulators and clamps range @@ -600,11 +597,15 @@ def main(): # Set frequency, gain, squelch, and volume center_freq = 144.5E6 receiver.set_center_freq(center_freq) - receiver.set_gain(10) +# receiver.set_gain(10) print("\n") print("Started %s at %.3f Msps" % (hw_args, receiver.samp_rate/1E6)) - print("RX at %.3f MHz with %d dB gain" % (receiver.center_freq/1E6, - receiver.gain_db)) +# print("RX at %.3f MHz with %d dB gain" % (receiver.center_freq/1E6, +# receiver.gain_db)) + print("RX at %.3f MHz" % (receiver.center_freq/1E6)) + receiver.filter_and_set_gains(parser.gains) + for gain in receiver.gains: + print("gain %s at %d dB" % (gain["name"], gain["value"])) receiver.set_squelch(-60) receiver.set_volume(0) print("%d demods of type %d at %d dB squelch and %d dB volume" % \ diff --git a/apps/scanner.py b/apps/scanner.py index fce1d96..38bd20d 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -58,7 +58,12 @@ class Scanner(object): hw_args (string): Argument string to pass to harwdare freq_correction (int): Frequency correction in ppm record (bool): Record audio to file if True + lockout_file_name (string): Name of file with channels to lockout + priority_file_name (string): Name of file with channels for priority + channel_log_file_name (string): Name of file with channel log entries + channel_log_timeout (int): Timeout delay between active channel entries in log audio_bps (int): Audio bit depth in bps (bits/samples) + max_demod_length (int): Maximum demod time in seconds (0=disable) Attributes: center_freq (float): Hardware RF center frequency in Hz @@ -79,6 +84,7 @@ class Scanner(object): channel_log_file_name (string): Name of file with channel log entries channel_log_timeout (int): Timeout delay between active channel entries in log log_timeout_last (int): Last timestamp when recently active channels were logged and cleared + max_demod_length (int): Maximum demod time in seconds (0=disable) """ # pylint: disable=too-many-instance-attributes # pylint: disable=too-many-arguments @@ -88,12 +94,13 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, lockout_file_name="", priority_file_name="", channel_log_file_name="", channel_log_timeout=15, play=True, - audio_bps=8): + audio_bps=8, max_demod_length=0): # Default values - self.gain_db = 0 - self.if_gain_db = 16 - self.bb_gain_db = 16 +# self.gains +# self.gain_db = 0 +# self.if_gain_db = 16 +# self.bb_gain_db = 16 self.squelch_db = -60 self.volume_db = 0 self.threshold_db = 10 @@ -114,6 +121,7 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.log_recent_channels = [] self.log_timeout_last = int(time.time()) self.log_mode = "" + self.max_demod_length = max_demod_length # Create receiver object self.receiver = recvr.Receiver(ask_samp_rate, num_demod, type_demod, @@ -169,7 +177,8 @@ def __print_channel_log_active__(self, freq, state): now.strftime("%Y-%m-%d, %H:%M:%S.%f"), state_str[state], freq, - self.gain_db, + 0, + #self.gain_db, self.threshold_db, self.channel_log_timeout)) elif self.log_mode == "db": @@ -191,7 +200,8 @@ def __print_channel_log__(self, freq, state, idx): now.strftime("%Y-%m-%d, %H:%M:%S.%f"), state_str[state], freq, - self.gain_db, + 0, + #self.gain_db, self.threshold_db, idx)) elif self.log_mode == "db": @@ -290,11 +300,24 @@ def scan_cycle(self): # Assigning channel to empty demodulator demodulator.set_center_freq(channel, self.center_freq) break + else: pass else: pass + # Stop any long running demodulators + if self.max_demod_length > 0: + for demodulator in self.receiver.demodulators: + if (demodulator.time_stamp > 0) and \ + (int(time.time()) - demodulator.time_stamp > \ + self.max_demod_length): + temp_freq = demodulator.center_freq + # clear the demodulator to reset file + demodulator.set_center_freq(0, self.center_freq) + # reset the demodulator to its frequency to restart file + demodulator.set_center_freq(0, temp_freq) + # Create an tuned channel list of strings for the GUI # If channel is a zero then use an empty string self.gui_tuned_channels = [] @@ -441,32 +464,14 @@ def set_center_freq(self, center_freq): # Clear the lockout since frequency is changing self.clear_lockout() - def set_gain(self, gain_db): - """Sets gain of RF hardware - - Args: - gain_db (float): Hardware RF gain in dB - """ - self.receiver.set_gain(gain_db) - self.gain_db = self.receiver.gain_db - - def set_if_gain(self, if_gain_db): - """Sets IF gain of RF hardware - - Args: - if_gain_db (float): Hardware IF gain in dB - """ - self.receiver.set_if_gain(if_gain_db) - self.if_gain_db = self.receiver.if_gain_db - - def set_bb_gain(self, bb_gain_db): - """Sets BB gain of RF hardware + def filter_and_set_gains(self, all_gains): + """Set the supported gains and return them Args: - bb_gain_db (float): Hardware BB gain in dB + all_gains (list of dictionary): Supported gains in dB """ - self.receiver.set_bb_gain(bb_gain_db) - self.bb_gain_db = self.receiver.bb_gain_db + self.gains = self.receiver.filter_and_set_gains(all_gains) + return self.gains def set_squelch(self, squelch_db): """Sets squelch of all demodulators @@ -536,13 +541,15 @@ def main(): # Set frequency, gain, squelch, and volume scanner.set_center_freq(parser.center_freq) - scanner.set_gain(parser.gain_db) - scanner.set_if_gain(parser.if_gain_db) - scanner.set_bb_gain(parser.bb_gain_db) print("\n") print("Started %s at %.3f Msps" % (hw_args, scanner.samp_rate/1E6)) - print("RX at %.3f MHz with %d dB gain" % (scanner.center_freq/1E6, - scanner.gain_db)) + print("RX at %.3f MHz with %d dB gain" % (scanner.center_freq/1E6)) + scanner.filter_and_set_gains(parser.gains) + for gain in scanner.gains: + print("gain %s at %d dB" % (gain["name"], gain["value"])) + #scanner.set_gain(parser.gain_db) + #scanner.set_if_gain(parser.if_gain_db) + #scanner.set_bb_gain(parser.bb_gain_db) scanner.set_squelch(parser.squelch_db) scanner.set_volume(parser.volume_db) print("%d demods of type %d at %d dB squelch and %d dB volume" % \ From 34b1232dd7dcc8e1f4e66758afe42546ad5a0209 Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Tue, 5 Jan 2021 12:55:55 -0800 Subject: [PATCH 19/41] Corrected missing timestamp initialization in demod constructor modified: receiver.py --- apps/receiver.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/receiver.py b/apps/receiver.py index ad031c0..75bbc32 100755 --- a/apps/receiver.py +++ b/apps/receiver.py @@ -53,10 +53,11 @@ def set_center_freq(self, center_freq, rf_center_freq): file_name = "/dev/null" else: # Otherwise use frequency and time stamp for file name - tstamp = "_" + str(int(time.time())) + timestamp = int(time.time()) + strtimestamp = "_" + str(timestamp) file_freq = (rf_center_freq + self.center_freq)/1E6 file_freq = np.round(file_freq, 3) - file_name = 'wav/' + '{:.3f}'.format(file_freq) + tstamp + ".wav" + file_name = 'wav/' + '{:.3f}'.format(file_freq) + strtimestamp + ".wav" # Make sure the 'wav' directory exists try: @@ -66,6 +67,7 @@ def set_center_freq(self, center_freq, rf_center_freq): self.file_name = file_name self.blocks_wavfile_sink.open(self.file_name) + self.time_stamp = timestamp def _delete_wavfile_if_empty(self): """Delete the current wavfile if it's empty.""" @@ -140,6 +142,7 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, # Default values self.center_freq = 0 + self.time_stamp = 0 squelch_db = -60 self.quad_demod_gain = 0.050 self.file_name = "/dev/null" @@ -277,6 +280,7 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, # Default values self.center_freq = 0 + self.time_stamp = 0 squelch_db = -60 self.agc_ref = 0.1 self.file_name = "/dev/null" From b31b005ab3aaa87655c73b0f69277f5a84df657b Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Tue, 5 Jan 2021 12:59:05 -0800 Subject: [PATCH 20/41] Fixed possibility of reference timestamp before init modified: receiver.py --- apps/receiver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/receiver.py b/apps/receiver.py index 75bbc32..93e7bd5 100755 --- a/apps/receiver.py +++ b/apps/receiver.py @@ -48,12 +48,12 @@ def set_center_freq(self, center_freq, rf_center_freq): self.center_freq = center_freq # Set the file name + timestamp = int(time.time()) if self.center_freq == 0 or not self.record: # If tuner at zero Hz, or record false, then file name to /dev/null file_name = "/dev/null" else: # Otherwise use frequency and time stamp for file name - timestamp = int(time.time()) strtimestamp = "_" + str(timestamp) file_freq = (rf_center_freq + self.center_freq)/1E6 file_freq = np.round(file_freq, 3) From b08207db9c49678f92cc1e7fd529c76a2dea3c81 Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Fri, 8 Jan 2021 01:45:35 -0800 Subject: [PATCH 21/41] Added command line switches for channel spacing with default 5000, and min file size with default 0, so setting min file size to 10000 will delete any demodulator output wav files that are less than 10k bytes in size when the demodulator is stopped. This may not take effect when ctrl-c is used to stop the program but should when "Q" is pressed since all demodulators are stopped in that case before shutdown. Changes to be committed: modified: ham2mon.py modified: parser.py modified: receiver.py modified: scanner.py --- apps/ham2mon.py | 4 +++- apps/parser.py | 14 ++++++++++++++ apps/receiver.py | 25 +++++++++++++++++-------- apps/scanner.py | 15 +++++++++++---- 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/apps/ham2mon.py b/apps/ham2mon.py index 5225681..c9fe207 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -58,10 +58,12 @@ def main(screen): freq_correction = PARSER.freq_correction audio_bps = PARSER.audio_bps max_demod_length = PARSER.max_demod_length + channel_spacing = PARSER.channel_spacing + min_file_size = PARSER.min_file_size scanner = scnr.Scanner(ask_samp_rate, num_demod, type_demod, hw_args, freq_correction, record, lockout_file_name, priority_file_name, channel_log_file_name, channel_log_timeout, - play, audio_bps, max_demod_length) + play, audio_bps, max_demod_length, channel_spacing, min_file_size) # Set the paramaters scanner.set_center_freq(PARSER.center_freq) diff --git a/apps/parser.py b/apps/parser.py index 466ad94..9f3840f 100755 --- a/apps/parser.py +++ b/apps/parser.py @@ -31,6 +31,8 @@ class CLParser(object): audio_bps (int): Audio bit depth in bps max_db (float): Spectrum max dB for display min_db (float): Spectrum min dB for display + channel_spacing (int): Channel spacing (spectrum bin size) for identification of channels + min_file_size (int): Minimum file size to save """ # pylint: disable=too-few-public-methods # pylint: disable=too-many-instance-attributes @@ -135,6 +137,14 @@ def __init__(self): default=0, help="Maxumum length for a demodulation (sec)") + parser.add_option("-B", "--channel-spacing", type="int", dest="channel_spacing", + default=5000, + help="Channel spacing (spectrum bin size)") + + parser.add_option("-F", "--min-file-size", type="int", dest="min_file_size", + default=5000, + help="Minimum size file to save when ") + options = parser.parse_args()[0] self.parser_args = parser.parse_args()[1] @@ -166,6 +176,8 @@ def __init__(self): self.max_db = float(options.max_db) self.min_db = float(options.min_db) self.max_demod_length = int(options.max_demod_length) + self.channel_spacing = int(options.channel_spacing) + self.min_file_size = int(options.min_file_size) def main(): @@ -196,6 +208,8 @@ def main(): print("audio_bps: " + str(parser.audio_bps)) print("max_db: " + str(parser.max_db)) print("min_db: " + str(parser.min_db)) + print("max_demod_length: " + str(parser.max_demod_length)) + print("channel_spacing: " + str(parser.channel_spacing)) if __name__ == '__main__': diff --git a/apps/receiver.py b/apps/receiver.py index 93e7bd5..c9feab1 100755 --- a/apps/receiver.py +++ b/apps/receiver.py @@ -75,9 +75,9 @@ def _delete_wavfile_if_empty(self): self.file_name == '/dev/null'): return - # If we never wrote any data to the wavfile sink, delete - # the (empty) wavfile - if os.stat(self.file_name).st_size in (44, 0): # ugly hack + # If we never wrote any data to the wavfile sink, or its smaller than + # the minimum defined size, then delete the (empty) wavfile + if os.stat(self.file_name).st_size < (self.min_file_size): os.unlink(self.file_name) # delete the file def set_squelch(self, squelch_db): @@ -127,15 +127,17 @@ class TunerDemodNBFM(BaseTuner): audio_rate (float): Output audio sample rate in sps (8 kHz minimum) record (bool): Record audio to file if True audio_bps (int): Audio bit depth in bps (bits/samples) + min_file_size (int): Minimum saved wav file size Attributes: center_freq (float): Baseband center frequency in Hz record (bool): Record audio to file if True + time_stamp (int): Time stamp of demodulator start for timing run length """ # pylint: disable=too-many-instance-attributes def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, - audio_bps=8): + audio_bps=8, min_file_size=0): gr.hier_block2.__init__(self, "TunerDemodNBFM", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_float)) @@ -147,6 +149,7 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, self.quad_demod_gain = 0.050 self.file_name = "/dev/null" self.record = record + self.min_file_size = min_file_size # Decimation values for four stages of decimation decims = (5, int(samp_rate/1E6)) @@ -264,10 +267,12 @@ class TunerDemodAM(BaseTuner): audio_rate (float): Output audio sample rate in sps (8 kHz minimum) record (bool): Record audio to file if True audio_bps (int): Audio bit depth in bps (bits/samples) + min_file_size (int): Minimum saved wav file size Attributes: center_freq (float): Baseband center frequency in Hz record (bool): Record audio to file if True + time_stamp (int): Time stamp of demodulator start for timing run length """ # pylint: disable=too-many-instance-attributes # pylint: disable=too-many-locals @@ -285,6 +290,8 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, self.agc_ref = 0.1 self.file_name = "/dev/null" self.record = record + self.min_file_size = min_file_size + # Decimation values for four stages of decimation decims = (5, int(samp_rate/1E6)) @@ -403,7 +410,7 @@ class Receiver(gr.top_block): def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, hw_args="uhd", freq_correction=0, record=True, play=True, - audio_bps=8): + audio_bps=8, min_file_size=0): # Call the initialization method from the parent class gr.top_block.__init__(self, "Receiver") @@ -414,6 +421,7 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.squelch_db = -60 self.volume_db = 0 audio_rate = 8000 + self.min_file_size = min_file_size # Setup the USRP source, or use the USRP sim self.src = osmosdr.source(args="numchan=" + str(1) + " " + hw_args) @@ -476,11 +484,11 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, if type_demod == 1: self.demodulators.append(TunerDemodAM(self.samp_rate, audio_rate, record, - audio_bps)) + audio_bps, self.min_file_size)) else: self.demodulators.append(TunerDemodNBFM(self.samp_rate, audio_rate, record, - audio_bps)) + audio_bps, self.min_file_size)) if play: # Create an adder @@ -591,8 +599,9 @@ def main(): record = False play = True audio_bps = 8 + min_file_size = 0 receiver = Receiver(ask_samp_rate, num_demod, type_demod, hw_args, - freq_correction, record, play, audio_bps) + freq_correction, record, play, audio_bps, min_file_size) # Start the receiver and wait for samples to accumulate receiver.start() diff --git a/apps/scanner.py b/apps/scanner.py index 38bd20d..3dd96a0 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -94,7 +94,8 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, lockout_file_name="", priority_file_name="", channel_log_file_name="", channel_log_timeout=15, play=True, - audio_bps=8, max_demod_length=0): + audio_bps=8, max_demod_length=0, channel_spacing=5000, + min_file_size=0): # Default values # self.gains @@ -113,7 +114,7 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.gui_tuned_channels = [] self.gui_active_channels = [] self.gui_lockout_channels = [] - self.channel_spacing = 5000 + self.channel_spacing = channel_spacing self.lockout_file_name = lockout_file_name self.priority_file_name = priority_file_name self.channel_log_file_name = channel_log_file_name @@ -122,11 +123,13 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.log_timeout_last = int(time.time()) self.log_mode = "" self.max_demod_length = max_demod_length + self.min_file_size = min_file_size # Create receiver object self.receiver = recvr.Receiver(ask_samp_rate, num_demod, type_demod, hw_args, freq_correction, record, play, - audio_bps) + audio_bps, + min_file_size) # Open channel log file for appending data, if it is specified if channel_log_file_name != "": @@ -534,10 +537,14 @@ def main(): priority_file_name = parser.priority_file_name channel_log_file_name = parser.channel_log_file_name audio_bps = parser.audio_bps + max_demo_length = parser.max_demod_length + channel_spacing = parser.channel_spacing + min_file_size = parser.min_file_size scanner = Scanner(ask_samp_rate, num_demod, type_demod, hw_args, freq_correction, record, lockout_file_name, priority_file_name, channel_log_file_name, - audio_bps) + audio_bps, max_demod_length, channel_spacing, + min_file_size) # Set frequency, gain, squelch, and volume scanner.set_center_freq(parser.center_freq) From 0295f450bffd10b933145b0518388b4214e7660e Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Fri, 8 Jan 2021 01:56:27 -0800 Subject: [PATCH 22/41] Fixed "Q" terminate cleans up demodulators (set all to baseband) Changes to be committed: modified: ham2mon.py --- apps/ham2mon.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/ham2mon.py b/apps/ham2mon.py index c9fe207..685feec 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -144,6 +144,10 @@ def main(screen): if lockoutwin.proc_keyb_clear_lockout(keyb): scanner.clear_lockout() + # cleanup terminating all demodulators + for demod in scanner.receiver.demodulators: + demod.set_center_freq(0, 0); + if __name__ == '__main__': try: # Do this since curses wrapper won't let parser write to screen From 9f95629eaad18b21fa41c024e79b8f1697dbd955 Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Fri, 8 Jan 2021 02:12:14 -0800 Subject: [PATCH 23/41] README fixes for latest features and command line flags, parser correction to display help Changes to be committed: modified: README.md modified: apps/parser.py --- README.md | 25 ++++++++++++++++++++++++- apps/parser.py | 4 ++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 32d23a6..a6716e7 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,16 @@ Additional screenshots show updated screen color and channel highlighting with ![GUI screenshot](https://github.com/lordmorgul/ham2mon/blob/master/ham2mon_priority_channels_active.png) ![GUI screenshot](https://github.com/lordmorgul/ham2mon/blob/master/ham2mon_priority_channels_overmax.png) + ## Tested with: +Recent development and tests: +- RTL-SDR v3 RTL2832 + R820T at 2 Msps (http://rtl-sdr.com) +- NooElec RTL2832 + R820T at 2 Msps (http://www.nooelec.com) +- GNU Radio 3.8.2.0 (https://github.com/gnuradio/gnuradio) +- GrOsmoSDR 0.1.4-29 (http://sdr.osmocom.org/trac/wiki/GrOsmoSDR) +- Python 3.8.6 + +Previous version tests: - Ettus B200 at 16 Msps (http://www.ettus.com) - NooElec RTL2832 + R820T at 2 Msps (http://www.nooelec.com) - GNU Radio 3.7.10 (https://github.com/gnuradio/gnuradio) @@ -30,9 +39,13 @@ lordmorgul: - pulled logger framework from kibihrchak and revised to python3 - log file framework with enable flags (to prepare for multiple loggers implemented, text and database) - log file timeout so active channels are indicated only every TIMEOUT seconds +- pulled long run demodulator fix to python3 version from john +- pulled gain corrections to python3 version from john +- defined max file size to save from command line option +- channel width configurable from command line option john: -- long running file end (pending pull into lordmorgul repo) +- long running file end (demodulator run time limit) kibihrchak: - Logger branch text file log entries @@ -65,6 +78,8 @@ madengr: ## Console Operation: +Options are displayed using ./parser.py -h + The following is an example of the option switches for UHD with NBFM demodulation, although omission of any will use default values (shown below) that are optimal for the B200: ./ham2mon.py -a "uhd" -n 8 -d 0 -f 146E6 -r 4E6 -g 30 -s -60 -v 0 -t 10 -w @@ -91,6 +106,8 @@ For console operation, it is possible to specify the log file name, in which cha Whenever a channel appears/dissapears, new line will be written in the log file. For the line format, check `__print_channel_log__()` in `scanner.Scanner`. +Active channels are flagged as active periodically based on the active channel logging timeout. + ## GUI Controls: `t/r = Detection threshold +/- 5 dB. (T/R for +/- 1dB)` @@ -193,6 +210,12 @@ Whenever a channel appears/dissapears, new line will be written in the log file. ` -N MIN_DB, --min_db=MIN_DB` ` Spectrum window minimum in dB` +` -k MAX_DEMOD_LENGTH, --max-demod-length=MAX_DEMOD_LENGTH` +` Maxumum length for a demodulation (sec)` +` -B CHANNEL_SPACING, --channel-spacing=CHANNEL_SPACING` +` Channel spacing (spectrum bin size)` +` -F MIN_FILE_SIZE, --min-file-size=MIN_FILE_SIZE` +` Minimum size file to save in bytes, default 0 (save all)` ## Description: diff --git a/apps/parser.py b/apps/parser.py index 9f3840f..b4612d7 100755 --- a/apps/parser.py +++ b/apps/parser.py @@ -142,8 +142,8 @@ def __init__(self): help="Channel spacing (spectrum bin size)") parser.add_option("-F", "--min-file-size", type="int", dest="min_file_size", - default=5000, - help="Minimum size file to save when ") + default=0, + help="Minimum size file to save in bytes, default 0 (save all)") options = parser.parse_args()[0] self.parser_args = parser.parse_args()[1] From 38d3c16bf8533f3c66757b61fecab720a2ff6d9a Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 23 Jan 2021 01:23:09 -0800 Subject: [PATCH 24/41] feature addition cleanups, removal extraneous comments and commented old code, corrected missing parameter descriptions and test script outputs. On branch Gain-changes-and-long-xmit-kill Changes to be committed: modified: README.md modified: apps/cursesgui.py modified: apps/ham2mon.py modified: apps/parser.py modified: apps/receiver.py modified: apps/scanner.py --- README.md | 5 +++-- apps/cursesgui.py | 17 +++++++++++++---- apps/ham2mon.py | 4 ++++ apps/parser.py | 4 +++- apps/receiver.py | 3 --- apps/scanner.py | 21 +++++++-------------- 6 files changed, 30 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index a6716e7..8d41a9b 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Additional screenshots show updated screen color and channel highlighting with ## Tested with: -Recent development and tests: +Recent development and tests on Python3: - RTL-SDR v3 RTL2832 + R820T at 2 Msps (http://rtl-sdr.com) - NooElec RTL2832 + R820T at 2 Msps (http://www.nooelec.com) - GNU Radio 3.8.2.0 (https://github.com/gnuradio/gnuradio) @@ -44,8 +44,9 @@ lordmorgul: - defined max file size to save from command line option - channel width configurable from command line option -john: +john-: - long running file end (demodulator run time limit) +- gain config corrections, available gains detected from gnuradio and other inputs ignored / not shown kibihrchak: - Logger branch text file log entries diff --git a/apps/cursesgui.py b/apps/cursesgui.py index d177929..26dfa0b 100755 --- a/apps/cursesgui.py +++ b/apps/cursesgui.py @@ -351,9 +351,13 @@ class RxWindow(object): gains (list): Hardware gains in dB squelch_db (int): Squelch in dB volume_dB (int): Volume in dB + type_demod (int): Type of demodulation (0 = FM, 1 = AM) record (bool): Record audio to file if True lockout_file_name (string): Name of file with channels to lockout priority_file_name (string): Name of file with channels for priority + channel_log_file_name (string): Name of file for channel activity logging + channel_log_timeout (int): Timeout delay between logging active state of channel in seconds + log_mode (string): Log system mode (file, database type) """ # pylint: disable=too-many-instance-attributes @@ -374,6 +378,11 @@ def __init__(self, screen): self.priority_file_name = "" self.channel_log_file_name = "" self.channel_log_timeout = 15 + # nothing other than file logging defined + if (self.channel_log_file_name != ""): + self.log_mode = "file" + else: + self.log_mode = "none" # Create a window object in the bottom half of the screen # Make it about 1/3 the screen width @@ -428,8 +437,8 @@ def draw_rx(self): self.win.addnstr(index+10, 1, text, 18, curses.color_pair(6)) text = "Log Timeout (s): " self.win.addnstr(index+11, 1, text, 18, curses.color_pair(6)) -# text = "Log Mode : " -# self.win.addnstr(index+12, 1, text, 18, curses.color_pair(6)) + text = "Log Mode : " + self.win.addnstr(index+12, 1, text, 18, curses.color_pair(6)) # Draw the receiver info suffix fields if self.freq_entry != 'None': @@ -464,8 +473,8 @@ def draw_rx(self): self.win.addnstr(index+10, 20, text, 20, curses.color_pair(6)) text = str(self.channel_log_timeout) self.win.addnstr(index+11, 20, text, 20, curses.color_pair(6)) -# text = str(self.log_mode) -# self.win.addnstr(index+12, 20, text, 20, curses.color_pair(6)) + text = str(self.log_mode) + self.win.addnstr(index+12, 20, text, 20, curses.color_pair(6)) # Hide cursor self.win.leaveok(1) diff --git a/apps/ham2mon.py b/apps/ham2mon.py index 685feec..83314bb 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -87,6 +87,10 @@ def main(screen): rxwin.priority_file_name = scanner.priority_file_name rxwin.channel_log_file_name = scanner.channel_log_file_name rxwin.channel_log_timeout = scanner.channel_log_timeout + if (rxwin.channel_log_file_name != ""): + rxwin.log_mode = "file" + else: + rxwin.log_mode = "none" specwin.max_db = PARSER.max_db specwin.min_db = PARSER.min_db diff --git a/apps/parser.py b/apps/parser.py index b4612d7..0e9e427 100755 --- a/apps/parser.py +++ b/apps/parser.py @@ -17,7 +17,7 @@ class CLParser(object): num_demod (int): Number of parallel demodulators center_freq (float): Hardware RF center frequency in Hz ask_samp_rate (float): Asking sample rate of hardware in sps (1E6 min) - gain_db (int): Hardware RF gain in dB + gains : Enumerated gain types and values squelch_db (int): Squelch in dB volume_dB (int): Volume in dB threshold_dB (int): Threshold for channel detection in dB @@ -31,6 +31,7 @@ class CLParser(object): audio_bps (int): Audio bit depth in bps max_db (float): Spectrum max dB for display min_db (float): Spectrum min dB for display + max_demod_length (int): Timeout for long running demodulators to reset new file timestamp in seconds channel_spacing (int): Channel spacing (spectrum bin size) for identification of channels min_file_size (int): Minimum file size to save """ @@ -210,6 +211,7 @@ def main(): print("min_db: " + str(parser.min_db)) print("max_demod_length: " + str(parser.max_demod_length)) print("channel_spacing: " + str(parser.channel_spacing)) + print("min_file_size: " + str(parser.min_file_size)) if __name__ == '__main__': diff --git a/apps/receiver.py b/apps/receiver.py index c9feab1..c205822 100755 --- a/apps/receiver.py +++ b/apps/receiver.py @@ -610,11 +610,8 @@ def main(): # Set frequency, gain, squelch, and volume center_freq = 144.5E6 receiver.set_center_freq(center_freq) -# receiver.set_gain(10) print("\n") print("Started %s at %.3f Msps" % (hw_args, receiver.samp_rate/1E6)) -# print("RX at %.3f MHz with %d dB gain" % (receiver.center_freq/1E6, -# receiver.gain_db)) print("RX at %.3f MHz" % (receiver.center_freq/1E6)) receiver.filter_and_set_gains(parser.gains) for gain in receiver.gains: diff --git a/apps/scanner.py b/apps/scanner.py index 3dd96a0..121a07b 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -68,7 +68,7 @@ class Scanner(object): Attributes: center_freq (float): Hardware RF center frequency in Hz samp_rate (float): Hardware sample rate in sps (1E6 min) - gain_db (int): Hardware RF gain in dB + gains : Enumerated gain types and values squelch_db (int): Squelch in dB volume_dB (int): Volume in dB threshold_dB (int): Threshold for channel detection in dB @@ -98,10 +98,6 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, min_file_size=0): # Default values -# self.gains -# self.gain_db = 0 -# self.if_gain_db = 16 -# self.bb_gain_db = 16 self.squelch_db = -60 self.volume_db = 0 self.threshold_db = 10 @@ -150,12 +146,6 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.min_freq = (self.center_freq - self.samp_rate/2) self.max_freq = (self.center_freq + self.samp_rate/2) - # Start the receiver and wait for samples to accumulate - self.receiver.start() - time.sleep(1) - - if self.channel_log_file != None : - self.channel_log_file.flush() # # removed this since its essentially the same as above and this required spectrum first # self.spectrum = self.receiver.probe_signal_vf.level() @@ -165,6 +155,12 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, # self.max_freq = ((len(self.spectrum) - len(self.spectrum)/2) * (self.samp_rate / len(self.spectrum) \ # + self.center_freq)) + # Start the receiver and wait for samples to accumulate + self.receiver.start() + time.sleep(1) + + if self.channel_log_file != None : + self.channel_log_file.flush() def __del__(self): if self.channel_log_file != None : @@ -554,9 +550,6 @@ def main(): scanner.filter_and_set_gains(parser.gains) for gain in scanner.gains: print("gain %s at %d dB" % (gain["name"], gain["value"])) - #scanner.set_gain(parser.gain_db) - #scanner.set_if_gain(parser.if_gain_db) - #scanner.set_bb_gain(parser.bb_gain_db) scanner.set_squelch(parser.squelch_db) scanner.set_volume(parser.volume_db) print("%d demods of type %d at %d dB squelch and %d dB volume" % \ From 883a329e515238e07a28220dbb48ccd62d1bc987 Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 12 Mar 2022 15:14:14 -0600 Subject: [PATCH 25/41] adding png graphic showing example of processor usage on 8 core laptop new file: ham2mon_processor_usage_2.png --- ham2mon_processor_usage_2.png | Bin 0 -> 168045 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ham2mon_processor_usage_2.png diff --git a/ham2mon_processor_usage_2.png b/ham2mon_processor_usage_2.png new file mode 100644 index 0000000000000000000000000000000000000000..a81621c730983300eac7eba2d47c936472740775 GIT binary patch literal 168045 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�$UvYiz{#DOm$yvC;0g~QW6lzw z&-Ajy$#cnbUiFalIFtv;Nk-8w_e%|eyAP_JSEQvW&A}%QWgSWCrI@F+{@*dlt<^qV zsHZv=B)viO*=c4Vf5ehOwt&>h>Z;B8GhZGCbQC8AeE3Hx$+gDs-DY4s-%VBQVsW~z zH|F_ybjU1DWYmq&k#dx_%C?2jJGQb0b7qeD{6fK{Bt|4m19YrLAi1kS;0CJIQD;{M za;Tui^dU$G&d}cmSxmGNzKwmplLG#;B@Z?>~v3a%zX9dmH`(7@Gr8cRz>=b!bqp@dt%c=(8Eo?Qeo#lIwGT z&5oA7AZ~dCN1m+g?`@{o6B&`BT7RkBP=SI7_~7W|ic4oz@TPSpG%nJ9TqG`(l53@w z3HD_EcQX0U@eNA;>gKdr8@j-CN1h)l_XTZz|5M4F(vx_+?{mvrI4L zFXr@Mby(?L>q&^oIl0z*0|^uW1|SfegzS)YM(Al>#Kj&O@LE`1T|GHy5PS(nHCPjP zQh&ub{p+d#H_pFU#Gw{O46NiK*-nbk$$MnIIWIGi__afua#vXZP2`U_{+jfHCN8zW zz+*+V_0hL1w>6C}KTrEjDKlG77poi!Y02e+16Rf!Yo0elXhZFcxdqy%SX?gV#tkFX z^Q!Xf^ZQ1P#d#@`HP1{az$+UlNo(=jOZI-^vFP8l^49|`oGvAYd7>xvDgSk8T*ZS` z0Wfk1^BmA~z(9l#5eSEF!DW3Wkd>bR84zCM%HIfuafu&TP$w}eKn4!{HYt%>Hz9cp zEonfb2K+g;&&3plCXNoiT8PC1)g1+inSmJ}sI?E9NEij&VDJT2%enb9L*fPyQeG4d zBe-f{1HkhzTSfm0LnT-t3(f<6b~82rLX$kOdiDZ{6Aq2INdkw&a58ItB>X|Qtaxhf zJ8ksi39Cdz;I8FRy*D?Dx9xT=Ha6(1lZz|wcwJ+SNnB0lTA`~k_4`jgn8I3iG%GtT zSeL;lrG-v$HllI6fB`Fho(wiK+Mg;%F3cuW73#nQfV4-$4FZ;v!BQJ$Y{?0dJ}{I; zM@Oe+Wu?I11WZ@`1YZT63;5kZ)hOSrCxe9@VDVqyh1>29qgy579q+L*Zvrz;2RyOa zAOhOol*6X!6J06faNR^8z&R)1s0tFDWgAd}e)T@AmN?Dc_)#Bb#l zEm*Oo2?FS5Nk|S8*0MNY`0XfLLPPhUvdFpqENS%x2Yu;#hNN#i z`P%ob%A!mE`FGBi@0>Q=tO9R=0dXO}Ld<4|cSXl-TT9I-tzziWZT5uuzJu!dbIQVeYh3C%sYe5>!y3uxd0vyAfAmVXE8zL2El8Ts5wBGB2r zbyvLnWm4)sMM@rjk;YJFjy^q>S0Trdk*(4_vbe^5o^5*VKeN^g@u*~LG(pQcIzsHy zKHDOK56FAeY(4v`iR_}~72^aAI$nXMS+fq4Tk%-;W}!04>~dIBao(jE`7e9t zrDo_|*c{ut?W#(Cw(M^GkEe-3RipLwM~6KV@4Q>Gn}Q7v4P5UGXR!-WKcB?wtW4#I z5}ob7_#gI)GmO3f`?_HA*2#KH!saXSoW+zf2QutR>$wFC(*w!9ywD`G)NDG^SN@n~ z@}TQq_{d>iOnxDP?bapNT%Rkqf|szxIE>=m)2zuZSeV&89#p?7_fNiX`h(+_Q~xB8 zM|)Up8~Ok<>|fPz{lBZ>UH?$Sh3uIjrmwkZ(37Jr2u%ne*38Jc9TC7D3Rt$RlM-TL-@#4x zT%9d&FE1|-V0AO`PHVa#u%N)(TOxp17_JS-BI$sO7b0R%!`=X{yqb8f)hF3^2%xDO zcB-#lF|SwbQ-WL3BWaj6~l`)dUlw&<)tcQLrMdVl;;T^Fq?JBO1v z!%y7p;L*2lGYc;Dq;+wQTQW3paiP$(EHXdt8eHpP89XWb!2%gRaP=aPkstb3;OQ|1 zV><%a0}#kj#5Q;xX1~UmO~E&fv>d?Wf&=8*&xKBxYSiKW_*X|b;TB3d!;-e$(5Qt0 zkJStYyo}eo?p~Z^4i;%c|8JYbwG3q|5 z#Y+NDN~A{r0&45ibR}<6g*Ps4AFkK+ez@wMwqK;2715jhrd^{IxC`-}vHOKKl7Z$Jl;=E}nYEH6~_n6o>-ns!vZw>U1j|lfjd5j%w zF>A>=6O<$$6Zo@Ih)1lX42UtOo`rR{)4Zqi*Y_C|^>oo}Ka6w4tscEYYx5zla-UN- z>k-bHM&DYGLXpZfjoaK~TQ7|BvWY!(o!k%(9?T4|n!SXz0x%3p*8^R%(nWecN*u(Y zo*XQ2lZ`DH%97r};waB)-;5fU9!U?t35I}c^jG;CE2{@!4Qg%nVP+#m)~s!9ZOB-G zEN8(ntpB4k+`o1bkT3Z77ru#ynt4hj=LT|I=mhiM__`rv@*r2A9~wx?^&XwdIpm&R z{Zo*h;JxC(%P<=HR4=Kp@CJZmfX`AgA1``c97#UI9abvlW8bnpDDKSa4xbSpH{Q1= zeih2HBBki+#@8BW5Bjbw2%IorT!^2!uK%R%fRofzuOalT+i~Nt^Ey?E>sfN~j~`Ft z1%qJ%JDj3UYV+=XDXOLJpDOwAeKaYq&@*}A?cOr^$jIr|AWGT6XN}RUS=~lKk! zarRi3(TaG@_-kjGhB9>xa(A@TNFZaQgP4YC(Acl>ou6z2xa1uuU-cCjc+0!EvXS<4 zquD@x-wNoJR7s-JHxU$2p?+DX5i6AAr+oc66gx+34Wm?f?%hMYv6 z`CT{ZV%5BU-O*es`QhP_@^jg5?{?p(l&?6&Y&<}F?8Eth3}2dbN(@&|y|f?8I&3%m zM&;0l?t9Z;30Cp5*CKmDE3wk!RX#h59>n>y=SMZ%_I~}%cY0-NpeCiNtVSnTdEcC% zWiaBE^OxW}`9cATDx6kHE=-qvfeFrd9IB}?dCeCz4r0tn-5s4i7rEoob`q&p#1gls zwlQ=K`lyy_hG-&rF%s+NXXl@jV!v8=lX@xTrxVi$Rxx4~x-y0^QGA&gaZ-;>eD)$3 zv%iCh7fDUX!rzXxbQKkp?}Dr4ZS@ms78Vx!Y74l6VCaBG=vF|iK=n{kdODNI!?!e| z-a5IecVpV_F;iuiO99Ijp|t>4qc>gg53NOV?>j0)d@M>dz*R#42Mz#szUc1KXWs-d z0=dAUiUvY_kE1!6>^}>Fbqo5Lw!pjqd!t8YW@berG*|A^!RbQ>Oz^cMz4Cf` zw6H|fOp-Kg=7^*ZvGgYtMtfp@KN=HfkMz>J0kT1wPj^wp@Q%~S@YL1id;2a-sH9u$ z;jEC_?>ajB`TgXeyVCF|cg*>k@6ENbicNiewAfH{Ts}(2Y|X&T*=F)efAkz#$rg%3 zxC)(3xC%D~MJyhM4rn_*l9b#H_+UtAah(yT#ABjBi-B5kk+_J)zZ}&7d->dFf&^!=eQ4)4Ql8dz$4>&< z#d&)zqH`9Y49iz0L72)`=&B&Re~^ApmgHtcb%Lj>BMIj}>rvX!0=c zH&Ud^1ikI>z<>|(Qh54lh6p19Z~^}q(qL^?6w@Ji9t);BXr4|>OQXJZ%gfvQGNj;| zHSI$q%6$q|AtXekCx~6fV zbhOMU-tm6@FPV@iGO4jjER-&@hVOd3AF0M=;R%UbPMLqamvmBZ-{rDH!(un5r;$(m zb6U7+d%ZEx#=cuGSbP;@H~0)cLDol`zP2xis^70D>AXP}|Iz!}=3ava+&FAfH(M$# z4^#(DiYE1Oi3Ks$IHMw;HpLxB+K)t8=QVAYp!szQ?#WqjszUf2TF9Cqjz+s=T=4vN zxdR8%3f(X>i9a3tLHr z7?1I-C@W}(_0F;YV}Ca4x~Y|-vdaBqeAP$Ec&B_MnyvvL)d|R zYeICqXd=OK!TjIJ?oCume7MY(Wn*=FT-J;O`w!M-R~A380YB;EKpgJd+_yheam!=`fG z1+3p(($Xa}vaswSpmBquf}x3V8ylOswMF{B#B^&(&(1_}q00r|vyFXuXxFdvI!jSZ z^WM4EHvby1TGoPQLjFkDQq~tr>KknQmn=WcC{^^FEh>!@k_OwXnbz%xuFH%+lCrj= z^ZCmtfAjJqEesd#r>>-3fA<2k>Jc#=x(vjUg@Yp<`LbRw#^dCE{3lquFf|X|A20e} z|1*HuMDx#tmzPr5(y=iA!|7pRAZNTl`LAwN-e%v_WvSNp=W#-sUbla>z}I(?4gK@+ z5)&SUO{ou_+`zpl!DV7KRi`If^n;`KH0CEty>>C(YNVQ6g% zgUJ@1>YPL@7?#x$ENB^FD-N0`!dU*c$d}T!tkKw zy_P#ga!K$Xe+F;nHe7VH5$UjSkO=o$t}+@ZV|)*=un=HrTEH#=&UQXpIl&o*2?8z% zzyM4}e>U3SL~5MvN|?7CwHZL}eORhT-8a`FQ~R<^gC9EAVedEZ=xbwEL0T#_Qy6r= zqo$^Y+lJR_MyhOFqs>WjsZqJRVYswBmRYstJA0n=f4Jc-s7vQEQb194wIb3zuT7(>uJQXN z`W=s06*_JC$y9h%5#!KVt^A_wbQd5V(qH0114TtW~M%L=OE>E(0p<8y=Kwj4RZ(M<(AAyf1faYxvA<=#rjybQBi{=vVAEG%hboyBYJBx~(O_#qiEy$ejGivP}t{`ERjc z6)g$1XI=}KkHcQPVh;K#ieiCH8ZbCCv{-u0?0$1bp0DyNAANy{tE-h2`kBv#>oW+y zR28!_`m1zEIY@;4xiF3|;_y|&1Q!KKe^`FbKoiZNX_t8jydr8$3alC^?2yyC^+O5~ zOc_sX9}l>Ko~oz}%pDsIh|<-xdBoAgFVlQ1Dfni+2=D7M>&c;qV@Ie9)<}|zDpL>k zFl2{)m3CIl_YqiE$2~E3F06`=zEiHXwjswwm{A}+&bSu|G6-1PP zi{n$}zcTLNj7Epi7Ti}i8Oa2kA0TrtWZqBqimG0R&%^MHP+1_2rw8oPa$^cg@T57oGRPqGQ9j4~!7|Z=8H2J!F0Av}8 zmL1SG<4$H}!&$Tz3p;$aq(kv8!Q2{=FjylZBA|aBylL+T$Xvt= zB!elz$FHEN`2 zcheW`8E)HP2;3nyOm0vmqdnumeF$ST#+h>5lEH?kd)&L$gnW%7fwtPu=&b?vr9rXh zMnaLRCdvM+!-VXbhFu1{mfTGi+=X1NHH%Rnrgb{cxj0VJA7-m7$!%>^CrQ9l@rNNd zyLF|Xdmd?1@vlc_!u+MEtZ>fGptwv<&qG-zr58n-@{@o|Q>8$L&t;gTra+A|EXN#~ zSMpCaFkL%a;p`E)JzCC`)DCFZ4&x?xFIxruwN2S1gw zs^@PJD-g4JP;qk1jFX`dpMALZmAg!;UrycVLB`L~?lJc(4A%^O#6-XDP3QV2niZj* z(3tBWM{-T{6q2Z(GGgL527j=_doImQ_-6i_h! zP!qv<3tbt&AVLUOu-8VK20(Q|q<2sf5s1Xh%y-~mfP!Ab=DK+e4gi3pu9;n`%q@)! z_5)*yZmufuiJU?FN36iGmx2-vQEw^hkM=DD`mQj*{XnDgpu9_~h^{OOhkZC$iuqg= z!_)iuBJ6zLErg4E>d7OK&D{Yb!BL+>cb;O7JRy`*LECrZ!7!o6=vPOEymjcmctFrg zN6!C#u0>R+x=Y^K1y!>BX-E?;ukMP?jjBg}uUAwv3FxVdH5T?(gf+GLnfPhvNF;8& zI(IpCRJk32RB*$I99~$^!Zx*9G(HEaVnD_`0O%Zmx`C9ZWT+Mi5X@_Dmuj1a#EUPc_7I=NkQ9?1w8;N!0@DfJ8 z7)IlV={F6;m_Ifb`kNgI%Vrur`*~iQk{739tyX58Z_X=P%)MPGasPzNWn@Q5J$>}s zuf99AdIXyfz0#)dTzAc>-W1&NJ*#DY%;%z1CfD+r=OupL2u8J6+>xx$^>|lWFZk}g zPs;ql=JnjhA2(xVHF60ApyMwJCNt5i(ecuevZo~M*$Y>@Z9wN4fe<_%P6pVUKs( zt&KE2xj$M*8_XvHzy`R4!IOt>ZoyWu1DQKQ*f!~~M=kWE;y6~s!v^ULcI1%29xSsn zFLNdU3gLGhR2G)V^3&K@a-b6-tP14r#Z@gS18E;<>;`a*hM7nn9Fg#KU`%(8?ym6=y+)Eun=}V+fK*>K>?fm!CQ%B zzvD4f9aedGqT07J8E1uuf10ha6?R{g!7{!-gxoiRgMJmy@vLS!uNNfHPZ@69ELYsq)R*Qe_0Wemw{QhIi5?bOON znkot5#ldf4vVR)&`ttMT>$=0OXExTgvPwrh>iX5o3-O8fyOyvwcSC6g+*1_1DkNl| z$5YhaMQ>y1!|SO_l980Z<+RAv)tp}SCI5}@&8C~bY4&h+wIkoSrc$C=+;5ShFi2hJ zf1>)W+k;o7;5ff`weLdY`@o`d)uBx0dY!?s1Q@*GjjrFHsV01p7hJkvM*kFJR(b`d zDmafEE+hvxwzN$9vsLQsuZ=>p3>k)}^d0rW01m@;u_t!-*5NXR0P%=ycTZFT=yu-l0qI|MRHtPJWNRl#}|$Qj%9WabbNZGu=|NRx;hD>xwJuS-i|WZn=j z#Ul-@=WfRk5*5AZT9uHlm-an@q3B}D>}4t99Qf%^jb zEwSaVBiJz_R*eOGiYb;3J)+GLv?UyqjX|+Y?pu4$d9Ex{nx?Q&M^39Sd_LYtpvJHd zQw-tan(i_B9!Md1B(wZ;UR2Tf!_i^zRCBY4!x`VZ7Oy#f4_|JwM=@9quUXw3A+jTrBWQ|aj7F9cJgZ(x8pJL+B554hP2s1lfQIbN{Jeuh2C)hry*Y>)cxLS9T)LEj$> zL8%=q`7T$(&btLePx@^alRzgFCGBe(DC)L)PME23XVzeR*t3BKbe^BTL!`QK8Qu}c zglCa0&@D5tI2SOb=+!@A7y?y>EtS@VOo2Z~=+JwE7bnh`BlsESurgl5?_W6pZL#zE zNtv}aPX95NdEh{b$}ri~<)JIpr(hG}BO{k;V?HW@x{Bn|I*~13WwDfmL>zR}hw_V} za1)Bm|C-0EX$Ec1t3Z_14p$_wqot#Olf1ukUiR7}k9`G3P2aoOQnqq*K6D?s{W&jB z-_kdO$R-l}LE;o3noorRGyP#)&=mrD6!#b*paX5ZorE(K#OZJG@I*no5^P+=6crVF ztx-h1F@L_u1>@E5BEh3Q?ekr2s8QxS_zh0Ks`JzJI{@;xXp

^3qM#dqPe9>Hau8+YstGSmTUMO<@a}DYLWi*kP_4jomEwrtjy)Rf+J)pIXU6 z8;%!w(Fo|@GQOa)p@q}r`_ktqC$|aP&)hXHf=0o1@1DIk-J~j0e~dY*eBEf-{rG@@ zw;Wqo?;1oq3ciIFXhhZ8ZBFzp8kNve<@|grmsQVwCW#@-uyrIOx44iNAG#Gl=bwUz zkD$K(vF~ZL0}KzoTzDJOCB;K(@NYF15Z)$+Cp7dj5C_)#E+*lvITlN$<^7puZhhRt zv@^SSv!hHiy#+#v{VBUGjg1p_RmT)+YHGmI*leT?)+u<-0~WE7{UCqXDPph-dh24t za_3{S(5KLjTb=fgpDZ!*4pp*7%jQ?)6q6blw7#q-1OkZ$nQndGO-M&a+hKGhdnR5d^y`k`l}DGol-NvG?`RG#VJsA>Nh~L_~=5J zoqOKZs})4zN$b&kHO02UAG^60f68r3b8%5Erky<{lD|B;8shIsngIJ#fkPJe4d#O2 z9jf0O54{F$Pm?|j#2Kl?KySI0>!Crp790HiGG0ghH4p7(kVHn_@`z0onYw}Z_E(lo zSWI3Y(1I}0Cn?=VV4zUMiC%5W?eoMg6n;(Nu&}RqzdX2UAc~?36l8=4^Zxww;`WYiq@L&{yqP?AQ2bQ^5%2v)|;rQ6Zi^Be82iXT3~EMH5;F)rbt znojzKL5Xt|=O$^ESsPC2bjL(8&21<0!200{J4v?d>37+3LYUCQo+^+le`V$MUa;;w z$UEL3#cW(&k{UbW7GbDa5-a03jZYdN%PluLC0cXT1}YPhtwO%7Me85diwd9wQOe5! zRS66&4q!?p;j_OB{TIM7{$V~|nPxKr@hYHez=<1S900}X7t9Vk)(cPTmQh6#B76a5&a-JGFrW2@)-W@v!2iu46MDTgj!} z1C0xYc60?i2d^J~p)u6D7&yCR%Zmw8I%kxbH~)*8*M#YZs**jM8{SzREKhT9MYT4u zd9DzcrL&z&<)sA0hPYJ6eKhNn=xU8GiujAc~ z%&_d2y#GOoN$aS?sAipj_#}j6GUnOodzL1=9-BhVnm&rD_2D3V^O#>EUo7Wre0x{A zy7%Mh%Wa|HlunnQtR%HnL1+*(qCPgC;O+;vl;nw-0HtlU;>nioHEjI)Sd`MkgSvD*E& z%h0Q==4bQAV}Mps3IFgxW~~m=Ja}98;bO-+(^OG0T#Gjg`_peKW+#S0@tn5tWQSO< z!T6(_Ay$9?L-Ah1?RBp4>B@+Zg*7Q`z>vTXF$VbS(r;(wm#TY`(F>}WzStc2%Jz+p<}t7c zM!mCaA{eX>@>hFV;(`zV5z{pwn4hxq8-b&D3rF-FjdSssYw)Oq81X74IB#8nsE-J1@EKn)m{x<}0RTSSR#3Qx8gFXiOfF>bFoQ_?TwVK# zCbgA%LyV!Wu5L^z1&z=@0*|N94@sb-G_&Z8*ujN=ku6JdzeAIA z+(quL+;L#CaRqDS3`@+yW^)VUw+!4kcWDLF*T3%BW1zGPdw`FCSJUq2s)U-&jV_bb zkk(X%#L=S2fM?8&ss-LtwzORIb%ZNKDV=i0Z?p&3$Ona~mV)!6_2_W1cna015W_Rxum@*WIL@r00(Q?! zGs~&2syN0TjzBljqmlksR8M=38Z91~5E{K?`ZJZO+FjLXzt_jh{_59myP4D`kGbzYn%E^FA9Z z_#CGU-6qg13s9!O-==e*NF>8cPq?IIw#Jlu8gxQ1rn5#~`-d?dR{UVg!Ermd$iu^f zTn8^6qJVZjuq>XggmeMrg6(j`%&ylONsWVv_t*S24d;d+3jg$On2!ILZ$W)n8LvtJ zj3>GQ(901b8t^6{pji(-m3KcNF0u`WdBx|?n}OOq%6|u;;?*c~}5d(oWfjAve zU{EYSTKWcz^*pz8SBL>$tA>N*Cx9QKT=qZ(cOmTaKt5rN7@eP$39Scr6%sow-|3dI z=c7d2tRjgB$Y=py^P!^Fkt$i=dGEAo$h6JXPrUA1=YyDqDw`| zX=gzgEHl8x2J_?(tJ!9q_)yqF%^)98Wo2dCe%D;1R2{FOS2D+d=$FE^+nR9XI0ORM zFG%eVeZd;&k4sOGO-)Wrq*3kg*Sj@TaT}jDKAV=Mqy76O_rCgon2Q6^uy-5zRnMJx z_w*}Q&$c8tXT>O{TenoOCAVWh0c>P1CUQvg1WlOtrE6Ulygta(cp}}Bvfjgo=~&$g z3*E-U;LFy(v$;!QJg4cgxuID|U>J^RsHa|gCpI32?#rjz9JL7<)1~6ObT~M7Ouht} z-g0_LD>@%T{NP(?fO;m_T9U~oYUc6NhIFfS!$5R_x;c4LKKUM-XJvIgMR7D5G2*mf z)Pk8sWVqwk1bQ2MeZH>WIlfxnxGFqnIQZ_!Ho-IAy`>#DLz^Ju&|Zl1Opjm8S#=W zSvA#`GP#{YD8~KEyfVGTUhsAdL?DL;=Wrh*c?Q5~V!RUq_liJ5Fidd>Z4;ssAbHb( z&;Uu}9zdi)T|({GvRGIzBd-srA|fm(_lFss9jv#&2!jost?B=w`gwEToE-`Z4yUx3 zu+qP3>BF8<8cb6xav_KEq~(qH&Ttt7Jf={^x<}DH(YK68fsHF3aLHf#Ea6X1l5Mm(H?<^jxv@Po_uhF+Nt7h(lB^mNfN$6b*FDc`qR%hm(39_WpKT?F7%uJBCWC z9k(|hid%cc<|AFDr?AsWJ7dJM^ACU%AFMV>ik^HqavS#XAok{YaIS@)!HM%*@Kw^J z3|6}Y$wk*O-x50a=BiuCR4a6FKQNr}vJ}6I5oqsc)%=#bokJv3l1TW*@)%5>j)kPN z7&m*JlTr#~g|~LIcH)LaS^(^luVyA&6;%VG_Z`CzoN-E_>`8<&2E*d_;aJ+AmoafZ z+5NknxinMr;n1I($U!}s>?~Tq%rPUYcdc*A96Uey8B{?-GudA-x>L4uvj=W({SkbNq?n*@V6N#*-vT`r)Aplpg&>^i!G0m< z>gu{thNLfGB2`dOsDZT2!J?d7GkDUW*zE-jYlzbUJ{g3l4V)El&*JqQvc2g;%1fc3 zba(-mWfWolBk6>*X~8oOfWH9sC?KuA9?)YYi(g~xXF?^xhC&4?B!ECqV68!*DhW9L z5H5U7kD!Tw_JA1v5H>V?;vnh2jx-0j5!7;gPMHlWN`M|xNO?f9jUcF(Xcw662DIJy zVHJfW_n@R5d=*G#3qbzkw76CuRr1rrnHf+?&@?m#4Z}d<0-vPj+|ys`@sDTGQSmuO zV@Gv`;^uTGG9^~}uHLbwa+SwivG@={`^p$K3P>NQwp{*?0Iw^g7Qqm- z24vEPRj==UhS4XPUi+1s@oyeIU!I|RS@K=;sm_st=un_7_-{LLY+vLkdus4tiLa*m zJs_QdpZ2CV-+y_Fm)Pl$E|~Un{)W+Qm7ZhnYe&NEpM~*mYZ_AEM>Pkt4*xpD8LEol z({Omg&})>Z0cYaGM|;$bCus_mQG#vkvxon}8PobWG2CFll654pI#jB$rU;UIUO8^!2%f(Y048zdVKOAQyEW7rAFTdE}z-;VzIy&k| z8@qz!Z*UC}^k?i$v_D%FV6ky3s7`q?&BFGPd-?r6;=+BPVl)D97g>jPR?7mN8`iON z5G<&f-uw<1KGKK-v>>E(97z=elJoKfU3@SqA{i$69?e!>1_mEE(V*M--irGd!?Xm~ zf;M!&z!J&<>_Lc&1xBDo{X_;LpIUdu_jGh<%KkS;F#;v@$PCdCt9I3R2MC~$rZ=J` zgFzljI;i1}N`xj4WL&e8Eu~GY7Xw0(NdYMk{s7Yqml9OqBtXE)+7Em4<9x0^=o!1{ zT<{qx$KX3<#d=!f6n5VTY1#Zn(CKm@hl|G7#00^nO=C_tvC*EU>`rVaG6_67J(09D zFi7Ncqx?B5vi(a~ECws3&AYtthFq}qbuKRIw;4(AKq3M!LPHb;Lmr zbiLbbP#FPUDyVw)Q2u5Bvf%^rptMAk+Y#>p_JydFkd%cJLt0-bzv){DIe~`<*&wAW zvA-V5Pcue=2RM?fgFAut-aR}xd%}w79r{t;j~_@WFO~BKDr`ETrPQ{CBFsXsX4YyG zIaK_`Jcp1HVoy<4?!V<|{gv;H@deoX;)!+c*d{k^=;X*#+gG?#yt_gmbUin?6fd`c zP+XG*#Wmup;dynoyGl+&&tCLZyBf7M#PjzWs4w zvh~-tBs}BTk}UUaBG~-vUl9=V5;SslJtoNE=#D_MUB6&Rc-@ihz1TRHgQw*xB@5US zJQC)@O-uy32gEqTr87o2$92N8(I5yj|Jc0BlScVo@+uHbykJSU!wHP_;J8{gW0CAYCv8 z2_1Q|W>an?fCmNah#deX)Svn$RT;SNVYG~Qm?Hr*w$JeD9853B9}nX2?c2Adq@@!R z6Wt+QW(6QoFHVc>TVOtf!ami!msr}ahqpjN0bfg%%&uQiIe7E+=ZZqg27NndEzZ^* zpD$mCd~3GP8l5^8Xt{~6KX*B-$o!&E{_wq(!JyfOq8`3oRJvtN26Tk9R3x|hi|`)eDKiYM>TX}J81tP4KiJbZsA%zpJ7B)F+L#cAy#us#&4ONp zx10Yw3!yGbQn`Hi>4C1t9tB(8Ti}QDf8OvP+Wr68q+VJ)muV#SszYj?yQaWKWf8Es z!C-+YEiG-^pB!=otBhq|hbgySt}0UQfdmoZk8F+OC5magv8hFP?f=T`|5s-B`%h%{ zY<753fErcRcFi^Cr31)O;FJ-6%mMj4O1G0uW`+2=KH86!r-}Dq-_zXE0t-nxzyQMt qHO|`;b&m>1rL6p0TVLk*IeNW-Q&#_=hCd4YkQSE}%NEgj_g?@Meec=; literal 0 HcmV?d00001 From 1f8d444f294f11d9e673052ba123f1ac99f0dfe1 Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 26 Mar 2022 21:59:41 -0600 Subject: [PATCH 26/41] Andrew Farris Added priority example files for FRS and GMRS, amatuer 2m and 70cm radio services new file: priority-frs1 new file: priority-frs2 new file: priority-gmrs new file: priority-gmrsri new file: priority-uhf new file: priority-vhf new file: ../ham2mon_processor_usage_2.png --- apps/priority-frs1 | 8 ++++++++ apps/priority-frs2 | 8 ++++++++ apps/priority-gmrs | 9 +++++++++ apps/priority-gmrsri | 9 +++++++++ apps/priority-uhf | 10 ++++++++++ apps/priority-vhf | 11 +++++++++++ ham2mon_processor_usage_2.png | Bin 0 -> 168045 bytes 7 files changed, 55 insertions(+) create mode 100644 apps/priority-frs1 create mode 100644 apps/priority-frs2 create mode 100644 apps/priority-gmrs create mode 100644 apps/priority-gmrsri create mode 100644 apps/priority-uhf create mode 100644 apps/priority-vhf create mode 100644 ham2mon_processor_usage_2.png diff --git a/apps/priority-frs1 b/apps/priority-frs1 new file mode 100644 index 0000000..1bdfdb5 --- /dev/null +++ b/apps/priority-frs1 @@ -0,0 +1,8 @@ +462562500 +462587500 +462612500 +462637500 +462662500 +462687500 +462712500 + diff --git a/apps/priority-frs2 b/apps/priority-frs2 new file mode 100644 index 0000000..29676d2 --- /dev/null +++ b/apps/priority-frs2 @@ -0,0 +1,8 @@ +467562500 +467587500 +467612500 +467637500 +467662500 +467687500 +467712500 + diff --git a/apps/priority-gmrs b/apps/priority-gmrs new file mode 100644 index 0000000..c8ff06b --- /dev/null +++ b/apps/priority-gmrs @@ -0,0 +1,9 @@ +462562500 +462550000 +462575000 +462600000 +462625000 +462650000 +462675000 +462700000 +462725000 diff --git a/apps/priority-gmrsri b/apps/priority-gmrsri new file mode 100644 index 0000000..ade92e4 --- /dev/null +++ b/apps/priority-gmrsri @@ -0,0 +1,9 @@ +467562500 +467550000 +467575000 +467600000 +467625000 +467650000 +467675000 +467700000 +467725000 diff --git a/apps/priority-uhf b/apps/priority-uhf new file mode 100644 index 0000000..2884b5b --- /dev/null +++ b/apps/priority-uhf @@ -0,0 +1,10 @@ +440560000 +440600000 +441400000 +441840000 +444575000 +445560000 +445600000 +445840000 +446000000 +446400000 diff --git a/apps/priority-vhf b/apps/priority-vhf new file mode 100644 index 0000000..62f611f --- /dev/null +++ b/apps/priority-vhf @@ -0,0 +1,11 @@ +145380000 +145980000 +146130000 +146190000 +146265000 +146420000 +146520000 +146730000 +146790000 +146865000 +147270000 diff --git a/ham2mon_processor_usage_2.png b/ham2mon_processor_usage_2.png new file mode 100644 index 0000000000000000000000000000000000000000..a81621c730983300eac7eba2d47c936472740775 GIT binary patch literal 168045 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�$UvYiz{#DOm$yvC;0g~QW6lzw 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 literal 0 HcmV?d00001 From e7e8b3993737c041bf0ab286a8b50b71f70f411a Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 26 Mar 2022 22:06:37 -0600 Subject: [PATCH 27/41] Andrew Farris Multiple fixes for version updates gr-osmosdr 0.2.0.0 (0.2.0) gnuradio 3.9.5.0 Added priority example files for FRS and GMRS, amatuer 2m and 70cm radio services Revised handling of /dev/null wave file sink by creating a null sink Revised error handling by adding OS and base catch blocks, commented out for testing in this comm --- apps/ham2mon.py | 19 ++++++++---- apps/parser.py | 15 +++++----- apps/receiver.py | 78 ++++++++++++++++++++++++++++++------------------ apps/scanner.py | 10 +------ 4 files changed, 72 insertions(+), 50 deletions(-) diff --git a/apps/ham2mon.py b/apps/ham2mon.py index 83314bb..2bd1567 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -163,15 +163,24 @@ def main(screen): curses.wrapper(main) except KeyboardInterrupt: pass - except RuntimeError: - print("") - print("RuntimeError: SDR hardware not detected or insufficient USB permissions. Try running as root.") - print("") +# except RuntimeError as err: +# print("") +# print("RuntimeError: SDR hardware not detected or insufficient USB permissions. Try running as root.") +# print("") +# print("RuntimeError: {err=}, {type(err)=}") +# print("") except err.LogError: print("") print("LogError: database logging not active, to be expanded.") print("") - + except OSError as err: + print("") + print("OS error: {0}".format(err)) + print("") +# except BaseException as err: +# print("") +# print("Unexpected: {err=}, {type(err)=}") +# print("") finally: # --- Cleanup on exit --- diff --git a/apps/parser.py b/apps/parser.py index 0e9e427..a6bdd85 100755 --- a/apps/parser.py +++ b/apps/parser.py @@ -105,14 +105,14 @@ def __init__(self): help="File of EOL delimited priority channels in Hz") parser.add_option("-L", "--log_file", type="string", - dest="channel_log_file_name", - default="", - help="Log file for channel detection") + dest="channel_log_file_name", + default="channel-log", + help="Log file for channel detection") parser.add_option("-A", "--log_active_timeout", type="int", - dest="channel_log_timeout", - default=15, - help="Timeout delay for active channel log entries") + dest="channel_log_timeout", + default=15, + help="Timeout delay for active channel log entries") parser.add_option("-c", "--correction", type="int", dest="freq_correction", default=0, @@ -123,7 +123,7 @@ def __init__(self): help="Mute audio from speaker (still allows recording)") parser.add_option("-b", "--bps", type="int", dest="audio_bps", - default=8, + default=16, help="Audio bit depth (bps)") parser.add_option("-M", "--max_db", type="float", dest="max_db", @@ -201,6 +201,7 @@ def main(): print("volume_db: " + str(parser.volume_db)) print("threshold_db: " + str(parser.threshold_db)) print("record: " + str(parser.record)) + print("play: " + str(parser.play)) print("lockout_file_name: " + str(parser.lockout_file_name)) print("priority_file_name: " + str(parser.priority_file_name)) print("channel_log_file_name: " + str(parser.channel_log_file_name)) diff --git a/apps/receiver.py b/apps/receiver.py index c205822..3136037 100755 --- a/apps/receiver.py +++ b/apps/receiver.py @@ -30,7 +30,7 @@ def set_center_freq(self, center_freq, rf_center_freq): Sets baseband center frequency of frequency translating FIR filter Also sets file name of wave file sink - If tuner is tuned to zero Hz then set to file name to /dev/null + If tuner is tuned to zero Hz then set to file name to None Otherwise set file name to tuned RF frequency in MHz Args: @@ -38,7 +38,9 @@ def set_center_freq(self, center_freq, rf_center_freq): rf_center_freq (float): RF center in Hz (for file name) """ # Since the frequency (hence file name) changed, then close it - self.blocks_wavfile_sink.close() + if (self.record and self.file_name and + self.file_name != None): + self.blocks_wavfile_sink.close() # If we never wrote any data to the wavfile sink, delete the file self._delete_wavfile_if_empty() @@ -50,8 +52,8 @@ def set_center_freq(self, center_freq, rf_center_freq): # Set the file name timestamp = int(time.time()) if self.center_freq == 0 or not self.record: - # If tuner at zero Hz, or record false, then file name to /dev/null - file_name = "/dev/null" + # If tuner at zero Hz, or record false, then file name to None + file_name = None else: # Otherwise use frequency and time stamp for file name strtimestamp = "_" + str(timestamp) @@ -65,14 +67,16 @@ def set_center_freq(self, center_freq, rf_center_freq): except OSError: # will need to add something here for Win support pass # directory already exists - self.file_name = file_name - self.blocks_wavfile_sink.open(self.file_name) + if (file_name != None and self.record and self.file_name != None): + self.file_name = file_name + self.blocks_wavfile_sink.open(self.file_name) + self.time_stamp = timestamp def _delete_wavfile_if_empty(self): """Delete the current wavfile if it's empty.""" if (not self.record or not self.file_name or - self.file_name == '/dev/null'): + self.file_name == None): return # If we never wrote any data to the wavfile sink, or its smaller than @@ -147,7 +151,7 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, self.time_stamp = 0 squelch_db = -60 self.quad_demod_gain = 0.050 - self.file_name = "/dev/null" + self.file_name = None self.record = record self.min_file_size = min_file_size @@ -156,8 +160,8 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, # Low pass filter taps for decimation by 5 low_pass_filter_taps_0 = \ - grfilter.firdes_low_pass(1, 1, 0.090, 0.010, - grfilter.firdes.WIN_HAMMING) + grfilter.firdes.low_pass(1, 1, 0.090, 0.010, + window.WIN_HAMMING) # Frequency translating FIR filter decimating by 5 self.freq_xlating_fir_filter_ccc = \ @@ -172,8 +176,8 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, # Low pass filter taps for decimation from samp_rate/25 to 40-79.9 ksps # In other words, decimation by int(samp_rate/1E6) # 12.5 kHz cutoff for NBFM channel bandwidth - low_pass_filter_taps_1 = grfilter.firdes_low_pass( - 1, samp_rate/decims[0]**2, 12.5E3, 1E3, grfilter.firdes.WIN_HAMMING) + low_pass_filter_taps_1 = grfilter.firdes.low_pass( + 1, samp_rate/decims[0]**2, 12.5E3, 1E3, window.WIN_HAMMING) # FIR filter decimation by int(samp_rate/1E6) fir_filter_ccc_1 = grfilter.fir_filter_ccc(decims[1], @@ -189,9 +193,9 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, analog.quadrature_demod_cf(self.quad_demod_gain) # 3.5 kHz cutoff for audio bandwidth - low_pass_filter_taps_2 = grfilter.firdes_low_pass(1,\ + low_pass_filter_taps_2 = grfilter.firdes.low_pass(1,\ samp_rate/(decims[1] * decims[0]**2),\ - 3.5E3, 500, grfilter.firdes.WIN_HAMMING) + 3.5E3, 500, window.WIN_HAMMING) # FIR filter decimating by 5 from 40-79.9 ksps to 8-15.98 ksps fir_filter_fff_0 = grfilter.fir_filter_fff(decims[0], @@ -219,12 +223,20 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, analog_pwr_squelch_ff = analog.pwr_squelch_ff(-200, 1e-1, 0, True) # File sink with single channel and bits/sample - self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, - audio_rate, audio_bps) + if (self.file_name != None): + self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, + audio_rate, audio_bps, + blocks.FORMAT_WAV, + blocks.FORMAT_PCM_16, + False) # Connect the blocks for recording self.connect(pfb_arb_resampler_fff, analog_pwr_squelch_ff) - self.connect(analog_pwr_squelch_ff, self.blocks_wavfile_sink) + if (self.file_name != None): + self.connect(analog_pwr_squelch_ff, self.blocks_wavfile_sink) + else: + null_sink1 = blocks.null_sink(gr.sizeof_float) + self.connect(analog_pwr_squelch_ff, null_sink1) def set_volume(self, volume_db): """Sets the volume @@ -278,7 +290,7 @@ class TunerDemodAM(BaseTuner): # pylint: disable=too-many-locals def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, - audio_bps=8): + audio_bps=16): gr.hier_block2.__init__(self, "TunerDemodAM", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_float)) @@ -288,7 +300,7 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, self.time_stamp = 0 squelch_db = -60 self.agc_ref = 0.1 - self.file_name = "/dev/null" + self.file_name = None self.record = record self.min_file_size = min_file_size @@ -298,8 +310,8 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, # Low pass filter taps for decimation by 5 low_pass_filter_taps_0 = \ - grfilter.firdes_low_pass(1, 1, 0.090, 0.010, - grfilter.firdes.WIN_HAMMING) + grfilter.firdes.low_pass(1, 1, 0.090, 0.010, + window.WIN_HAMMING) # Frequency translating FIR filter decimating by 5 self.freq_xlating_fir_filter_ccc = \ @@ -314,8 +326,8 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, # Low pass filter taps for decimation from samp_rate/25 to 40-79.9 ksps # In other words, decimation by int(samp_rate/1E6) # 12.5 kHz cutoff for NBFM channel bandwidth - low_pass_filter_taps_1 = grfilter.firdes_low_pass( - 1, samp_rate/decims[0]**2, 12.5E3, 1E3, grfilter.firdes.WIN_HAMMING) + low_pass_filter_taps_1 = grfilter.firdes.low_pass( + 1, samp_rate/decims[0]**2, 12.5E3, 1E3, window.WIN_HAMMING) # FIR filter decimation by int(samp_rate/1E6) fir_filter_ccc_1 = grfilter.fir_filter_ccc(decims[1], @@ -336,9 +348,9 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, am_demod_cf = blocks.complex_to_mag(1) # 3.5 kHz cutoff for audio bandwidth - low_pass_filter_taps_2 = grfilter.firdes_low_pass(1,\ + low_pass_filter_taps_2 = grfilter.firdes.low_pass(1,\ samp_rate/(decims[1] * decims[0]**2),\ - 3.5E3, 500, grfilter.firdes.WIN_HAMMING) + 3.5E3, 500, window.WIN_HAMMING) # FIR filter decimating by 5 from 40-79.9 ksps to 8-15.98 ksps fir_filter_fff_0 = grfilter.fir_filter_fff(decims[0], @@ -366,12 +378,20 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, analog_pwr_squelch_ff = analog.pwr_squelch_ff(-200, 1e-1, 0, True) # File sink with single channel and 8 bits/sample - self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, - audio_rate, audio_bps) + if (self.file_name != None): + self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, + audio_rate, audio_bps, + blocks.FORMAT_WAV, + blocks.FORMAT_PCM_16, + False) # Connect the blocks for recording self.connect(pfb_arb_resampler_fff, analog_pwr_squelch_ff) - self.connect(analog_pwr_squelch_ff, self.blocks_wavfile_sink) + if (self.file_name != None): + self.connect(analog_pwr_squelch_ff, self.blocks_wavfile_sink) + else: + null_sink1 = blocks.null_sink(gr.sizeof_float) + self.connect(analog_pwr_squelch_ff, null_sink1) def set_volume(self, volume_db): """Sets the volume @@ -410,7 +430,7 @@ class Receiver(gr.top_block): def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, hw_args="uhd", freq_correction=0, record=True, play=True, - audio_bps=8, min_file_size=0): + audio_bps=16, min_file_size=0): # Call the initialization method from the parent class gr.top_block.__init__(self, "Receiver") diff --git a/apps/scanner.py b/apps/scanner.py index 121a07b..265da88 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -114,6 +114,7 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.lockout_file_name = lockout_file_name self.priority_file_name = priority_file_name self.channel_log_file_name = channel_log_file_name + self.channel_log_file = None self.channel_log_timeout = channel_log_timeout self.log_recent_channels = [] self.log_timeout_last = int(time.time()) @@ -146,15 +147,6 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.min_freq = (self.center_freq - self.samp_rate/2) self.max_freq = (self.center_freq + self.samp_rate/2) - -# # removed this since its essentially the same as above and this required spectrum first -# self.spectrum = self.receiver.probe_signal_vf.level() -# # estimate min/max frequency based on spectrum length and sample rate -# self.min_freq = ((0 - len(self.spectrum)/2) * (self.samp_rate / len(self.spectrum) \ -# + self.center_freq)) -# self.max_freq = ((len(self.spectrum) - len(self.spectrum)/2) * (self.samp_rate / len(self.spectrum) \ -# + self.center_freq)) - # Start the receiver and wait for samples to accumulate self.receiver.start() time.sleep(1) From 88df396dcd6e866a4a5f1ab8211918a92c7e6b1c Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 2 Apr 2022 12:29:18 -0600 Subject: [PATCH 28/41] Modified gui code for simplicity rearranging outputs if desired Added freq_low and freq_high tuner limits (in addition to max_freq and min_freq) limited by the sampling Added freq_low and freq_high to gui, command line switches, and demod setup Modified some logic on set frequency and wav filename, separated out function for set_file_name from set_center_freq General cleanup of some comments and code organization, removed last_center member from BaseTuner as never used modified: cursesgui.py modified: ham2mon.py modified: parser.py modified: receiver.py modified: scanner.py --- apps/cursesgui.py | 125 +++++++++++++++++++++++++++++++++++----------- apps/ham2mon.py | 28 +++++++---- apps/parser.py | 17 +++++++ apps/receiver.py | 82 ++++++++++++++++++------------ apps/scanner.py | 65 ++++++++++++++++++++---- 5 files changed, 235 insertions(+), 82 deletions(-) diff --git a/apps/cursesgui.py b/apps/cursesgui.py index 26dfa0b..d1b40cf 100755 --- a/apps/cursesgui.py +++ b/apps/cursesgui.py @@ -368,6 +368,8 @@ def __init__(self, screen): self.center_freq = 146E6 self.min_freq = 144E6 self.max_freq = 148E6 + self.freq_low = 144E6 + self.freq_max = 148E6 self.samp_rate = 2E6 self.freq_entry = 'None' self.squelch_db = -60 @@ -398,8 +400,7 @@ def draw_rx(self): """Draws receiver paramaters """ - # Clear previous contents, draw border, and title -# self.win.clear() + # Erase previous contents, draw border, and title # using erase prevents jitter in some terminals compared to clear() directly self.win.erase() self.win.border(0) @@ -408,73 +409,139 @@ def draw_rx(self): curses.color_pair(6) | curses.A_DIM | curses.A_BOLD) # Draw the receiver info prefix fields + index = 1 text = "RF Freq (MHz) : " self.win.addnstr(1, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Min Freq (MHz) : " self.win.addnstr(2, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Max Freq (MHz) : " self.win.addnstr(3, 1, text, 18, curses.color_pair(6)) + + index = index+1 + text = "Low Tune (MHz) : " + self.win.addnstr(4, 1, text, 18, curses.color_pair(6)) - for index, gain in enumerate(self.gains, 2): + index = index+1 + text = "High Tune (MHz): " + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + for index2, gain in enumerate(self.gains, 2): text = "{} Gain (dB){} : ".format(gain["name"], (4-len(gain["name"]))*' ') - self.win.addnstr(index+2, 1, text, 15) + self.win.addnstr(index+index2-1, 1, text, 18) + index3 = index2 + index = index+index3 text = "BB Rate (Msps) : " - self.win.addnstr(index+3, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "BB Sql (dB) : " - self.win.addnstr(index+4, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "AF Vol (dB) : " - self.win.addnstr(index+5, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Record : " - self.win.addnstr(index+6, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Demod Type : " - self.win.addnstr(index+7, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Lockout File : " - self.win.addnstr(index+8, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Priority File : " - self.win.addnstr(index+9, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Log File : " - self.win.addnstr(index+10, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Log Timeout (s): " - self.win.addnstr(index+11, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Log Mode : " - self.win.addnstr(index+12, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) # Draw the receiver info suffix fields + index = 1 if self.freq_entry != 'None': text = self.freq_entry else: text = '{:.3f}'.format((self.center_freq)/1E6) - self.win.addnstr(1, 20, text, 8, curses.color_pair(5)) + self.win.addnstr(index, 20, text, 8, curses.color_pair(5)) + + index = index+1 text = '{:.3f}'.format((self.min_freq)/1E6) - self.win.addnstr(2, 20, text, 8, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 8, curses.color_pair(5)) + + index = index+1 text = '{:.3f}'.format((self.max_freq)/1E6) - self.win.addnstr(3, 20, text, 8, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 8, curses.color_pair(5)) + + index = index+1 + text = '{:.3f}'.format((self.freq_low)/1E6) + self.win.addnstr(index, 20, text, 8, curses.color_pair(5)) + + index = index+1 + text = '{:.3f}'.format((self.freq_high)/1E6) + self.win.addnstr(index, 20, text, 8, curses.color_pair(5)) - for index, gain in enumerate(self.gains, 2): + for index2, gain in enumerate(self.gains, 2): text = str(gain["value"]) - self.win.addnstr(index+2, 20, text, 8, curses.color_pair(5)) + self.win.addnstr(index+index2-1, 20, text, 8, curses.color_pair(5)) + index3 = index2 + index = index+index3 text = str(self.samp_rate/1E6) - self.win.addnstr(index+3, 20, text, 8, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 8, curses.color_pair(5)) + + index = index+1 text = str(self.squelch_db) - self.win.addnstr(index+4, 20, text, 8, curses.color_pair(5)) + self.win.addnstr(index, 20, text, 8, curses.color_pair(5)) + + index = index+1 text = str(self.volume_db) - self.win.addnstr(index+5, 20, text, 8, curses.color_pair(5)) + self.win.addnstr(index, 20, text, 8, curses.color_pair(5)) + + index = index+1 text = str(self.record) - self.win.addnstr(index+6, 20, text, 8, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 8, curses.color_pair(6)) + + index = index+1 text = str(self.type_demod) - self.win.addnstr(index+7, 20, text, 8, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 8, curses.color_pair(6)) + + index = index+1 text = str(self.lockout_file_name) - self.win.addnstr(index+8, 20, text, 20, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 20, curses.color_pair(6)) + + index = index+1 text = str(self.priority_file_name) - self.win.addnstr(index+9, 20, text, 20, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 20, curses.color_pair(6)) + + index = index+1 text = str(self.channel_log_file_name) - self.win.addnstr(index+10, 20, text, 20, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 20, curses.color_pair(6)) + + index = index+1 text = str(self.channel_log_timeout) - self.win.addnstr(index+11, 20, text, 20, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 20, curses.color_pair(5)) + + index = index+1 text = str(self.log_mode) - self.win.addnstr(index+12, 20, text, 20, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 20, curses.color_pair(6)) # Hide cursor self.win.leaveok(1) diff --git a/apps/ham2mon.py b/apps/ham2mon.py index 2bd1567..b0262b9 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -60,10 +60,14 @@ def main(screen): max_demod_length = PARSER.max_demod_length channel_spacing = PARSER.channel_spacing min_file_size = PARSER.min_file_size + freq_low = PARSER.freq_low + freq_high = PARSER.freq_high + scanner = scnr.Scanner(ask_samp_rate, num_demod, type_demod, hw_args, freq_correction, record, lockout_file_name, priority_file_name, channel_log_file_name, channel_log_timeout, - play, audio_bps, max_demod_length, channel_spacing, min_file_size) + play, audio_bps, max_demod_length, channel_spacing, min_file_size, + freq_low, freq_high) # Set the paramaters scanner.set_center_freq(PARSER.center_freq) @@ -78,6 +82,8 @@ def main(screen): rxwin.center_freq = scanner.center_freq rxwin.min_freq = scanner.min_freq rxwin.max_freq = scanner.max_freq + rxwin.freq_low = scanner.freq_low + rxwin.freq_high = scanner.freq_high rxwin.samp_rate = scanner.samp_rate rxwin.squelch_db = scanner.squelch_db rxwin.volume_db = scanner.volume_db @@ -163,12 +169,12 @@ def main(screen): curses.wrapper(main) except KeyboardInterrupt: pass -# except RuntimeError as err: -# print("") -# print("RuntimeError: SDR hardware not detected or insufficient USB permissions. Try running as root.") -# print("") -# print("RuntimeError: {err=}, {type(err)=}") -# print("") + except RuntimeError as err: + print("") + print("RuntimeError: SDR hardware not detected or insufficient USB permissions. Try running as root.") + print("") + print("RuntimeError: {err=}, {type(err)=}") + print("") except err.LogError: print("") print("LogError: database logging not active, to be expanded.") @@ -177,10 +183,10 @@ def main(screen): print("") print("OS error: {0}".format(err)) print("") -# except BaseException as err: -# print("") -# print("Unexpected: {err=}, {type(err)=}") -# print("") + except BaseException as err: + print("") + print("Unexpected: {err=}, {type(err)=}", err, type(err)) + print("") finally: # --- Cleanup on exit --- diff --git a/apps/parser.py b/apps/parser.py index a6bdd85..41c5920 100755 --- a/apps/parser.py +++ b/apps/parser.py @@ -34,6 +34,8 @@ class CLParser(object): max_demod_length (int): Timeout for long running demodulators to reset new file timestamp in seconds channel_spacing (int): Channel spacing (spectrum bin size) for identification of channels min_file_size (int): Minimum file size to save + freq_low (int): Low frequency for channels + freq_high (int): High frequency for channels """ # pylint: disable=too-few-public-methods # pylint: disable=too-many-instance-attributes @@ -55,6 +57,10 @@ def __init__(self): default=0, help="Type of demodulator (0=NBFM, 1=AM)") + parser.add_option("-e", "--range", type="string", + dest="freq_range", default="0-2000000000", + help="Limit reception to specified frequency range") + parser.add_option("-f", "--freq", type="string", dest="center_freq", default=146E6, help="Hardware RF center frequency in Hz") @@ -180,6 +186,15 @@ def __init__(self): self.channel_spacing = int(options.channel_spacing) self.min_file_size = int(options.min_file_size) + try: + self.freq_low = int(options.freq_range.split('-')[0]) + except: + self.freq_low = 0 + + try: + self.freq_high = int(options.freq_range.split('-')[1]) + except: + self.freq_high = 0 def main(): """Test the parser""" @@ -213,6 +228,8 @@ def main(): print("max_demod_length: " + str(parser.max_demod_length)) print("channel_spacing: " + str(parser.channel_spacing)) print("min_file_size: " + str(parser.min_file_size)) + print("freq_low: " + str(parser.freq_low)) + print("freq_high: " + str(parser.freq_high)) if __name__ == '__main__': diff --git a/apps/receiver.py b/apps/receiver.py index 3136037..6875e3d 100755 --- a/apps/receiver.py +++ b/apps/receiver.py @@ -25,6 +25,15 @@ class BaseTuner(gr.hier_block2): See TunerDemodNBFM and TunerDemodAM for better documentation. """ + def __init__(self): + # Default values + self.last_heard = 0 + self.active = False + self.file_name = None + + def set_last_heard(self, a_time): + self.last_heard = a_time + def set_center_freq(self, center_freq, rf_center_freq): """Sets baseband center frequency and file name @@ -42,35 +51,42 @@ def set_center_freq(self, center_freq, rf_center_freq): self.file_name != None): self.blocks_wavfile_sink.close() - # If we never wrote any data to the wavfile sink, delete the file + # If we did not write enough data to the wavfile sink, delete the file self._delete_wavfile_if_empty() - # Set the frequency - self.freq_xlating_fir_filter_ccc.set_center_freq(center_freq) + # Set the frequency of the tuner self.center_freq = center_freq + self.freq_xlating_fir_filter_ccc.set_center_freq(self.center_freq) - # Set the file name - timestamp = int(time.time()) + # Set the file name if recording if self.center_freq == 0 or not self.record: # If tuner at zero Hz, or record false, then file name to None - file_name = None + self.file_name = None else: - # Otherwise use frequency and time stamp for file name - strtimestamp = "_" + str(timestamp) - file_freq = (rf_center_freq + self.center_freq)/1E6 - file_freq = np.round(file_freq, 3) - file_name = 'wav/' + '{:.3f}'.format(file_freq) + strtimestamp + ".wav" - - # Make sure the 'wav' directory exists - try: - os.mkdir('wav') - except OSError: # will need to add something here for Win support - pass # directory already exists - - if (file_name != None and self.record and self.file_name != None): - self.file_name = file_name + self.set_file_name(rf_center_freq) + + if (self.file_name != None and self.record): self.blocks_wavfile_sink.open(self.file_name) + self.active = True + + def set_file_name(self, rf_center_freq): + # Otherwise use frequency and time stamp for file name + timestamp = int(time.time()) + tstamp = time.strftime("%Y%m%d_%H%M%S", time.localtime()) + "{:.3f}".format(time.time()%1)[1:] + file_freq = (rf_center_freq + self.center_freq)/1E6 + file_freq = np.round(file_freq, 4) + file_name = 'wav/' + '{:.4f}'.format(file_freq) + "_" + tstamp + ".wav" + + # Make sure the 'wav' directory exists + # a better approach likely is checking existence instead of failing to create it + try: + os.mkdir('wav') + except OSError: # will need to add something here for Win support + pass # directory already exists + + self.file_name = file_name + # timestamp the demod update to match filename self.time_stamp = timestamp def _delete_wavfile_if_empty(self): @@ -84,6 +100,8 @@ def _delete_wavfile_if_empty(self): if os.stat(self.file_name).st_size < (self.min_file_size): os.unlink(self.file_name) # delete the file + self.active = False + def set_squelch(self, squelch_db): """Sets the threshold for both squelches @@ -222,17 +240,17 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, # Only want it to gate when the previous squelch has gone to zero analog_pwr_squelch_ff = analog.pwr_squelch_ff(-200, 1e-1, 0, True) + # Connect the blocks for recording + self.connect(pfb_arb_resampler_fff, analog_pwr_squelch_ff) + # File sink with single channel and bits/sample - if (self.file_name != None): + if (self.record): + self.set_file_name(self.center_freq) self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, - audio_rate, audio_bps, + audio_rate, blocks.FORMAT_WAV, blocks.FORMAT_PCM_16, False) - - # Connect the blocks for recording - self.connect(pfb_arb_resampler_fff, analog_pwr_squelch_ff) - if (self.file_name != None): self.connect(analog_pwr_squelch_ff, self.blocks_wavfile_sink) else: null_sink1 = blocks.null_sink(gr.sizeof_float) @@ -377,17 +395,17 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, # Only want it to gate when the previous squelch has gone to zero analog_pwr_squelch_ff = analog.pwr_squelch_ff(-200, 1e-1, 0, True) + # Connect the blocks for recording + self.connect(pfb_arb_resampler_fff, analog_pwr_squelch_ff) + # File sink with single channel and 8 bits/sample - if (self.file_name != None): + if (self.record): + self.set_file_name(self.center_freq) self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, - audio_rate, audio_bps, + audio_rate, blocks.FORMAT_WAV, blocks.FORMAT_PCM_16, False) - - # Connect the blocks for recording - self.connect(pfb_arb_resampler_fff, analog_pwr_squelch_ff) - if (self.file_name != None): self.connect(analog_pwr_squelch_ff, self.blocks_wavfile_sink) else: null_sink1 = blocks.null_sink(gr.sizeof_float) diff --git a/apps/scanner.py b/apps/scanner.py index 265da88..bb11d92 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -64,9 +64,14 @@ class Scanner(object): channel_log_timeout (int): Timeout delay between active channel entries in log audio_bps (int): Audio bit depth in bps (bits/samples) max_demod_length (int): Maximum demod time in seconds (0=disable) + freq_low (int): Freq below which we won't tune a receiver (Hz) + freq_high (int): Freq above which we won't tune a receiver (Hz) + spacing (int): granularity of frequency quantization Attributes: center_freq (float): Hardware RF center frequency in Hz + low_bound (int): Freq below which we won't tune a receiver (Hz) + high_bound (int): Freq above which we won't tune a receiver (Hz) samp_rate (float): Hardware sample rate in sps (1E6 min) gains : Enumerated gain types and values squelch_db (int): Squelch in dB @@ -95,7 +100,7 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, channel_log_file_name="", channel_log_timeout=15, play=True, audio_bps=8, max_demod_length=0, channel_spacing=5000, - min_file_size=0): + min_file_size=0, freq_low=0, freq_high=2000000000): # Default values self.squelch_db = -60 @@ -103,6 +108,9 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.threshold_db = 10 self.record = record self.play = play + self.audio_bps = audio_bps + self.freq_low = freq_low + self.freq_high = freq_high self.spectrum = [] self.lockout_channels = [] self.priority_channels = [] @@ -121,6 +129,9 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.log_mode = "" self.max_demod_length = max_demod_length self.min_file_size = min_file_size + self.low_bound = freq_low + self.high_bound = freq_high + self.hang_time = 1.0 # Create receiver object self.receiver = recvr.Receiver(ask_samp_rate, num_demod, type_demod, @@ -146,6 +157,14 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.center_freq = self.receiver.center_freq self.min_freq = (self.center_freq - self.samp_rate/2) self.max_freq = (self.center_freq + self.samp_rate/2) + # cannot set channel freq lower than min sampled freq + if (self.freq_low < self.min_freq): + self.freq_low = self.min_freq + # cannot set channel freq higher than max sampled freq + if (self.freq_high > self.max_freq): + self.freq_high = self.max_freq + self.low_bound = self.freq_low - self.center_freq + self.high_bound = self.freq_high - self.center_freq # Start the receiver and wait for samples to accumulate self.receiver.start() @@ -237,12 +256,18 @@ def scan_cycle(self): # Round channels to channel spacing # Note this affects tuning the demodulators # 5000 Hz is adequate for NBFM - channels = np.round(channels / self.channel_spacing) * self.channel_spacing + # Note that channel spacing is with respect to the center + baseband offset, + # not just the offset itself + real_channels = channels + self.center_freq + real_channels = np.round(real_channels / self.channel_spacing) * self.channel_spacing + channels = real_channels - self.center_freq # set active channels for gui highlight before filtering down lockout or adding priority active_channels = channels # Remove channels that are already in the priority list + # future, should find channels that are close too priority and replace with priority + # when less than channel_spacing separated from priority temp = [] for channel in channels: if channel not in self.priority_channels: @@ -263,17 +288,28 @@ def scan_cycle(self): pass channels = temp - # Set demodulators that are no longer in channel list to 0 Hz - #for demodulator in self.receiver.demodulators: + # Remove channels that are outside the requested freq range +# temp = [] +# for channel in channels: +# if channel > self.freq_low and channel < self.freq_high: +# temp = np.append(temp, channel) +# else: +# pass +# channels = temp + + # Update demodulator last heards and expire old ones + the_now = time.time() for idx in range(len(self.receiver.demodulators)): demodulator = self.receiver.demodulators[idx] if (demodulator.center_freq != 0) and (demodulator.center_freq not in channels): - demodulator.set_center_freq(0, self.center_freq) - # Write in channel log file that the channel is off - demodulator_freq = demodulator.center_freq - self.__print_channel_log__(demodulator_freq + self.center_freq, False, idx) + if the_now - demodulator.last_heard > self.hang_time: + demodulator.set_center_freq(0, self.center_freq) + # Write in channel log file that the channel is off + demodulator_freq = demodulator.center_freq + self.__print_channel_log__(demodulator_freq + self.center_freq, False, idx) else: - pass + #pass + demodulator.set_last_heard(the_now) # Add new channels to demodulators for channel in channels: @@ -448,6 +484,15 @@ def set_center_freq(self, center_freq): # reset min/max based on sample rate self.min_freq = (self.center_freq - self.samp_rate/2) self.max_freq = (self.center_freq + self.samp_rate/2) + # reset low/high based on new center and bounds + self.freq_low = self.low_bound - self.center_freq + self.freq_high = self.high_bound + self.center_freq + # cannot set channel freq lower than min sampled freq + if (self.freq_low < self.min_freq): + self.freq_low = self.min_freq + # cannot set channel freq higher than max sampled freq + if (self.freq_high > self.max_freq): + self.freq_high = self.max_freq # Update the priority since frequency is changing self.update_priority() @@ -525,7 +570,7 @@ def main(): priority_file_name = parser.priority_file_name channel_log_file_name = parser.channel_log_file_name audio_bps = parser.audio_bps - max_demo_length = parser.max_demod_length + max_demod_length = parser.max_demod_length channel_spacing = parser.channel_spacing min_file_size = parser.min_file_size scanner = Scanner(ask_samp_rate, num_demod, type_demod, hw_args, From c1eeb379461c7ad613820fa0d4dc9091c2de85a0 Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 2 Apr 2022 12:46:58 -0600 Subject: [PATCH 29/41] updated change log history including miweber67 contribution captured modified: ../README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 05a2717..239d816 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,10 @@ lordmorgul: - pulled gain corrections to python3 version from john - defined max file size to save from command line option - channel width configurable from command line option +- incorporate miweber67 freq range limits + +miweber67 +- frequency range to limit selected channels to within specific limit john-: - long running file end (demodulator run time limit) @@ -165,6 +169,9 @@ Active channels are flagged as active periodically based on the active channel l ` -f CENTER_FREQ, --freq=CENTER_FREQ` ` Hardware RF center frequency in Hz` +` -e RANGE, --range=RANGE` +` Limit reception to specified range, xx-yy in Hz` + ` -r ASK_SAMP_RATE, --rate=ASK_SAMP_RATE` ` Hardware ask sample rate in sps (1E6 minimum)` @@ -227,6 +234,7 @@ Active channels are flagged as active periodically based on the active channel l ` Minimum size file to save in bytes, default 0 (save all)` + ## Description: The high speed signal processing is done in GR and the logic & control in Python. There are no custom GR blocks. The GUI is written in Curses and is meant to be lightweight. See the video for a basic overview. I attempted to make the program very object oriented and “Pythonic”. Each module runs on it's own for testing purposes. From f60c600f8cdd4861e2b47574be5c399220096318 Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 2 Apr 2022 14:05:00 -0600 Subject: [PATCH 30/41] Added center_freq to constructor params for Scanner to provide ability to calculate desired low and high freq tuning bounds with given low_freq and high_freq Fixed error in Scanner test code from old gain code upgrades Edited ham2mon to add new param Fixed logic of removing channels that are below low_bound and above high_bound modified: ham2mon.py modified: scanner.py --- apps/ham2mon.py | 5 +++-- apps/scanner.py | 53 ++++++++++++++++++++++++++++++------------------- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/apps/ham2mon.py b/apps/ham2mon.py index b0262b9..8ee2d09 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -60,6 +60,7 @@ def main(screen): max_demod_length = PARSER.max_demod_length channel_spacing = PARSER.channel_spacing min_file_size = PARSER.min_file_size + center_freq = PARSER.center_freq freq_low = PARSER.freq_low freq_high = PARSER.freq_high @@ -67,10 +68,10 @@ def main(screen): freq_correction, record, lockout_file_name, priority_file_name, channel_log_file_name, channel_log_timeout, play, audio_bps, max_demod_length, channel_spacing, min_file_size, - freq_low, freq_high) + center_freq, freq_low, freq_high) # Set the paramaters - scanner.set_center_freq(PARSER.center_freq) + scanner.set_center_freq(center_freq) scanner.set_squelch(PARSER.squelch_db) scanner.set_volume(PARSER.volume_db) diff --git a/apps/scanner.py b/apps/scanner.py index bb11d92..bc18806 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -64,6 +64,7 @@ class Scanner(object): channel_log_timeout (int): Timeout delay between active channel entries in log audio_bps (int): Audio bit depth in bps (bits/samples) max_demod_length (int): Maximum demod time in seconds (0=disable) + center_freq (int): initial center frequency for receiver (Hz) freq_low (int): Freq below which we won't tune a receiver (Hz) freq_high (int): Freq above which we won't tune a receiver (Hz) spacing (int): granularity of frequency quantization @@ -100,7 +101,7 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, channel_log_file_name="", channel_log_timeout=15, play=True, audio_bps=8, max_demod_length=0, channel_spacing=5000, - min_file_size=0, freq_low=0, freq_high=2000000000): + min_file_size=0, center_freq=0, freq_low=0, freq_high=2000000000): # Default values self.squelch_db = -60 @@ -111,6 +112,7 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.audio_bps = audio_bps self.freq_low = freq_low self.freq_high = freq_high + self.center_freq = center_freq self.spectrum = [] self.lockout_channels = [] self.priority_channels = [] @@ -139,6 +141,9 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, audio_bps, min_file_size) + # Set the initial center frequency here to allow setting min/max and low/high bounds + self.receiver.set_center_freq(center_freq) + # Open channel log file for appending data, if it is specified if channel_log_file_name != "": self.channel_log_file = open(channel_log_file_name, 'a') @@ -147,12 +152,12 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, else: # Opening log file failed so cannot perform this log mode # Either raise exception or continue without logging, second preferable - self.log_mode = "" + self.log_mode = "none" #raise(LogError("file","Cannot open log file")) else: self.channel_log_file = None - # Get the hardware sample rate and center frequency + # Get the hardware sample rate and center frequency in Hz self.samp_rate = self.receiver.samp_rate self.center_freq = self.receiver.center_freq self.min_freq = (self.center_freq - self.samp_rate/2) @@ -178,7 +183,7 @@ def __del__(self): self.channel_log_file.close() def __print_channel_log_active__(self, freq, state): - if self.log_mode is not None and state is True: + if self.log_mode is not None and self.log_mode != "none" and state is True: state_str = {True: "act", False: "off"} now = datetime.datetime.now() if self.log_mode == "file" and self.channel_log_file is not None: @@ -199,7 +204,7 @@ def __print_channel_log_active__(self, freq, state): raise(err.LogError("unknown","no log mode defined")) def __print_channel_log__(self, freq, state, idx): - if self.log_mode is not None: + if self.log_mode is not None and self.log_mode != "none": state_str = {True: "on", False: "off"} if state == False: freq = 0 @@ -289,13 +294,13 @@ def scan_cycle(self): channels = temp # Remove channels that are outside the requested freq range -# temp = [] -# for channel in channels: -# if channel > self.freq_low and channel < self.freq_high: -# temp = np.append(temp, channel) -# else: -# pass -# channels = temp + temp = [] + for channel in channels: + if channel > self.low_bound and channel < self.high_bound: + temp = np.append(temp, channel) + else: + pass + channels = temp # Update demodulator last heards and expire old ones the_now = time.time() @@ -345,25 +350,26 @@ def scan_cycle(self): # reset the demodulator to its frequency to restart file demodulator.set_center_freq(0, temp_freq) - # Create an tuned channel list of strings for the GUI + # Create an tuned channel list of strings for the GUI in MHz # If channel is a zero then use an empty string self.gui_tuned_channels = [] for demod_freq in self.receiver.get_demod_freqs(): if demod_freq == 0: text = "" else: - # Calculate actual RF frequency + # Calculate actual RF frequency in MHz gui_tuned_channel = (demod_freq + \ self.center_freq)/1E6 text = '{:.3f}'.format(gui_tuned_channel) self.gui_tuned_channels.append(text) - # Create an active channel list of strings for the GUI + # Create an active channel list of strings for the GUI in MHz # This is any channel above threshold # do not include priority if not above threshold # do include lockout if above threshold self.gui_active_channels = [] for channel in active_channels: + # calculate active channel freq in MHz gui_active_channel = (channel + self.center_freq)/1E6 text = '{:.3f}'.format(gui_active_channel) self.gui_active_channels.append(text) @@ -402,9 +408,10 @@ def add_lockout(self, idx): self.lockout_channels = np.append(self.lockout_channels, demod_freq) - # Create a lockout channel list of strings for the GUI + # Create a lockout channel list of strings for the GUI in MHz self.gui_lockout_channels = [] for lockout_channel in self.lockout_channels: + # lockout channel in MHz gui_lockout_channel = (lockout_channel + \ self.receiver.center_freq)/1E6 text = '{:.3f}'.format(gui_lockout_channel) @@ -435,9 +442,10 @@ def clear_lockout(self): else: pass - # Create a lockout channel list of strings for the GUI + # Create a lockout channel list of strings for the GUI in MHz self.gui_lockout_channels = [] for lockout_channel in self.lockout_channels: + # lockout channel in MHz gui_lockout_channel = (lockout_channel + \ self.receiver.center_freq)/1E6 text = '{:.3f}'.format(gui_lockout_channel) @@ -459,6 +467,7 @@ def update_priority(self): lines = builtins.filter(None, lines) else: lines = __builtin__.filter(None, lines) + # Convert to baseband frequencies, round, and append if within BW for freq in lines: bb_freq = float(freq) - self.center_freq @@ -473,6 +482,7 @@ def update_priority(self): def set_center_freq(self, center_freq): """Sets RF center frequency of hardware and clears lockout channels + Sets low and high demod frequency limits based on provided bounds in command line Args: center_freq (float): Hardware RF center frequency in Hz @@ -484,7 +494,7 @@ def set_center_freq(self, center_freq): # reset min/max based on sample rate self.min_freq = (self.center_freq - self.samp_rate/2) self.max_freq = (self.center_freq + self.samp_rate/2) - # reset low/high based on new center and bounds + # reset low/high freq for demod based on new center and bounds from original provided self.freq_low = self.low_bound - self.center_freq self.freq_high = self.high_bound + self.center_freq # cannot set channel freq lower than min sampled freq @@ -573,17 +583,20 @@ def main(): max_demod_length = parser.max_demod_length channel_spacing = parser.channel_spacing min_file_size = parser.min_file_size + center_freq = parser.center_freq + freq_low = parser.freq_low + freq_high = parser.freq_high scanner = Scanner(ask_samp_rate, num_demod, type_demod, hw_args, freq_correction, record, lockout_file_name, priority_file_name, channel_log_file_name, audio_bps, max_demod_length, channel_spacing, - min_file_size) + min_file_size, center_freq, freq_low, freq_high) # Set frequency, gain, squelch, and volume scanner.set_center_freq(parser.center_freq) print("\n") print("Started %s at %.3f Msps" % (hw_args, scanner.samp_rate/1E6)) - print("RX at %.3f MHz with %d dB gain" % (scanner.center_freq/1E6)) + print("RX at %.3f MHz" % (scanner.center_freq/1E6)) scanner.filter_and_set_gains(parser.gains) for gain in scanner.gains: print("gain %s at %d dB" % (gain["name"], gain["value"])) From 0325c849ec9a6ece1a9729b9d9c16e70563da9b6 Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 9 Apr 2022 00:37:07 -0500 Subject: [PATCH 31/41] Clean personally relevant freqs out of priority examples, GMRS channels only, calling channels only in vhf for 2m and uhf for 70cm examples --- apps/priority-gmrs | 1 - apps/priority-gmrsri | 1 - apps/priority-uhf | 10 +--------- apps/priority-vhf | 11 +---------- 4 files changed, 2 insertions(+), 21 deletions(-) diff --git a/apps/priority-gmrs b/apps/priority-gmrs index c8ff06b..482c457 100644 --- a/apps/priority-gmrs +++ b/apps/priority-gmrs @@ -1,4 +1,3 @@ -462562500 462550000 462575000 462600000 diff --git a/apps/priority-gmrsri b/apps/priority-gmrsri index ade92e4..3d22f38 100644 --- a/apps/priority-gmrsri +++ b/apps/priority-gmrsri @@ -1,4 +1,3 @@ -467562500 467550000 467575000 467600000 diff --git a/apps/priority-uhf b/apps/priority-uhf index 2884b5b..9183cf5 100644 --- a/apps/priority-uhf +++ b/apps/priority-uhf @@ -1,10 +1,2 @@ -440560000 -440600000 -441400000 -441840000 -444575000 -445560000 -445600000 -445840000 +444000000 446000000 -446400000 diff --git a/apps/priority-vhf b/apps/priority-vhf index 62f611f..ab6b77e 100644 --- a/apps/priority-vhf +++ b/apps/priority-vhf @@ -1,11 +1,2 @@ -145380000 -145980000 -146130000 -146190000 -146265000 -146420000 146520000 -146730000 -146790000 -146865000 -147270000 +146900000 From 8a85570a9bae90b483180be5f06be5d9d22af5bd Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 26 Mar 2022 21:59:41 -0600 Subject: [PATCH 32/41] Andrew Farris Added priority example files for FRS and GMRS, amatuer 2m and 70cm radio services new file: priority-frs1 new file: priority-frs2 new file: priority-gmrs new file: priority-gmrsri new file: priority-uhf new file: priority-vhf new file: ../ham2mon_processor_usage_2.png --- apps/priority-frs1 | 8 ++++++++ apps/priority-frs2 | 8 ++++++++ apps/priority-gmrs | 9 +++++++++ apps/priority-gmrsri | 9 +++++++++ apps/priority-uhf | 10 ++++++++++ apps/priority-vhf | 11 +++++++++++ 6 files changed, 55 insertions(+) create mode 100644 apps/priority-frs1 create mode 100644 apps/priority-frs2 create mode 100644 apps/priority-gmrs create mode 100644 apps/priority-gmrsri create mode 100644 apps/priority-uhf create mode 100644 apps/priority-vhf diff --git a/apps/priority-frs1 b/apps/priority-frs1 new file mode 100644 index 0000000..1bdfdb5 --- /dev/null +++ b/apps/priority-frs1 @@ -0,0 +1,8 @@ +462562500 +462587500 +462612500 +462637500 +462662500 +462687500 +462712500 + diff --git a/apps/priority-frs2 b/apps/priority-frs2 new file mode 100644 index 0000000..29676d2 --- /dev/null +++ b/apps/priority-frs2 @@ -0,0 +1,8 @@ +467562500 +467587500 +467612500 +467637500 +467662500 +467687500 +467712500 + diff --git a/apps/priority-gmrs b/apps/priority-gmrs new file mode 100644 index 0000000..c8ff06b --- /dev/null +++ b/apps/priority-gmrs @@ -0,0 +1,9 @@ +462562500 +462550000 +462575000 +462600000 +462625000 +462650000 +462675000 +462700000 +462725000 diff --git a/apps/priority-gmrsri b/apps/priority-gmrsri new file mode 100644 index 0000000..ade92e4 --- /dev/null +++ b/apps/priority-gmrsri @@ -0,0 +1,9 @@ +467562500 +467550000 +467575000 +467600000 +467625000 +467650000 +467675000 +467700000 +467725000 diff --git a/apps/priority-uhf b/apps/priority-uhf new file mode 100644 index 0000000..2884b5b --- /dev/null +++ b/apps/priority-uhf @@ -0,0 +1,10 @@ +440560000 +440600000 +441400000 +441840000 +444575000 +445560000 +445600000 +445840000 +446000000 +446400000 diff --git a/apps/priority-vhf b/apps/priority-vhf new file mode 100644 index 0000000..62f611f --- /dev/null +++ b/apps/priority-vhf @@ -0,0 +1,11 @@ +145380000 +145980000 +146130000 +146190000 +146265000 +146420000 +146520000 +146730000 +146790000 +146865000 +147270000 From b48a07b83171074e97b47180cfb27d98d841b68a Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 26 Mar 2022 22:06:37 -0600 Subject: [PATCH 33/41] Andrew Farris Multiple fixes for version updates gr-osmosdr 0.2.0.0 (0.2.0) gnuradio 3.9.5.0 Added priority example files for FRS and GMRS, amatuer 2m and 70cm radio services Revised handling of /dev/null wave file sink by creating a null sink Revised error handling by adding OS and base catch blocks, commented out for testing in this comm --- apps/ham2mon.py | 19 ++++++++---- apps/parser.py | 15 +++++----- apps/receiver.py | 78 ++++++++++++++++++++++++++++++------------------ apps/scanner.py | 10 +------ 4 files changed, 72 insertions(+), 50 deletions(-) diff --git a/apps/ham2mon.py b/apps/ham2mon.py index 83314bb..2bd1567 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -163,15 +163,24 @@ def main(screen): curses.wrapper(main) except KeyboardInterrupt: pass - except RuntimeError: - print("") - print("RuntimeError: SDR hardware not detected or insufficient USB permissions. Try running as root.") - print("") +# except RuntimeError as err: +# print("") +# print("RuntimeError: SDR hardware not detected or insufficient USB permissions. Try running as root.") +# print("") +# print("RuntimeError: {err=}, {type(err)=}") +# print("") except err.LogError: print("") print("LogError: database logging not active, to be expanded.") print("") - + except OSError as err: + print("") + print("OS error: {0}".format(err)) + print("") +# except BaseException as err: +# print("") +# print("Unexpected: {err=}, {type(err)=}") +# print("") finally: # --- Cleanup on exit --- diff --git a/apps/parser.py b/apps/parser.py index 0e9e427..a6bdd85 100755 --- a/apps/parser.py +++ b/apps/parser.py @@ -105,14 +105,14 @@ def __init__(self): help="File of EOL delimited priority channels in Hz") parser.add_option("-L", "--log_file", type="string", - dest="channel_log_file_name", - default="", - help="Log file for channel detection") + dest="channel_log_file_name", + default="channel-log", + help="Log file for channel detection") parser.add_option("-A", "--log_active_timeout", type="int", - dest="channel_log_timeout", - default=15, - help="Timeout delay for active channel log entries") + dest="channel_log_timeout", + default=15, + help="Timeout delay for active channel log entries") parser.add_option("-c", "--correction", type="int", dest="freq_correction", default=0, @@ -123,7 +123,7 @@ def __init__(self): help="Mute audio from speaker (still allows recording)") parser.add_option("-b", "--bps", type="int", dest="audio_bps", - default=8, + default=16, help="Audio bit depth (bps)") parser.add_option("-M", "--max_db", type="float", dest="max_db", @@ -201,6 +201,7 @@ def main(): print("volume_db: " + str(parser.volume_db)) print("threshold_db: " + str(parser.threshold_db)) print("record: " + str(parser.record)) + print("play: " + str(parser.play)) print("lockout_file_name: " + str(parser.lockout_file_name)) print("priority_file_name: " + str(parser.priority_file_name)) print("channel_log_file_name: " + str(parser.channel_log_file_name)) diff --git a/apps/receiver.py b/apps/receiver.py index c205822..3136037 100755 --- a/apps/receiver.py +++ b/apps/receiver.py @@ -30,7 +30,7 @@ def set_center_freq(self, center_freq, rf_center_freq): Sets baseband center frequency of frequency translating FIR filter Also sets file name of wave file sink - If tuner is tuned to zero Hz then set to file name to /dev/null + If tuner is tuned to zero Hz then set to file name to None Otherwise set file name to tuned RF frequency in MHz Args: @@ -38,7 +38,9 @@ def set_center_freq(self, center_freq, rf_center_freq): rf_center_freq (float): RF center in Hz (for file name) """ # Since the frequency (hence file name) changed, then close it - self.blocks_wavfile_sink.close() + if (self.record and self.file_name and + self.file_name != None): + self.blocks_wavfile_sink.close() # If we never wrote any data to the wavfile sink, delete the file self._delete_wavfile_if_empty() @@ -50,8 +52,8 @@ def set_center_freq(self, center_freq, rf_center_freq): # Set the file name timestamp = int(time.time()) if self.center_freq == 0 or not self.record: - # If tuner at zero Hz, or record false, then file name to /dev/null - file_name = "/dev/null" + # If tuner at zero Hz, or record false, then file name to None + file_name = None else: # Otherwise use frequency and time stamp for file name strtimestamp = "_" + str(timestamp) @@ -65,14 +67,16 @@ def set_center_freq(self, center_freq, rf_center_freq): except OSError: # will need to add something here for Win support pass # directory already exists - self.file_name = file_name - self.blocks_wavfile_sink.open(self.file_name) + if (file_name != None and self.record and self.file_name != None): + self.file_name = file_name + self.blocks_wavfile_sink.open(self.file_name) + self.time_stamp = timestamp def _delete_wavfile_if_empty(self): """Delete the current wavfile if it's empty.""" if (not self.record or not self.file_name or - self.file_name == '/dev/null'): + self.file_name == None): return # If we never wrote any data to the wavfile sink, or its smaller than @@ -147,7 +151,7 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, self.time_stamp = 0 squelch_db = -60 self.quad_demod_gain = 0.050 - self.file_name = "/dev/null" + self.file_name = None self.record = record self.min_file_size = min_file_size @@ -156,8 +160,8 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, # Low pass filter taps for decimation by 5 low_pass_filter_taps_0 = \ - grfilter.firdes_low_pass(1, 1, 0.090, 0.010, - grfilter.firdes.WIN_HAMMING) + grfilter.firdes.low_pass(1, 1, 0.090, 0.010, + window.WIN_HAMMING) # Frequency translating FIR filter decimating by 5 self.freq_xlating_fir_filter_ccc = \ @@ -172,8 +176,8 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, # Low pass filter taps for decimation from samp_rate/25 to 40-79.9 ksps # In other words, decimation by int(samp_rate/1E6) # 12.5 kHz cutoff for NBFM channel bandwidth - low_pass_filter_taps_1 = grfilter.firdes_low_pass( - 1, samp_rate/decims[0]**2, 12.5E3, 1E3, grfilter.firdes.WIN_HAMMING) + low_pass_filter_taps_1 = grfilter.firdes.low_pass( + 1, samp_rate/decims[0]**2, 12.5E3, 1E3, window.WIN_HAMMING) # FIR filter decimation by int(samp_rate/1E6) fir_filter_ccc_1 = grfilter.fir_filter_ccc(decims[1], @@ -189,9 +193,9 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, analog.quadrature_demod_cf(self.quad_demod_gain) # 3.5 kHz cutoff for audio bandwidth - low_pass_filter_taps_2 = grfilter.firdes_low_pass(1,\ + low_pass_filter_taps_2 = grfilter.firdes.low_pass(1,\ samp_rate/(decims[1] * decims[0]**2),\ - 3.5E3, 500, grfilter.firdes.WIN_HAMMING) + 3.5E3, 500, window.WIN_HAMMING) # FIR filter decimating by 5 from 40-79.9 ksps to 8-15.98 ksps fir_filter_fff_0 = grfilter.fir_filter_fff(decims[0], @@ -219,12 +223,20 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, analog_pwr_squelch_ff = analog.pwr_squelch_ff(-200, 1e-1, 0, True) # File sink with single channel and bits/sample - self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, - audio_rate, audio_bps) + if (self.file_name != None): + self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, + audio_rate, audio_bps, + blocks.FORMAT_WAV, + blocks.FORMAT_PCM_16, + False) # Connect the blocks for recording self.connect(pfb_arb_resampler_fff, analog_pwr_squelch_ff) - self.connect(analog_pwr_squelch_ff, self.blocks_wavfile_sink) + if (self.file_name != None): + self.connect(analog_pwr_squelch_ff, self.blocks_wavfile_sink) + else: + null_sink1 = blocks.null_sink(gr.sizeof_float) + self.connect(analog_pwr_squelch_ff, null_sink1) def set_volume(self, volume_db): """Sets the volume @@ -278,7 +290,7 @@ class TunerDemodAM(BaseTuner): # pylint: disable=too-many-locals def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, - audio_bps=8): + audio_bps=16): gr.hier_block2.__init__(self, "TunerDemodAM", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_float)) @@ -288,7 +300,7 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, self.time_stamp = 0 squelch_db = -60 self.agc_ref = 0.1 - self.file_name = "/dev/null" + self.file_name = None self.record = record self.min_file_size = min_file_size @@ -298,8 +310,8 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, # Low pass filter taps for decimation by 5 low_pass_filter_taps_0 = \ - grfilter.firdes_low_pass(1, 1, 0.090, 0.010, - grfilter.firdes.WIN_HAMMING) + grfilter.firdes.low_pass(1, 1, 0.090, 0.010, + window.WIN_HAMMING) # Frequency translating FIR filter decimating by 5 self.freq_xlating_fir_filter_ccc = \ @@ -314,8 +326,8 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, # Low pass filter taps for decimation from samp_rate/25 to 40-79.9 ksps # In other words, decimation by int(samp_rate/1E6) # 12.5 kHz cutoff for NBFM channel bandwidth - low_pass_filter_taps_1 = grfilter.firdes_low_pass( - 1, samp_rate/decims[0]**2, 12.5E3, 1E3, grfilter.firdes.WIN_HAMMING) + low_pass_filter_taps_1 = grfilter.firdes.low_pass( + 1, samp_rate/decims[0]**2, 12.5E3, 1E3, window.WIN_HAMMING) # FIR filter decimation by int(samp_rate/1E6) fir_filter_ccc_1 = grfilter.fir_filter_ccc(decims[1], @@ -336,9 +348,9 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, am_demod_cf = blocks.complex_to_mag(1) # 3.5 kHz cutoff for audio bandwidth - low_pass_filter_taps_2 = grfilter.firdes_low_pass(1,\ + low_pass_filter_taps_2 = grfilter.firdes.low_pass(1,\ samp_rate/(decims[1] * decims[0]**2),\ - 3.5E3, 500, grfilter.firdes.WIN_HAMMING) + 3.5E3, 500, window.WIN_HAMMING) # FIR filter decimating by 5 from 40-79.9 ksps to 8-15.98 ksps fir_filter_fff_0 = grfilter.fir_filter_fff(decims[0], @@ -366,12 +378,20 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, analog_pwr_squelch_ff = analog.pwr_squelch_ff(-200, 1e-1, 0, True) # File sink with single channel and 8 bits/sample - self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, - audio_rate, audio_bps) + if (self.file_name != None): + self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, + audio_rate, audio_bps, + blocks.FORMAT_WAV, + blocks.FORMAT_PCM_16, + False) # Connect the blocks for recording self.connect(pfb_arb_resampler_fff, analog_pwr_squelch_ff) - self.connect(analog_pwr_squelch_ff, self.blocks_wavfile_sink) + if (self.file_name != None): + self.connect(analog_pwr_squelch_ff, self.blocks_wavfile_sink) + else: + null_sink1 = blocks.null_sink(gr.sizeof_float) + self.connect(analog_pwr_squelch_ff, null_sink1) def set_volume(self, volume_db): """Sets the volume @@ -410,7 +430,7 @@ class Receiver(gr.top_block): def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, hw_args="uhd", freq_correction=0, record=True, play=True, - audio_bps=8, min_file_size=0): + audio_bps=16, min_file_size=0): # Call the initialization method from the parent class gr.top_block.__init__(self, "Receiver") diff --git a/apps/scanner.py b/apps/scanner.py index 121a07b..265da88 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -114,6 +114,7 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.lockout_file_name = lockout_file_name self.priority_file_name = priority_file_name self.channel_log_file_name = channel_log_file_name + self.channel_log_file = None self.channel_log_timeout = channel_log_timeout self.log_recent_channels = [] self.log_timeout_last = int(time.time()) @@ -146,15 +147,6 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.min_freq = (self.center_freq - self.samp_rate/2) self.max_freq = (self.center_freq + self.samp_rate/2) - -# # removed this since its essentially the same as above and this required spectrum first -# self.spectrum = self.receiver.probe_signal_vf.level() -# # estimate min/max frequency based on spectrum length and sample rate -# self.min_freq = ((0 - len(self.spectrum)/2) * (self.samp_rate / len(self.spectrum) \ -# + self.center_freq)) -# self.max_freq = ((len(self.spectrum) - len(self.spectrum)/2) * (self.samp_rate / len(self.spectrum) \ -# + self.center_freq)) - # Start the receiver and wait for samples to accumulate self.receiver.start() time.sleep(1) From d5bc9fc8e4fe5e172b238e024171b3dae97bbbb1 Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 2 Apr 2022 12:29:18 -0600 Subject: [PATCH 34/41] Modified gui code for simplicity rearranging outputs if desired Added freq_low and freq_high tuner limits (in addition to max_freq and min_freq) limited by the sampling Added freq_low and freq_high to gui, command line switches, and demod setup Modified some logic on set frequency and wav filename, separated out function for set_file_name from set_center_freq General cleanup of some comments and code organization, removed last_center member from BaseTuner as never used modified: cursesgui.py modified: ham2mon.py modified: parser.py modified: receiver.py modified: scanner.py --- apps/cursesgui.py | 125 +++++++++++++++++++++++++++++++++++----------- apps/ham2mon.py | 28 +++++++---- apps/parser.py | 17 +++++++ apps/receiver.py | 82 ++++++++++++++++++------------ apps/scanner.py | 65 ++++++++++++++++++++---- 5 files changed, 235 insertions(+), 82 deletions(-) diff --git a/apps/cursesgui.py b/apps/cursesgui.py index 26dfa0b..d1b40cf 100755 --- a/apps/cursesgui.py +++ b/apps/cursesgui.py @@ -368,6 +368,8 @@ def __init__(self, screen): self.center_freq = 146E6 self.min_freq = 144E6 self.max_freq = 148E6 + self.freq_low = 144E6 + self.freq_max = 148E6 self.samp_rate = 2E6 self.freq_entry = 'None' self.squelch_db = -60 @@ -398,8 +400,7 @@ def draw_rx(self): """Draws receiver paramaters """ - # Clear previous contents, draw border, and title -# self.win.clear() + # Erase previous contents, draw border, and title # using erase prevents jitter in some terminals compared to clear() directly self.win.erase() self.win.border(0) @@ -408,73 +409,139 @@ def draw_rx(self): curses.color_pair(6) | curses.A_DIM | curses.A_BOLD) # Draw the receiver info prefix fields + index = 1 text = "RF Freq (MHz) : " self.win.addnstr(1, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Min Freq (MHz) : " self.win.addnstr(2, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Max Freq (MHz) : " self.win.addnstr(3, 1, text, 18, curses.color_pair(6)) + + index = index+1 + text = "Low Tune (MHz) : " + self.win.addnstr(4, 1, text, 18, curses.color_pair(6)) - for index, gain in enumerate(self.gains, 2): + index = index+1 + text = "High Tune (MHz): " + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + for index2, gain in enumerate(self.gains, 2): text = "{} Gain (dB){} : ".format(gain["name"], (4-len(gain["name"]))*' ') - self.win.addnstr(index+2, 1, text, 15) + self.win.addnstr(index+index2-1, 1, text, 18) + index3 = index2 + index = index+index3 text = "BB Rate (Msps) : " - self.win.addnstr(index+3, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "BB Sql (dB) : " - self.win.addnstr(index+4, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "AF Vol (dB) : " - self.win.addnstr(index+5, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Record : " - self.win.addnstr(index+6, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Demod Type : " - self.win.addnstr(index+7, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Lockout File : " - self.win.addnstr(index+8, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Priority File : " - self.win.addnstr(index+9, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Log File : " - self.win.addnstr(index+10, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Log Timeout (s): " - self.win.addnstr(index+11, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) + + index = index+1 text = "Log Mode : " - self.win.addnstr(index+12, 1, text, 18, curses.color_pair(6)) + self.win.addnstr(index, 1, text, 18, curses.color_pair(6)) # Draw the receiver info suffix fields + index = 1 if self.freq_entry != 'None': text = self.freq_entry else: text = '{:.3f}'.format((self.center_freq)/1E6) - self.win.addnstr(1, 20, text, 8, curses.color_pair(5)) + self.win.addnstr(index, 20, text, 8, curses.color_pair(5)) + + index = index+1 text = '{:.3f}'.format((self.min_freq)/1E6) - self.win.addnstr(2, 20, text, 8, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 8, curses.color_pair(5)) + + index = index+1 text = '{:.3f}'.format((self.max_freq)/1E6) - self.win.addnstr(3, 20, text, 8, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 8, curses.color_pair(5)) + + index = index+1 + text = '{:.3f}'.format((self.freq_low)/1E6) + self.win.addnstr(index, 20, text, 8, curses.color_pair(5)) + + index = index+1 + text = '{:.3f}'.format((self.freq_high)/1E6) + self.win.addnstr(index, 20, text, 8, curses.color_pair(5)) - for index, gain in enumerate(self.gains, 2): + for index2, gain in enumerate(self.gains, 2): text = str(gain["value"]) - self.win.addnstr(index+2, 20, text, 8, curses.color_pair(5)) + self.win.addnstr(index+index2-1, 20, text, 8, curses.color_pair(5)) + index3 = index2 + index = index+index3 text = str(self.samp_rate/1E6) - self.win.addnstr(index+3, 20, text, 8, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 8, curses.color_pair(5)) + + index = index+1 text = str(self.squelch_db) - self.win.addnstr(index+4, 20, text, 8, curses.color_pair(5)) + self.win.addnstr(index, 20, text, 8, curses.color_pair(5)) + + index = index+1 text = str(self.volume_db) - self.win.addnstr(index+5, 20, text, 8, curses.color_pair(5)) + self.win.addnstr(index, 20, text, 8, curses.color_pair(5)) + + index = index+1 text = str(self.record) - self.win.addnstr(index+6, 20, text, 8, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 8, curses.color_pair(6)) + + index = index+1 text = str(self.type_demod) - self.win.addnstr(index+7, 20, text, 8, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 8, curses.color_pair(6)) + + index = index+1 text = str(self.lockout_file_name) - self.win.addnstr(index+8, 20, text, 20, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 20, curses.color_pair(6)) + + index = index+1 text = str(self.priority_file_name) - self.win.addnstr(index+9, 20, text, 20, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 20, curses.color_pair(6)) + + index = index+1 text = str(self.channel_log_file_name) - self.win.addnstr(index+10, 20, text, 20, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 20, curses.color_pair(6)) + + index = index+1 text = str(self.channel_log_timeout) - self.win.addnstr(index+11, 20, text, 20, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 20, curses.color_pair(5)) + + index = index+1 text = str(self.log_mode) - self.win.addnstr(index+12, 20, text, 20, curses.color_pair(6)) + self.win.addnstr(index, 20, text, 20, curses.color_pair(6)) # Hide cursor self.win.leaveok(1) diff --git a/apps/ham2mon.py b/apps/ham2mon.py index 2bd1567..b0262b9 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -60,10 +60,14 @@ def main(screen): max_demod_length = PARSER.max_demod_length channel_spacing = PARSER.channel_spacing min_file_size = PARSER.min_file_size + freq_low = PARSER.freq_low + freq_high = PARSER.freq_high + scanner = scnr.Scanner(ask_samp_rate, num_demod, type_demod, hw_args, freq_correction, record, lockout_file_name, priority_file_name, channel_log_file_name, channel_log_timeout, - play, audio_bps, max_demod_length, channel_spacing, min_file_size) + play, audio_bps, max_demod_length, channel_spacing, min_file_size, + freq_low, freq_high) # Set the paramaters scanner.set_center_freq(PARSER.center_freq) @@ -78,6 +82,8 @@ def main(screen): rxwin.center_freq = scanner.center_freq rxwin.min_freq = scanner.min_freq rxwin.max_freq = scanner.max_freq + rxwin.freq_low = scanner.freq_low + rxwin.freq_high = scanner.freq_high rxwin.samp_rate = scanner.samp_rate rxwin.squelch_db = scanner.squelch_db rxwin.volume_db = scanner.volume_db @@ -163,12 +169,12 @@ def main(screen): curses.wrapper(main) except KeyboardInterrupt: pass -# except RuntimeError as err: -# print("") -# print("RuntimeError: SDR hardware not detected or insufficient USB permissions. Try running as root.") -# print("") -# print("RuntimeError: {err=}, {type(err)=}") -# print("") + except RuntimeError as err: + print("") + print("RuntimeError: SDR hardware not detected or insufficient USB permissions. Try running as root.") + print("") + print("RuntimeError: {err=}, {type(err)=}") + print("") except err.LogError: print("") print("LogError: database logging not active, to be expanded.") @@ -177,10 +183,10 @@ def main(screen): print("") print("OS error: {0}".format(err)) print("") -# except BaseException as err: -# print("") -# print("Unexpected: {err=}, {type(err)=}") -# print("") + except BaseException as err: + print("") + print("Unexpected: {err=}, {type(err)=}", err, type(err)) + print("") finally: # --- Cleanup on exit --- diff --git a/apps/parser.py b/apps/parser.py index a6bdd85..41c5920 100755 --- a/apps/parser.py +++ b/apps/parser.py @@ -34,6 +34,8 @@ class CLParser(object): max_demod_length (int): Timeout for long running demodulators to reset new file timestamp in seconds channel_spacing (int): Channel spacing (spectrum bin size) for identification of channels min_file_size (int): Minimum file size to save + freq_low (int): Low frequency for channels + freq_high (int): High frequency for channels """ # pylint: disable=too-few-public-methods # pylint: disable=too-many-instance-attributes @@ -55,6 +57,10 @@ def __init__(self): default=0, help="Type of demodulator (0=NBFM, 1=AM)") + parser.add_option("-e", "--range", type="string", + dest="freq_range", default="0-2000000000", + help="Limit reception to specified frequency range") + parser.add_option("-f", "--freq", type="string", dest="center_freq", default=146E6, help="Hardware RF center frequency in Hz") @@ -180,6 +186,15 @@ def __init__(self): self.channel_spacing = int(options.channel_spacing) self.min_file_size = int(options.min_file_size) + try: + self.freq_low = int(options.freq_range.split('-')[0]) + except: + self.freq_low = 0 + + try: + self.freq_high = int(options.freq_range.split('-')[1]) + except: + self.freq_high = 0 def main(): """Test the parser""" @@ -213,6 +228,8 @@ def main(): print("max_demod_length: " + str(parser.max_demod_length)) print("channel_spacing: " + str(parser.channel_spacing)) print("min_file_size: " + str(parser.min_file_size)) + print("freq_low: " + str(parser.freq_low)) + print("freq_high: " + str(parser.freq_high)) if __name__ == '__main__': diff --git a/apps/receiver.py b/apps/receiver.py index 3136037..6875e3d 100755 --- a/apps/receiver.py +++ b/apps/receiver.py @@ -25,6 +25,15 @@ class BaseTuner(gr.hier_block2): See TunerDemodNBFM and TunerDemodAM for better documentation. """ + def __init__(self): + # Default values + self.last_heard = 0 + self.active = False + self.file_name = None + + def set_last_heard(self, a_time): + self.last_heard = a_time + def set_center_freq(self, center_freq, rf_center_freq): """Sets baseband center frequency and file name @@ -42,35 +51,42 @@ def set_center_freq(self, center_freq, rf_center_freq): self.file_name != None): self.blocks_wavfile_sink.close() - # If we never wrote any data to the wavfile sink, delete the file + # If we did not write enough data to the wavfile sink, delete the file self._delete_wavfile_if_empty() - # Set the frequency - self.freq_xlating_fir_filter_ccc.set_center_freq(center_freq) + # Set the frequency of the tuner self.center_freq = center_freq + self.freq_xlating_fir_filter_ccc.set_center_freq(self.center_freq) - # Set the file name - timestamp = int(time.time()) + # Set the file name if recording if self.center_freq == 0 or not self.record: # If tuner at zero Hz, or record false, then file name to None - file_name = None + self.file_name = None else: - # Otherwise use frequency and time stamp for file name - strtimestamp = "_" + str(timestamp) - file_freq = (rf_center_freq + self.center_freq)/1E6 - file_freq = np.round(file_freq, 3) - file_name = 'wav/' + '{:.3f}'.format(file_freq) + strtimestamp + ".wav" - - # Make sure the 'wav' directory exists - try: - os.mkdir('wav') - except OSError: # will need to add something here for Win support - pass # directory already exists - - if (file_name != None and self.record and self.file_name != None): - self.file_name = file_name + self.set_file_name(rf_center_freq) + + if (self.file_name != None and self.record): self.blocks_wavfile_sink.open(self.file_name) + self.active = True + + def set_file_name(self, rf_center_freq): + # Otherwise use frequency and time stamp for file name + timestamp = int(time.time()) + tstamp = time.strftime("%Y%m%d_%H%M%S", time.localtime()) + "{:.3f}".format(time.time()%1)[1:] + file_freq = (rf_center_freq + self.center_freq)/1E6 + file_freq = np.round(file_freq, 4) + file_name = 'wav/' + '{:.4f}'.format(file_freq) + "_" + tstamp + ".wav" + + # Make sure the 'wav' directory exists + # a better approach likely is checking existence instead of failing to create it + try: + os.mkdir('wav') + except OSError: # will need to add something here for Win support + pass # directory already exists + + self.file_name = file_name + # timestamp the demod update to match filename self.time_stamp = timestamp def _delete_wavfile_if_empty(self): @@ -84,6 +100,8 @@ def _delete_wavfile_if_empty(self): if os.stat(self.file_name).st_size < (self.min_file_size): os.unlink(self.file_name) # delete the file + self.active = False + def set_squelch(self, squelch_db): """Sets the threshold for both squelches @@ -222,17 +240,17 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, # Only want it to gate when the previous squelch has gone to zero analog_pwr_squelch_ff = analog.pwr_squelch_ff(-200, 1e-1, 0, True) + # Connect the blocks for recording + self.connect(pfb_arb_resampler_fff, analog_pwr_squelch_ff) + # File sink with single channel and bits/sample - if (self.file_name != None): + if (self.record): + self.set_file_name(self.center_freq) self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, - audio_rate, audio_bps, + audio_rate, blocks.FORMAT_WAV, blocks.FORMAT_PCM_16, False) - - # Connect the blocks for recording - self.connect(pfb_arb_resampler_fff, analog_pwr_squelch_ff) - if (self.file_name != None): self.connect(analog_pwr_squelch_ff, self.blocks_wavfile_sink) else: null_sink1 = blocks.null_sink(gr.sizeof_float) @@ -377,17 +395,17 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, # Only want it to gate when the previous squelch has gone to zero analog_pwr_squelch_ff = analog.pwr_squelch_ff(-200, 1e-1, 0, True) + # Connect the blocks for recording + self.connect(pfb_arb_resampler_fff, analog_pwr_squelch_ff) + # File sink with single channel and 8 bits/sample - if (self.file_name != None): + if (self.record): + self.set_file_name(self.center_freq) self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, - audio_rate, audio_bps, + audio_rate, blocks.FORMAT_WAV, blocks.FORMAT_PCM_16, False) - - # Connect the blocks for recording - self.connect(pfb_arb_resampler_fff, analog_pwr_squelch_ff) - if (self.file_name != None): self.connect(analog_pwr_squelch_ff, self.blocks_wavfile_sink) else: null_sink1 = blocks.null_sink(gr.sizeof_float) diff --git a/apps/scanner.py b/apps/scanner.py index 265da88..bb11d92 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -64,9 +64,14 @@ class Scanner(object): channel_log_timeout (int): Timeout delay between active channel entries in log audio_bps (int): Audio bit depth in bps (bits/samples) max_demod_length (int): Maximum demod time in seconds (0=disable) + freq_low (int): Freq below which we won't tune a receiver (Hz) + freq_high (int): Freq above which we won't tune a receiver (Hz) + spacing (int): granularity of frequency quantization Attributes: center_freq (float): Hardware RF center frequency in Hz + low_bound (int): Freq below which we won't tune a receiver (Hz) + high_bound (int): Freq above which we won't tune a receiver (Hz) samp_rate (float): Hardware sample rate in sps (1E6 min) gains : Enumerated gain types and values squelch_db (int): Squelch in dB @@ -95,7 +100,7 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, channel_log_file_name="", channel_log_timeout=15, play=True, audio_bps=8, max_demod_length=0, channel_spacing=5000, - min_file_size=0): + min_file_size=0, freq_low=0, freq_high=2000000000): # Default values self.squelch_db = -60 @@ -103,6 +108,9 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.threshold_db = 10 self.record = record self.play = play + self.audio_bps = audio_bps + self.freq_low = freq_low + self.freq_high = freq_high self.spectrum = [] self.lockout_channels = [] self.priority_channels = [] @@ -121,6 +129,9 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.log_mode = "" self.max_demod_length = max_demod_length self.min_file_size = min_file_size + self.low_bound = freq_low + self.high_bound = freq_high + self.hang_time = 1.0 # Create receiver object self.receiver = recvr.Receiver(ask_samp_rate, num_demod, type_demod, @@ -146,6 +157,14 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.center_freq = self.receiver.center_freq self.min_freq = (self.center_freq - self.samp_rate/2) self.max_freq = (self.center_freq + self.samp_rate/2) + # cannot set channel freq lower than min sampled freq + if (self.freq_low < self.min_freq): + self.freq_low = self.min_freq + # cannot set channel freq higher than max sampled freq + if (self.freq_high > self.max_freq): + self.freq_high = self.max_freq + self.low_bound = self.freq_low - self.center_freq + self.high_bound = self.freq_high - self.center_freq # Start the receiver and wait for samples to accumulate self.receiver.start() @@ -237,12 +256,18 @@ def scan_cycle(self): # Round channels to channel spacing # Note this affects tuning the demodulators # 5000 Hz is adequate for NBFM - channels = np.round(channels / self.channel_spacing) * self.channel_spacing + # Note that channel spacing is with respect to the center + baseband offset, + # not just the offset itself + real_channels = channels + self.center_freq + real_channels = np.round(real_channels / self.channel_spacing) * self.channel_spacing + channels = real_channels - self.center_freq # set active channels for gui highlight before filtering down lockout or adding priority active_channels = channels # Remove channels that are already in the priority list + # future, should find channels that are close too priority and replace with priority + # when less than channel_spacing separated from priority temp = [] for channel in channels: if channel not in self.priority_channels: @@ -263,17 +288,28 @@ def scan_cycle(self): pass channels = temp - # Set demodulators that are no longer in channel list to 0 Hz - #for demodulator in self.receiver.demodulators: + # Remove channels that are outside the requested freq range +# temp = [] +# for channel in channels: +# if channel > self.freq_low and channel < self.freq_high: +# temp = np.append(temp, channel) +# else: +# pass +# channels = temp + + # Update demodulator last heards and expire old ones + the_now = time.time() for idx in range(len(self.receiver.demodulators)): demodulator = self.receiver.demodulators[idx] if (demodulator.center_freq != 0) and (demodulator.center_freq not in channels): - demodulator.set_center_freq(0, self.center_freq) - # Write in channel log file that the channel is off - demodulator_freq = demodulator.center_freq - self.__print_channel_log__(demodulator_freq + self.center_freq, False, idx) + if the_now - demodulator.last_heard > self.hang_time: + demodulator.set_center_freq(0, self.center_freq) + # Write in channel log file that the channel is off + demodulator_freq = demodulator.center_freq + self.__print_channel_log__(demodulator_freq + self.center_freq, False, idx) else: - pass + #pass + demodulator.set_last_heard(the_now) # Add new channels to demodulators for channel in channels: @@ -448,6 +484,15 @@ def set_center_freq(self, center_freq): # reset min/max based on sample rate self.min_freq = (self.center_freq - self.samp_rate/2) self.max_freq = (self.center_freq + self.samp_rate/2) + # reset low/high based on new center and bounds + self.freq_low = self.low_bound - self.center_freq + self.freq_high = self.high_bound + self.center_freq + # cannot set channel freq lower than min sampled freq + if (self.freq_low < self.min_freq): + self.freq_low = self.min_freq + # cannot set channel freq higher than max sampled freq + if (self.freq_high > self.max_freq): + self.freq_high = self.max_freq # Update the priority since frequency is changing self.update_priority() @@ -525,7 +570,7 @@ def main(): priority_file_name = parser.priority_file_name channel_log_file_name = parser.channel_log_file_name audio_bps = parser.audio_bps - max_demo_length = parser.max_demod_length + max_demod_length = parser.max_demod_length channel_spacing = parser.channel_spacing min_file_size = parser.min_file_size scanner = Scanner(ask_samp_rate, num_demod, type_demod, hw_args, From f52a936847f7494a306d9899d3f458affec8387d Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 2 Apr 2022 12:46:58 -0600 Subject: [PATCH 35/41] updated change log history including miweber67 contribution captured modified: ../README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 05a2717..239d816 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,10 @@ lordmorgul: - pulled gain corrections to python3 version from john - defined max file size to save from command line option - channel width configurable from command line option +- incorporate miweber67 freq range limits + +miweber67 +- frequency range to limit selected channels to within specific limit john-: - long running file end (demodulator run time limit) @@ -165,6 +169,9 @@ Active channels are flagged as active periodically based on the active channel l ` -f CENTER_FREQ, --freq=CENTER_FREQ` ` Hardware RF center frequency in Hz` +` -e RANGE, --range=RANGE` +` Limit reception to specified range, xx-yy in Hz` + ` -r ASK_SAMP_RATE, --rate=ASK_SAMP_RATE` ` Hardware ask sample rate in sps (1E6 minimum)` @@ -227,6 +234,7 @@ Active channels are flagged as active periodically based on the active channel l ` Minimum size file to save in bytes, default 0 (save all)` + ## Description: The high speed signal processing is done in GR and the logic & control in Python. There are no custom GR blocks. The GUI is written in Curses and is meant to be lightweight. See the video for a basic overview. I attempted to make the program very object oriented and “Pythonic”. Each module runs on it's own for testing purposes. From 10e50426a1b737981e42f10e6c2657ee6d953da7 Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 2 Apr 2022 14:05:00 -0600 Subject: [PATCH 36/41] Added center_freq to constructor params for Scanner to provide ability to calculate desired low and high freq tuning bounds with given low_freq and high_freq Fixed error in Scanner test code from old gain code upgrades Edited ham2mon to add new param Fixed logic of removing channels that are below low_bound and above high_bound modified: ham2mon.py modified: scanner.py --- apps/ham2mon.py | 5 +++-- apps/scanner.py | 53 ++++++++++++++++++++++++++++++------------------- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/apps/ham2mon.py b/apps/ham2mon.py index b0262b9..8ee2d09 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -60,6 +60,7 @@ def main(screen): max_demod_length = PARSER.max_demod_length channel_spacing = PARSER.channel_spacing min_file_size = PARSER.min_file_size + center_freq = PARSER.center_freq freq_low = PARSER.freq_low freq_high = PARSER.freq_high @@ -67,10 +68,10 @@ def main(screen): freq_correction, record, lockout_file_name, priority_file_name, channel_log_file_name, channel_log_timeout, play, audio_bps, max_demod_length, channel_spacing, min_file_size, - freq_low, freq_high) + center_freq, freq_low, freq_high) # Set the paramaters - scanner.set_center_freq(PARSER.center_freq) + scanner.set_center_freq(center_freq) scanner.set_squelch(PARSER.squelch_db) scanner.set_volume(PARSER.volume_db) diff --git a/apps/scanner.py b/apps/scanner.py index bb11d92..bc18806 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -64,6 +64,7 @@ class Scanner(object): channel_log_timeout (int): Timeout delay between active channel entries in log audio_bps (int): Audio bit depth in bps (bits/samples) max_demod_length (int): Maximum demod time in seconds (0=disable) + center_freq (int): initial center frequency for receiver (Hz) freq_low (int): Freq below which we won't tune a receiver (Hz) freq_high (int): Freq above which we won't tune a receiver (Hz) spacing (int): granularity of frequency quantization @@ -100,7 +101,7 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, channel_log_file_name="", channel_log_timeout=15, play=True, audio_bps=8, max_demod_length=0, channel_spacing=5000, - min_file_size=0, freq_low=0, freq_high=2000000000): + min_file_size=0, center_freq=0, freq_low=0, freq_high=2000000000): # Default values self.squelch_db = -60 @@ -111,6 +112,7 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.audio_bps = audio_bps self.freq_low = freq_low self.freq_high = freq_high + self.center_freq = center_freq self.spectrum = [] self.lockout_channels = [] self.priority_channels = [] @@ -139,6 +141,9 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, audio_bps, min_file_size) + # Set the initial center frequency here to allow setting min/max and low/high bounds + self.receiver.set_center_freq(center_freq) + # Open channel log file for appending data, if it is specified if channel_log_file_name != "": self.channel_log_file = open(channel_log_file_name, 'a') @@ -147,12 +152,12 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, else: # Opening log file failed so cannot perform this log mode # Either raise exception or continue without logging, second preferable - self.log_mode = "" + self.log_mode = "none" #raise(LogError("file","Cannot open log file")) else: self.channel_log_file = None - # Get the hardware sample rate and center frequency + # Get the hardware sample rate and center frequency in Hz self.samp_rate = self.receiver.samp_rate self.center_freq = self.receiver.center_freq self.min_freq = (self.center_freq - self.samp_rate/2) @@ -178,7 +183,7 @@ def __del__(self): self.channel_log_file.close() def __print_channel_log_active__(self, freq, state): - if self.log_mode is not None and state is True: + if self.log_mode is not None and self.log_mode != "none" and state is True: state_str = {True: "act", False: "off"} now = datetime.datetime.now() if self.log_mode == "file" and self.channel_log_file is not None: @@ -199,7 +204,7 @@ def __print_channel_log_active__(self, freq, state): raise(err.LogError("unknown","no log mode defined")) def __print_channel_log__(self, freq, state, idx): - if self.log_mode is not None: + if self.log_mode is not None and self.log_mode != "none": state_str = {True: "on", False: "off"} if state == False: freq = 0 @@ -289,13 +294,13 @@ def scan_cycle(self): channels = temp # Remove channels that are outside the requested freq range -# temp = [] -# for channel in channels: -# if channel > self.freq_low and channel < self.freq_high: -# temp = np.append(temp, channel) -# else: -# pass -# channels = temp + temp = [] + for channel in channels: + if channel > self.low_bound and channel < self.high_bound: + temp = np.append(temp, channel) + else: + pass + channels = temp # Update demodulator last heards and expire old ones the_now = time.time() @@ -345,25 +350,26 @@ def scan_cycle(self): # reset the demodulator to its frequency to restart file demodulator.set_center_freq(0, temp_freq) - # Create an tuned channel list of strings for the GUI + # Create an tuned channel list of strings for the GUI in MHz # If channel is a zero then use an empty string self.gui_tuned_channels = [] for demod_freq in self.receiver.get_demod_freqs(): if demod_freq == 0: text = "" else: - # Calculate actual RF frequency + # Calculate actual RF frequency in MHz gui_tuned_channel = (demod_freq + \ self.center_freq)/1E6 text = '{:.3f}'.format(gui_tuned_channel) self.gui_tuned_channels.append(text) - # Create an active channel list of strings for the GUI + # Create an active channel list of strings for the GUI in MHz # This is any channel above threshold # do not include priority if not above threshold # do include lockout if above threshold self.gui_active_channels = [] for channel in active_channels: + # calculate active channel freq in MHz gui_active_channel = (channel + self.center_freq)/1E6 text = '{:.3f}'.format(gui_active_channel) self.gui_active_channels.append(text) @@ -402,9 +408,10 @@ def add_lockout(self, idx): self.lockout_channels = np.append(self.lockout_channels, demod_freq) - # Create a lockout channel list of strings for the GUI + # Create a lockout channel list of strings for the GUI in MHz self.gui_lockout_channels = [] for lockout_channel in self.lockout_channels: + # lockout channel in MHz gui_lockout_channel = (lockout_channel + \ self.receiver.center_freq)/1E6 text = '{:.3f}'.format(gui_lockout_channel) @@ -435,9 +442,10 @@ def clear_lockout(self): else: pass - # Create a lockout channel list of strings for the GUI + # Create a lockout channel list of strings for the GUI in MHz self.gui_lockout_channels = [] for lockout_channel in self.lockout_channels: + # lockout channel in MHz gui_lockout_channel = (lockout_channel + \ self.receiver.center_freq)/1E6 text = '{:.3f}'.format(gui_lockout_channel) @@ -459,6 +467,7 @@ def update_priority(self): lines = builtins.filter(None, lines) else: lines = __builtin__.filter(None, lines) + # Convert to baseband frequencies, round, and append if within BW for freq in lines: bb_freq = float(freq) - self.center_freq @@ -473,6 +482,7 @@ def update_priority(self): def set_center_freq(self, center_freq): """Sets RF center frequency of hardware and clears lockout channels + Sets low and high demod frequency limits based on provided bounds in command line Args: center_freq (float): Hardware RF center frequency in Hz @@ -484,7 +494,7 @@ def set_center_freq(self, center_freq): # reset min/max based on sample rate self.min_freq = (self.center_freq - self.samp_rate/2) self.max_freq = (self.center_freq + self.samp_rate/2) - # reset low/high based on new center and bounds + # reset low/high freq for demod based on new center and bounds from original provided self.freq_low = self.low_bound - self.center_freq self.freq_high = self.high_bound + self.center_freq # cannot set channel freq lower than min sampled freq @@ -573,17 +583,20 @@ def main(): max_demod_length = parser.max_demod_length channel_spacing = parser.channel_spacing min_file_size = parser.min_file_size + center_freq = parser.center_freq + freq_low = parser.freq_low + freq_high = parser.freq_high scanner = Scanner(ask_samp_rate, num_demod, type_demod, hw_args, freq_correction, record, lockout_file_name, priority_file_name, channel_log_file_name, audio_bps, max_demod_length, channel_spacing, - min_file_size) + min_file_size, center_freq, freq_low, freq_high) # Set frequency, gain, squelch, and volume scanner.set_center_freq(parser.center_freq) print("\n") print("Started %s at %.3f Msps" % (hw_args, scanner.samp_rate/1E6)) - print("RX at %.3f MHz with %d dB gain" % (scanner.center_freq/1E6)) + print("RX at %.3f MHz" % (scanner.center_freq/1E6)) scanner.filter_and_set_gains(parser.gains) for gain in scanner.gains: print("gain %s at %d dB" % (gain["name"], gain["value"])) From 6d5a8ea6dc640977d85c10f32abc365e8130e2ba Mon Sep 17 00:00:00 2001 From: Andrew Farris Date: Sat, 9 Apr 2022 00:37:07 -0500 Subject: [PATCH 37/41] Clean personally relevant freqs out of priority examples, GMRS channels only, calling channels only in vhf for 2m and uhf for 70cm examples --- apps/priority-gmrs | 1 - apps/priority-gmrsri | 1 - apps/priority-uhf | 10 +--------- apps/priority-vhf | 11 +---------- 4 files changed, 2 insertions(+), 21 deletions(-) diff --git a/apps/priority-gmrs b/apps/priority-gmrs index c8ff06b..482c457 100644 --- a/apps/priority-gmrs +++ b/apps/priority-gmrs @@ -1,4 +1,3 @@ -462562500 462550000 462575000 462600000 diff --git a/apps/priority-gmrsri b/apps/priority-gmrsri index ade92e4..3d22f38 100644 --- a/apps/priority-gmrsri +++ b/apps/priority-gmrsri @@ -1,4 +1,3 @@ -467562500 467550000 467575000 467600000 diff --git a/apps/priority-uhf b/apps/priority-uhf index 2884b5b..9183cf5 100644 --- a/apps/priority-uhf +++ b/apps/priority-uhf @@ -1,10 +1,2 @@ -440560000 -440600000 -441400000 -441840000 -444575000 -445560000 -445600000 -445840000 +444000000 446000000 -446400000 diff --git a/apps/priority-vhf b/apps/priority-vhf index 62f611f..ab6b77e 100644 --- a/apps/priority-vhf +++ b/apps/priority-vhf @@ -1,11 +1,2 @@ -145380000 -145980000 -146130000 -146190000 -146265000 -146420000 146520000 -146730000 -146790000 -146865000 -147270000 +146900000 From 9866eec4a01ec0c961b1868b733e174804489498 Mon Sep 17 00:00:00 2001 From: john <4852923-john---@users.noreply.gitlab.com> Date: Mon, 6 Nov 2023 08:56:01 -0600 Subject: [PATCH 38/41] fixed freq_low --- apps/scanner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/scanner.py b/apps/scanner.py index bc18806..1f3111b 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -495,7 +495,7 @@ def set_center_freq(self, center_freq): self.min_freq = (self.center_freq - self.samp_rate/2) self.max_freq = (self.center_freq + self.samp_rate/2) # reset low/high freq for demod based on new center and bounds from original provided - self.freq_low = self.low_bound - self.center_freq + self.freq_low = self.low_bound + self.center_freq self.freq_high = self.high_bound + self.center_freq # cannot set channel freq lower than min sampled freq if (self.freq_low < self.min_freq): From 96068bd9421f5dc63ce28da56b2bf8bb4d521983 Mon Sep 17 00:00:00 2001 From: john <4852923-john---@users.noreply.gitlab.com> Date: Tue, 7 Nov 2023 13:43:40 -0600 Subject: [PATCH 39/41] testing note --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 239d816..c47b54e 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Recent development and tests on Python3: - NooElec RTL2832 + R820T at 2 Msps (http://www.nooelec.com) - GNU Radio 3.8.2.0 (https://github.com/gnuradio/gnuradio) - GrOsmoSDR 0.1.4-29 (http://sdr.osmocom.org/trac/wiki/GrOsmoSDR) +- Airspy Mini (https://airspy.com/airspy-mini/) - Python 3.8.6 Previous version tests: From 50f4d7f6ab03782f02252a9d3d27b6475d859bb6 Mon Sep 17 00:00:00 2001 From: john <4852923-john---@users.noreply.gitlab.com> Date: Mon, 13 Nov 2023 08:51:11 -0600 Subject: [PATCH 40/41] remove unused code --- apps/receiver.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/receiver.py b/apps/receiver.py index 6875e3d..bcdc69c 100755 --- a/apps/receiver.py +++ b/apps/receiver.py @@ -28,7 +28,6 @@ class BaseTuner(gr.hier_block2): def __init__(self): # Default values self.last_heard = 0 - self.active = False self.file_name = None def set_last_heard(self, a_time): @@ -68,8 +67,6 @@ def set_center_freq(self, center_freq, rf_center_freq): if (self.file_name != None and self.record): self.blocks_wavfile_sink.open(self.file_name) - self.active = True - def set_file_name(self, rf_center_freq): # Otherwise use frequency and time stamp for file name timestamp = int(time.time()) @@ -100,8 +97,6 @@ def _delete_wavfile_if_empty(self): if os.stat(self.file_name).st_size < (self.min_file_size): os.unlink(self.file_name) # delete the file - self.active = False - def set_squelch(self, squelch_db): """Sets the threshold for both squelches From a059c00fa6deadb62abbf3b110f4b968d10a6e5b Mon Sep 17 00:00:00 2001 From: lordmorgul Date: Sun, 4 Feb 2024 01:12:02 -0600 Subject: [PATCH 41/41] Priority demod assignment (#18) priority scanning algorithm change, scanner.py significantly changed, few remaining bugs (currently crashes with a list access error, but saving work done) modified: receiver.py modified: scanner.py debugging new scan priority, added modules for traceback and sys calls corrections to priority channel handling :w Changes to be committed: modified: ham2mon.py modified: receiver.py modified: scanner.py --- apps/ham2mon.py | 51 ++++++++- apps/receiver.py | 44 +++++--- apps/scanner.py | 264 ++++++++++++++++++++++++++++++----------------- 3 files changed, 244 insertions(+), 115 deletions(-) diff --git a/apps/ham2mon.py b/apps/ham2mon.py index 8ee2d09..9b8d1d6 100755 --- a/apps/ham2mon.py +++ b/apps/ham2mon.py @@ -12,6 +12,24 @@ import parser import time import errors as err +import traceback +import sys +import os +from datetime import datetime + +def print_custom_error_message(): + exc_type, exc_value, exc_tb = sys.exc_info() + stack_summary = traceback.extract_tb(exc_tb) + end = stack_summary[-1] + + err_type = type(exc_value).__name__ + err_msg = str(exc_value) + date = datetime.strftime(datetime.now(), "%B %d, %Y at precisely %I:%M %p") + + print(f"On {date}, a {err_type} occured in {end.filename} inside {end.name} on line {end.lineno} with the error message: {err_msg}.") + print(f"The following line of code is responsible: {end.line!r}") + print("Please make a note of it.") + print("") def main(screen): """Start scanner with GUI interface @@ -157,7 +175,7 @@ def main(screen): # cleanup terminating all demodulators for demod in scanner.receiver.demodulators: - demod.set_center_freq(0, 0); + demod.set_tuner_freq(0, 0); if __name__ == '__main__': try: @@ -176,18 +194,49 @@ def main(screen): print("") print("RuntimeError: {err=}, {type(err)=}") print("") + print(traceback.format_exc) + print(sys.exc_info()[2]) + print("") + + print_custom_error_message() + except err.LogError: print("") print("LogError: database logging not active, to be expanded.") print("") + print(traceback.format_exc) + print(sys.exc_info()[2]) + print("") + + print_custom_error_message() + except OSError as err: print("") print("OS error: {0}".format(err)) print("") + print(traceback.format_exc) + print(sys.exc_info()[2]) + print("") + + print_custom_error_message() + + #exc_type, exc_obj, exc_tb = sys.exc_info() + #fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] + #print(exc_type, fname, exc_tb.tb_lineno) + except BaseException as err: print("") print("Unexpected: {err=}, {type(err)=}", err, type(err)) print("") + print(traceback.format_exc) + print(sys.exc_info()[2]) + print("") + + print_custom_error_message() + + #exc_type, exc_obj, exc_tb = sys.exc_info() + #fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] + #print(exc_type, fname, exc_tb.tb_lineno) finally: # --- Cleanup on exit --- diff --git a/apps/receiver.py b/apps/receiver.py index bcdc69c..e066893 100755 --- a/apps/receiver.py +++ b/apps/receiver.py @@ -30,10 +30,13 @@ def __init__(self): self.last_heard = 0 self.file_name = None + def get_last_heard(): + return self.last_heard + def set_last_heard(self, a_time): self.last_heard = a_time - def set_center_freq(self, center_freq, rf_center_freq): + def set_tuner_freq(self, tuner_freq, rf_center_freq): """Sets baseband center frequency and file name Sets baseband center frequency of frequency translating FIR filter @@ -42,7 +45,7 @@ def set_center_freq(self, center_freq, rf_center_freq): Otherwise set file name to tuned RF frequency in MHz Args: - center_freq (float): Baseband center frequency in Hz + tuner_freq (float): Baseband tuner frequency in Hz rf_center_freq (float): RF center in Hz (for file name) """ # Since the frequency (hence file name) changed, then close it @@ -54,11 +57,12 @@ def set_center_freq(self, center_freq, rf_center_freq): self._delete_wavfile_if_empty() # Set the frequency of the tuner - self.center_freq = center_freq - self.freq_xlating_fir_filter_ccc.set_center_freq(self.center_freq) + self.tuner_freq = tuner_freq + self.rf_center_freq = rf_center_freq + self.freq_xlating_fir_filter_ccc.set_center_freq(self.tuner_freq) # Set the file name if recording - if self.center_freq == 0 or not self.record: + if self.tuner_freq == 0 or not self.record: # If tuner at zero Hz, or record false, then file name to None self.file_name = None else: @@ -68,10 +72,11 @@ def set_center_freq(self, center_freq, rf_center_freq): self.blocks_wavfile_sink.open(self.file_name) def set_file_name(self, rf_center_freq): + self.rf_center_freq = rf_center_freq # Otherwise use frequency and time stamp for file name timestamp = int(time.time()) tstamp = time.strftime("%Y%m%d_%H%M%S", time.localtime()) + "{:.3f}".format(time.time()%1)[1:] - file_freq = (rf_center_freq + self.center_freq)/1E6 + file_freq = (self.rf_center_freq + self.tuner_freq)/1E6 file_freq = np.round(file_freq, 4) file_name = 'wav/' + '{:.4f}'.format(file_freq) + "_" + tstamp + ".wav" @@ -160,13 +165,15 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, gr.io_signature(1, 1, gr.sizeof_float)) # Default values - self.center_freq = 0 + self.tuner_freq = 0 + self.rf_center_freq = 0 self.time_stamp = 0 squelch_db = -60 self.quad_demod_gain = 0.050 self.file_name = None self.record = record self.min_file_size = min_file_size + self.last_heard = 0 # Decimation values for four stages of decimation decims = (5, int(samp_rate/1E6)) @@ -180,7 +187,7 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, self.freq_xlating_fir_filter_ccc = \ grfilter.freq_xlating_fir_filter_ccc(decims[0], low_pass_filter_taps_0, - self.center_freq, samp_rate) + self.tuner_freq, samp_rate) # FIR filter decimating by 5 fir_filter_ccc_0 = grfilter.fir_filter_ccc(decims[0], @@ -240,7 +247,7 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, # File sink with single channel and bits/sample if (self.record): - self.set_file_name(self.center_freq) + self.set_file_name(self.tuner_freq) self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, audio_rate, blocks.FORMAT_WAV, @@ -295,7 +302,8 @@ class TunerDemodAM(BaseTuner): min_file_size (int): Minimum saved wav file size Attributes: - center_freq (float): Baseband center frequency in Hz + tuner_freq (float): Baseband center frequency in Hz + rf_center_freq (float): RF center frequency in Hz record (bool): Record audio to file if True time_stamp (int): Time stamp of demodulator start for timing run length """ @@ -309,13 +317,15 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, gr.io_signature(1, 1, gr.sizeof_float)) # Default values - self.center_freq = 0 + self.tuner_freq = 0 + self.rf_center_freq = 0 self.time_stamp = 0 squelch_db = -60 self.agc_ref = 0.1 self.file_name = None self.record = record self.min_file_size = min_file_size + self.last_heard = 0 # Decimation values for four stages of decimation @@ -330,7 +340,7 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, self.freq_xlating_fir_filter_ccc = \ grfilter.freq_xlating_fir_filter_ccc(decims[0], low_pass_filter_taps_0, - self.center_freq, samp_rate) + self.tuner_freq, samp_rate) # FIR filter decimating by 5 fir_filter_ccc_0 = grfilter.fir_filter_ccc(decims[0], @@ -395,7 +405,7 @@ def __init__(self, samp_rate=4E6, audio_rate=8000, record=True, # File sink with single channel and 8 bits/sample if (self.record): - self.set_file_name(self.center_freq) + self.set_file_name(self.tuner_freq, self.rf_center_freq) self.blocks_wavfile_sink = blocks.wavfile_sink(self.file_name, 1, audio_rate, blocks.FORMAT_WAV, @@ -609,10 +619,10 @@ def get_demod_freqs(self): Returns: List[float]: List of baseband center frequencies in Hz """ - center_freqs = [] + tuner_freqs = [] for demodulator in self.demodulators: - center_freqs.append(demodulator.center_freq) - return center_freqs + tuner_freqs.append(demodulator.tuner_freq) + return tuner_freqs def main(): @@ -662,7 +672,7 @@ def main(): # Tune demodulators to baseband channels # If recording on, this creates empty wav file since manually tuning. for idx, demodulator in enumerate(receiver.demodulators): - demodulator.set_center_freq(channels[idx], center_freq) + demodulator.set_tuner_freq(channels[idx], center_freq) # Print demodulator info for idx, channel in enumerate(channels): diff --git a/apps/scanner.py b/apps/scanner.py index 1f3111b..d90a370 100755 --- a/apps/scanner.py +++ b/apps/scanner.py @@ -117,6 +117,10 @@ def __init__(self, ask_samp_rate=4E6, num_demod=4, type_demod=0, self.lockout_channels = [] self.priority_channels = [] self.active_channels = [] + self.unordered_active_channels = [] + self.ordered_active_channels = [] + self.power_ordered_active_channels = [] + self.ordered_active_channels_freqs = [] self.gui_tuned_channels = [] self.gui_active_channels = [] self.gui_lockout_channels = [] @@ -242,115 +246,173 @@ def scan_cycle(self): """ # pylint: disable=too-many-branches - # Retune demodulators that are locked out - for demodulator in self.receiver.demodulators: - if demodulator.center_freq in self.lockout_channels: - demodulator.set_center_freq(0, self.center_freq) - else: - pass - - # Grab the FFT data, set threshold, and estimate baseband channels + # Grab the FFT data, set threshold, and estimate baseband signal centers for defining channels self.spectrum = self.receiver.probe_signal_vf.level() threshold = 10**(self.threshold_db/10.0) - channels = np.array(estimate.channel_estimate(self.spectrum, threshold)) + signal_bins = np.array(estimate.channel_estimate(self.spectrum, threshold)) - # Convert channels from bin indices to baseband frequency in Hz - channels = (channels-len(self.spectrum)/2)*\ - self.samp_rate/len(self.spectrum) + # Convert detected signal peaks from bin indices to baseband frequency in Hz + signal_freqs = (signal_bins - len(self.spectrum)/2) * self.samp_rate / len(self.spectrum) + + # keep signal power with each channel for scanner prioritization (close call priority) + signal_powers = [] + for bindx in range(len(signal_bins)): + signal_powers.append(self.spectrum[bindx]) # Round channels to channel spacing # Note this affects tuning the demodulators # 5000 Hz is adequate for NBFM # Note that channel spacing is with respect to the center + baseband offset, # not just the offset itself - real_channels = channels + self.center_freq - real_channels = np.round(real_channels / self.channel_spacing) * self.channel_spacing - channels = real_channels - self.center_freq + + # TODO should find channels that are less than half channel-spacing away from a provided priority channel + # and replace with priority channel center rather than fixed spacings + #signal_channelized = signal_freqs + self.center_freq + #signal_channelized = np.round(signal_channels / self.channel_spacing) * self.channel_spacing + #signal_channelized = signal_channels - self.center_freq + # in baseband + signal_channels = [] + for fidx in range(len(signal_freqs)): + signal_channels.append(np.round(signal_freqs[fidx] / self.channel_spacing) * self.channel_spacing) + # signal_channels.append((np.round((signal_freqs[fidx] + self.center_freq) / self.channel_spacing) \ + # + self.channel_spacing) - self.center_freq) # set active channels for gui highlight before filtering down lockout or adding priority - active_channels = channels - - # Remove channels that are already in the priority list - # future, should find channels that are close too priority and replace with priority - # when less than channel_spacing separated from priority - temp = [] - for channel in channels: - if channel not in self.priority_channels: - temp = np.append(temp, channel) - else: - pass - channels = temp + # TODO revisit how gui highlights active vs priority, use tuple to inform channel, pwr, type(priority/continuing/closecall/regular) + # in baseband + self.active_channels = signal_channels - # Put the priority channels in front - channels = np.append(self.priority_channels, channels) + # + #sys.stderr.write("\n\n ** gothere **\n\n") + # - # Remove channels that are locked out - temp = [] - for channel in channels: - if channel not in self.lockout_channels: - temp = np.append(temp, channel) - else: - pass - channels = temp + # create list of tuples for bin index, channel frequency, channel power, channel type + # channel type will be enum (priority, continuing, close, normal) + # priority = in priority list from file + # continuing = demod already assigned, signal continues + # close = power more than YYdb above threshold (this is future revision, nothing done for close currently, YY undefined) + # new = power above threshold + + channel_type = ["priority", "continuing", "new"] + channel_type_gui = ["+", " ", "^"] + + # empty list of tuples + # channels_tuple_key = ("index", "signal frequency channel", "signal power", "spectrum bin") + # in baseband + self.unordered_active_channels = [] + for idx in range(len(signal_channels)): + self.unordered_active_channels.append((idx,signal_channels[idx],signal_powers[idx],signal_bins[idx])) + + self.ordered_active_channels = [] + # Remove channels that are locked out # Remove channels that are outside the requested freq range - temp = [] - for channel in channels: - if channel > self.low_bound and channel < self.high_bound: - temp = np.append(temp, channel) - else: - pass - channels = temp + for a_chan in self.unordered_active_channels: + if a_chan[1] in self.lockout_channels or a_chan[1] < self.low_bound or a_chan[1] > self.high_bound: + self.unordered_active_channels.remove(a_chan) + + # Put the channels in priority order + # 1 - channels in priority list + # 2 - channels already being monitored that are still active + # 3 - new channels in highest power order + + # 1 - channels in the priority list + # Check active channels for any priority channels + # Check in priority channel order to insure we select higher + # priority channels over lower priority channels per file order + for a_chan in self.unordered_active_channels: + if a_chan[1] in self.priority_channels: + self.ordered_active_channels.append((a_chan[0], a_chan[1], a_chan[2], a_chan[3], channel_type[0], channel_type_gui[0])) + self.unordered_active_channels.remove(a_chan) + + # 2 - channels already being monitored + active_demods = [freq for freq in self.receiver.get_demod_freqs() if freq > 0] + # check on-going signals + for a_chan in self.unordered_active_channels: + if a_chan[1] in active_demods: + self.ordered_active_channels.append((a_chan[0], a_chan[1], a_chan[2], a_chan[3], channel_type[1], channel_type_gui[1])) + self.unordered_active_channels.remove(a_chan) + + # 3 - new channels in highest power order + # take remaining unordered channels, get spectrum power for that channel freq, and reorder + + # for sorting the channel tuples by power level, list.sort(reverse=True,key=sortPwr) + # the sortPwr function returns the third element of the tuple, which is signal power + + self.power_ordered_active_channels = sorted(self.unordered_active_channels, key=lambda a: a[1], reverse=True) + + for a_chan in self.power_ordered_active_channels: + self.ordered_active_channels.append((a_chan[0], a_chan[1], a_chan[2], a_chan[3], channel_type[2], channel_type_gui[2])) + self.unordered_active_channels.remove(a_chan) + self.power_ordered_active_channels.remove(a_chan) + + # channels are ordered + # from this point on we work with ordered_active_channels as channel tuples + # but a simple list of the ordered frequencies is faster for several operations remaining + self.ordered_active_channels_freqs = [] + for a_chan in self.ordered_active_channels: + self.ordered_active_channels_freqs.append(a_chan[1]) # Update demodulator last heards and expire old ones the_now = time.time() - for idx in range(len(self.receiver.demodulators)): - demodulator = self.receiver.demodulators[idx] - if (demodulator.center_freq != 0) and (demodulator.center_freq not in channels): - if the_now - demodulator.last_heard > self.hang_time: - demodulator.set_center_freq(0, self.center_freq) - # Write in channel log file that the channel is off - demodulator_freq = demodulator.center_freq - self.__print_channel_log__(demodulator_freq + self.center_freq, False, idx) + for idx, demod in enumerate(self.receiver.demodulators): + if (demod.tuner_freq != 0) and (demod.tuner_freq not in self.ordered_active_channels_freqs): + if the_now - demod.last_heard > self.hang_time: + demod.set_tuner_freq(0, self.center_freq) else: - #pass - demodulator.set_last_heard(the_now) - - # Add new channels to demodulators - for channel in channels: - # If channel not in demodulators - if channel not in self.receiver.get_demod_freqs(): - # Sequence through each demodulator - #for demodulator in self.receiver.demodulators: - for idx in range(len(self.receiver.demodulators)): - demodulator = self.receiver.demodulators[idx] - # If demodulator is empty and channel not already there - if (demodulator.center_freq == 0) and \ - (channel not in self.receiver.get_demod_freqs()): - # Write in channel log file that the channel is on - self.__print_channel_log__(channel + self.center_freq, True, idx) - # Assigning channel to empty demodulator - demodulator.set_center_freq(channel, self.center_freq) - break - - else: - pass - else: - pass - - # Stop any long running demodulators - if self.max_demod_length > 0: - for demodulator in self.receiver.demodulators: - if (demodulator.time_stamp > 0) and \ - (int(time.time()) - demodulator.time_stamp > \ - self.max_demod_length): - temp_freq = demodulator.center_freq - # clear the demodulator to reset file - demodulator.set_center_freq(0, self.center_freq) - # reset the demodulator to its frequency to restart file - demodulator.set_center_freq(0, temp_freq) - - # Create an tuned channel list of strings for the GUI in MHz + # maintain active demod + demod.set_last_heard(the_now) + # Write in channel log file that the channel is off + self.__print_channel_log__(demod.tuner_freq + self.center_freq, False, idx) + + # priority relative to this round of assignments only + demod_priority = [99999] * len(self.receiver.demodulators) + + # mark demodulators already servicing active channels with their relative priority + # priority is index of ordered channels, lower is better + active_channel_covered_flags= [False] * len(self.ordered_active_channels) + for idx, a_chan in enumerate(self.ordered_active_channels): + for jdx, demod in enumerate(self.receiver.demodulators): + if demod.tuner_freq == a_chan[1]: + demod_priority[jdx] = idx + active_channel_covered_flags[idx] = True + + # assign uncovered channels to demodulators in priority order + # should stop this when reaching the max num of demodulators, do not keep replacing last lowest priority + # the lowest priority channel that can be serviced will be the max number of demodulators + num_demod = len(self.receiver.demodulators) + for idx, a_chan in enumerate(self.ordered_active_channels): + if not active_channel_covered_flags[idx] and idx <= num_demod: + # locate lowest prio demod available, with priority lower than current channel priority idx + # low priority is a high priority value, because ordered channel indexes are used as priorities (1 is highest priority) + lowest_prio_demod_idx = -1 + lowest_prio_demod_prio = idx + for kdx, demod in enumerate(self.receiver.demodulators): + if demod_priority[kdx] > lowest_prio_demod_prio: + lowest_prio_demod_prio = demod_priority[kdx] + lowest_prio_demod_idx = kdx + lowest_prio_demod = demod + + # if a lower priority demod was found, replace it with current idx ordered channel, else cannot service this channel + if (lowest_prio_demod_prio > idx): + lowest_prio_demod.set_tuner_freq(a_chan[1], self.center_freq) + active_channel_covered_flags[idx] = True + demod_priority[lowest_prio_demod_idx] = idx + else: + break + + # this resets demodulators to the same frequency when running length is exceeded, which is a file size control + for demod in self.receiver.demodulators: + if demod.time_stamp > 0 and \ + time.time() - demod.time_stamp > \ + self.max_demod_length: + temp_freq = demod.tuner_freq + # clear the demod to reset file + demod.set_tuner_freq(0, self.center_freq) + # reset the demod to its frequency to restart file + demod.set_tuner_freq(temp_freq, self.center_freq) + + # Create tuned channel list of strings for the GUI in MHz # If channel is a zero then use an empty string self.gui_tuned_channels = [] for demod_freq in self.receiver.get_demod_freqs(): @@ -358,17 +420,18 @@ def scan_cycle(self): text = "" else: # Calculate actual RF frequency in MHz - gui_tuned_channel = (demod_freq + \ - self.center_freq)/1E6 + gui_tuned_channel = (demod_freq + self.center_freq)/1E6 text = '{:.3f}'.format(gui_tuned_channel) self.gui_tuned_channels.append(text) - # Create an active channel list of strings for the GUI in MHz + # Should there be a priority active channel list for GUI? could display other color when priority channel is active versus normal active + + # Create active channel list of strings for the GUI in MHz # This is any channel above threshold # do not include priority if not above threshold - # do include lockout if above threshold + # do include lockout if above threshold, this would highlight the active lockout freq for visual info only self.gui_active_channels = [] - for channel in active_channels: + for channel in self.active_channels: # calculate active channel freq in MHz gui_active_channel = (channel + self.center_freq)/1E6 text = '{:.3f}'.format(gui_active_channel) @@ -403,11 +466,18 @@ def add_lockout(self, idx): # Check to make sure index is within the number of demodulators if idx < len(self.receiver.demodulators): # Lockout if not zero and not already locked out - demod_freq = self.receiver.demodulators[idx].center_freq + demod_freq = self.receiver.demodulators[idx].tuner_freq if (demod_freq != 0) and (demod_freq not in self.lockout_channels): self.lockout_channels = np.append(self.lockout_channels, demod_freq) + # Retune demodulators that are locked out + for demod in self.receiver.demodulators: + if demod.tuner_freq in self.lockout_channels: + demod.set_tuner_freq(0, self.center_freq) + else: + pass + # Create a lockout channel list of strings for the GUI in MHz self.gui_lockout_channels = [] for lockout_channel in self.lockout_channels: @@ -593,7 +663,7 @@ def main(): min_file_size, center_freq, freq_low, freq_high) # Set frequency, gain, squelch, and volume - scanner.set_center_freq(parser.center_freq) + scanner.set_center_freq(center_freq) print("\n") print("Started %s at %.3f Msps" % (hw_args, scanner.samp_rate/1E6)) print("RX at %.3f MHz" % (scanner.center_freq/1E6))