From 6c7fb8a8e93b79b13c80a5ce0256ae3190ca53d2 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Thu, 18 Jul 2019 16:47:20 +0200 Subject: Add PSK125 decoder script --- decoder/README.md | 21 + decoder/analyse_capture.grc | 1676 +++++++++++++++++++++++++++++++++++++++++++ decoder/analyse_capture.py | 132 ++++ decoder/varidecode.py | 113 +++ 4 files changed, 1942 insertions(+) create mode 100644 decoder/README.md create mode 100644 decoder/analyse_capture.grc create mode 100755 decoder/analyse_capture.py create mode 100755 decoder/varidecode.py (limited to 'decoder') diff --git a/decoder/README.md b/decoder/README.md new file mode 100644 index 0000000..6ca6b9a --- /dev/null +++ b/decoder/README.md @@ -0,0 +1,21 @@ +Introduction +------------ + +This folder contains a set of scripts that can be used to automatically decode the PSK125 beacon at 22:00 + +Dependencies +------------ + +* Python 3 +* GNURadio 3.7 +* An SDR device and a suitable I/Q capture tool + +Principle of operation +---------------------- + +1. Capture I/Q data, in u8 format, at 20148ksps, centered on 145.700MHz, into a file called `iq.raw` +1. Demodulate FM and PSK using the GNURadio flowgraph `analyse_capture.grc`. It will write a file called `psk125.bit` +1. Run the `varidecode.py` script, which will read `psk125.bit` and write `psk125.txt` with decoded beacon data + +Example for RTLSDR: `rtl_sdr -f 145700000 -n 204800000 iq.raw` will capture 100 seconds worth of IQ data. + diff --git a/decoder/analyse_capture.grc b/decoder/analyse_capture.grc new file mode 100644 index 0000000..e844934 --- /dev/null +++ b/decoder/analyse_capture.grc @@ -0,0 +1,1676 @@ + + + + Wed Jul 17 22:04:54 2019 + + options + + author + HB9EGM + + + window_size + + + + category + [GRC Hier Blocks] + + + comment + + + + description + + + + _enabled + True + + + _coordinate + (8, 8) + + + _rotation + 0 + + + generate_options + no_gui + + + hier_block_src_path + .: + + + id + analyse_capture + + + max_nouts + 0 + + + qt_qss_theme + + + + realtime_scheduling + + + + run_command + {python} -u {filename} + + + run_options + run + + + run + True + + + sizing_mode + fixed + + + thread_safe_setters + + + + title + Analyse RTLSDR capture + + + placement + (0,0) + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (12, 229) + + + _rotation + 0 + + + id + audio_rate + + + value + int(32e3) + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (12, 296) + + + _rotation + 0 + + + id + decim + + + value + 16 + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (8, 160) + + + _rotation + 0 + + + id + samp_rate + + + value + 2048000 + + + + variable_low_pass_filter_taps + + beta + 6.76 + + + comment + + + + cutoff_freq + 3e3 + + + _enabled + True + + + _coordinate + (385, 15) + + + _rotation + 0 + + + gain + 1.0/256 + + + id + taps + + + samp_rate + samp_rate + + + width + 10e2 + + + win + firdes.WIN_HAMMING + + + + analog_agc_xx + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (612, 257) + + + _rotation + 0 + + + gain + 1.0 + + + id + analog_agc_xx_0 + + + max_gain + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + rate + 1e-4 + + + reference + 0.2 + + + type + float + + + + analog_const_source_x + + alias + + + + comment + + + + const + 0 + + + affinity + + + + _enabled + True + + + _coordinate + (42, 453) + + + _rotation + 0 + + + id + analog_const_source_x_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + type + float + + + + analog_nbfm_rx + + audio_rate + audio_rate + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (428, 257) + + + _rotation + 0 + + + id + analog_nbfm_rx_0 + + + max_dev + 5e3 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + quad_rate + samp_rate/decim + + + tau + 75e-6 + + + + analog_sig_source_x + + amp + 1 + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + freq + 588 + + + _coordinate + (202, 502) + + + _rotation + 0 + + + id + analog_sig_source_x_1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + offset + 0 + + + type + complex + + + samp_rate + audio_rate + + + waveform + analog.GR_COS_WAVE + + + + audio_sink + + alias + + + + comment + + + + affinity + + + + device_name + + + + _enabled + 0 + + + _coordinate + (832, 281) + + + _rotation + 0 + + + id + audio_sink_0 + + + num_inputs + 1 + + + ok_to_block + True + + + samp_rate + audio_rate + + + + blocks_complex_to_float + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (410, 726) + + + _rotation + 0 + + + id + blocks_complex_to_float_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + vlen + 1 + + + + blocks_deinterleave + + alias + + + + blocksize + 1 + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (361, 168) + + + _rotation + 0 + + + id + blocks_deinterleave_0 + + + type + byte + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + num_streams + 2 + + + vlen + 1 + + + + blocks_file_sink + + append + False + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + file + ./psk125.bit + + + _coordinate + (760, 702) + + + _rotation + 0 + + + id + blocks_file_sink_0 + + + type + byte + + + unbuffered + False + + + vlen + 1 + + + + blocks_file_source + + begin_tag + pmt.PMT_NIL + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + file + ./iq.raw + + + _coordinate + (153, 156) + + + _rotation + 0 + + + id + blocks_file_source_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + type + byte + + + repeat + False + + + vlen + 1 + + + + blocks_float_to_complex + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (636, 162) + + + _rotation + 0 + + + id + blocks_float_to_complex_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + vlen + 1 + + + + blocks_float_to_complex + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (214, 438) + + + _rotation + 0 + + + id + blocks_float_to_complex_1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + vlen + 1 + + + + blocks_multiply_xx + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (386, 481) + + + _rotation + 0 + + + id + blocks_multiply_xx_0 + + + type + complex + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + num_inputs + 2 + + + vlen + 1 + + + + blocks_uchar_to_float + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (495, 165) + + + _rotation + 0 + + + id + blocks_uchar_to_float_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + + blocks_uchar_to_float + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (495, 195) + + + _rotation + 0 + + + id + blocks_uchar_to_float_0_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + + digital_binary_slicer_fb + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (613, 723) + + + _rotation + 0 + + + id + digital_binary_slicer_fb_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + + digital_diff_phasor_cc + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (214, 735) + + + _rotation + 0 + + + id + digital_diff_phasor_cc_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + + digital_mpsk_receiver_cc + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (778, 419) + + + _rotation + 0 + + + gain_mu + 0.04 + + + gain_omega + 64*64/4 + + + id + digital_mpsk_receiver_cc_0 + + + w + cmath.pi/100.0 + + + M + 2 + + + fmax + 0.25 + + + maxoutbuf + 0 + + + fmin + -0.25 + + + minoutbuf + 0 + + + mu + 0.25 + + + omega_relative_limit + 0.005 + + + omega + 64 + + + theta + 0 + + + + freq_xlating_fft_filter_ccc + + alias + + + + center_freq + 145725e3-145700e3 + + + comment + + + + affinity + + + + decim + decim + + + _enabled + True + + + _coordinate + (177, 251) + + + _rotation + 0 + + + id + freq_xlating_fft_filter_ccc_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + nthreads + 1 + + + samp_delay + 0 + + + samp_rate + samp_rate + + + taps + taps + + + + low_pass_filter + + beta + 6.76 + + + alias + + + + comment + + + + affinity + + + + cutoff_freq + 200 + + + decim + 4 + + + _enabled + True + + + type + fir_filter_ccf + + + _coordinate + (515, 438) + + + _rotation + 0 + + + gain + 1 + + + id + low_pass_filter_0 + + + interp + 1 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + samp_rate + audio_rate + + + width + 20 + + + win + firdes.WIN_HAMMING + + + + qtgui_const_sink_x + + autoscale + False + + + axislabels + True + + + alias + + + + comment + + + + affinity + + + + _enabled + 0 + + + _coordinate + (1017, 481) + + + gui_hint + + + + _rotation + 0 + + + grid + False + + + id + qtgui_const_sink_x_1 + + + legend + True + + + alpha1 + 1.0 + + + color1 + "blue" + + + label1 + + + + marker1 + 0 + + + style1 + 0 + + + width1 + 1 + + + alpha10 + 1.0 + + + color10 + "red" + + + label10 + + + + marker10 + 0 + + + style10 + 0 + + + width10 + 1 + + + alpha2 + 1.0 + + + color2 + "red" + + + label2 + + + + marker2 + 0 + + + style2 + 0 + + + width2 + 1 + + + alpha3 + 1.0 + + + color3 + "red" + + + label3 + + + + marker3 + 0 + + + style3 + 0 + + + width3 + 1 + + + alpha4 + 1.0 + + + color4 + "red" + + + label4 + + + + marker4 + 0 + + + style4 + 0 + + + width4 + 1 + + + alpha5 + 1.0 + + + color5 + "red" + + + label5 + + + + marker5 + 0 + + + style5 + 0 + + + width5 + 1 + + + alpha6 + 1.0 + + + color6 + "red" + + + label6 + + + + marker6 + 0 + + + style6 + 0 + + + width6 + 1 + + + alpha7 + 1.0 + + + color7 + "red" + + + label7 + + + + marker7 + 0 + + + style7 + 0 + + + width7 + 1 + + + alpha8 + 1.0 + + + color8 + "red" + + + label8 + + + + marker8 + 0 + + + style8 + 0 + + + width8 + 1 + + + alpha9 + 1.0 + + + color9 + "red" + + + label9 + + + + marker9 + 0 + + + style9 + 0 + + + width9 + 1 + + + name + "" + + + nconnections + 1 + + + size + 32 + + + tr_chan + 0 + + + tr_level + 0.0 + + + tr_mode + qtgui.TRIG_MODE_FREE + + + tr_slope + qtgui.TRIG_SLOPE_POS + + + tr_tag + "" + + + type + complex + + + update_time + 0.10 + + + xmax + 2 + + + xmin + -2 + + + ymax + 2 + + + ymin + -2 + + + + analog_agc_xx_0 + audio_sink_0 + 0 + 0 + + + analog_agc_xx_0 + blocks_float_to_complex_1 + 0 + 0 + + + analog_const_source_x_0 + blocks_float_to_complex_1 + 0 + 1 + + + analog_nbfm_rx_0 + analog_agc_xx_0 + 0 + 0 + + + analog_sig_source_x_1 + blocks_multiply_xx_0 + 0 + 1 + + + blocks_complex_to_float_0 + digital_binary_slicer_fb_0 + 0 + 0 + + + blocks_deinterleave_0 + blocks_uchar_to_float_0 + 0 + 0 + + + blocks_deinterleave_0 + blocks_uchar_to_float_0_0 + 1 + 0 + + + blocks_file_source_0 + blocks_deinterleave_0 + 0 + 0 + + + blocks_float_to_complex_0 + freq_xlating_fft_filter_ccc_0 + 0 + 0 + + + blocks_float_to_complex_1 + blocks_multiply_xx_0 + 0 + 0 + + + blocks_multiply_xx_0 + low_pass_filter_0 + 0 + 0 + + + blocks_uchar_to_float_0 + blocks_float_to_complex_0 + 0 + 0 + + + blocks_uchar_to_float_0_0 + blocks_float_to_complex_0 + 0 + 1 + + + digital_binary_slicer_fb_0 + blocks_file_sink_0 + 0 + 0 + + + digital_diff_phasor_cc_0 + blocks_complex_to_float_0 + 0 + 0 + + + digital_mpsk_receiver_cc_0 + digital_diff_phasor_cc_0 + 0 + 0 + + + digital_mpsk_receiver_cc_0 + qtgui_const_sink_x_1 + 0 + 0 + + + freq_xlating_fft_filter_ccc_0 + analog_nbfm_rx_0 + 0 + 0 + + + low_pass_filter_0 + digital_mpsk_receiver_cc_0 + 0 + 0 + + diff --git a/decoder/analyse_capture.py b/decoder/analyse_capture.py new file mode 100755 index 0000000..69fd714 --- /dev/null +++ b/decoder/analyse_capture.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- +################################################## +# GNU Radio Python Flow Graph +# Title: Analyse RTLSDR capture +# Author: HB9EGM +# GNU Radio version: 3.7.13.5 +################################################## + + +from gnuradio import analog +from gnuradio import blocks +from gnuradio import digital +from gnuradio import digital;import cmath +from gnuradio import eng_notation +from gnuradio import filter +from gnuradio import gr +from gnuradio.eng_option import eng_option +from gnuradio.filter import firdes +from optparse import OptionParser +import pmt + + +class analyse_capture(gr.top_block): + + def __init__(self): + gr.top_block.__init__(self, "Analyse RTLSDR capture") + + ################################################## + # Variables + ################################################## + self.samp_rate = samp_rate = 2048000 + + self.taps = taps = firdes.low_pass(1.0/256, samp_rate, 3e3, 10e2, firdes.WIN_HAMMING, 6.76) + + self.decim = decim = 16 + self.audio_rate = audio_rate = int(32e3) + + ################################################## + # Blocks + ################################################## + self.low_pass_filter_0 = filter.fir_filter_ccf(4, firdes.low_pass( + 1, audio_rate, 200, 20, firdes.WIN_HAMMING, 6.76)) + self.freq_xlating_fft_filter_ccc_0 = filter.freq_xlating_fft_filter_ccc(decim, (taps), 145725e3-145700e3, samp_rate) + self.freq_xlating_fft_filter_ccc_0.set_nthreads(1) + self.freq_xlating_fft_filter_ccc_0.declare_sample_delay(0) + self.digital_mpsk_receiver_cc_0 = digital.mpsk_receiver_cc(2, 0, cmath.pi/100.0, -0.25, 0.25, 0.25, 0.04, 64, 64*64/4, 0.005) + self.digital_diff_phasor_cc_0 = digital.diff_phasor_cc() + self.digital_binary_slicer_fb_0 = digital.binary_slicer_fb() + self.blocks_uchar_to_float_0_0 = blocks.uchar_to_float() + self.blocks_uchar_to_float_0 = blocks.uchar_to_float() + self.blocks_multiply_xx_0 = blocks.multiply_vcc(1) + self.blocks_float_to_complex_1 = blocks.float_to_complex(1) + self.blocks_float_to_complex_0 = blocks.float_to_complex(1) + self.blocks_file_source_0 = blocks.file_source(gr.sizeof_char*1, './iq.raw', False) + self.blocks_file_source_0.set_begin_tag(pmt.PMT_NIL) + self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_char*1, './psk125.bit', False) + self.blocks_file_sink_0.set_unbuffered(False) + self.blocks_deinterleave_0 = blocks.deinterleave(gr.sizeof_char*1, 1) + self.blocks_complex_to_float_0 = blocks.complex_to_float(1) + self.analog_sig_source_x_1 = analog.sig_source_c(audio_rate, analog.GR_COS_WAVE, 588, 1, 0) + self.analog_nbfm_rx_0 = analog.nbfm_rx( + audio_rate=audio_rate, + quad_rate=samp_rate/decim, + tau=75e-6, + max_dev=5e3, + ) + self.analog_const_source_x_0 = analog.sig_source_f(0, analog.GR_CONST_WAVE, 0, 0, 0) + self.analog_agc_xx_0 = analog.agc_ff(1e-4, 0.2, 1.0) + self.analog_agc_xx_0.set_max_gain(1) + + + + ################################################## + # Connections + ################################################## + self.connect((self.analog_agc_xx_0, 0), (self.blocks_float_to_complex_1, 0)) + self.connect((self.analog_const_source_x_0, 0), (self.blocks_float_to_complex_1, 1)) + self.connect((self.analog_nbfm_rx_0, 0), (self.analog_agc_xx_0, 0)) + self.connect((self.analog_sig_source_x_1, 0), (self.blocks_multiply_xx_0, 1)) + self.connect((self.blocks_complex_to_float_0, 0), (self.digital_binary_slicer_fb_0, 0)) + self.connect((self.blocks_deinterleave_0, 0), (self.blocks_uchar_to_float_0, 0)) + self.connect((self.blocks_deinterleave_0, 1), (self.blocks_uchar_to_float_0_0, 0)) + self.connect((self.blocks_file_source_0, 0), (self.blocks_deinterleave_0, 0)) + self.connect((self.blocks_float_to_complex_0, 0), (self.freq_xlating_fft_filter_ccc_0, 0)) + self.connect((self.blocks_float_to_complex_1, 0), (self.blocks_multiply_xx_0, 0)) + self.connect((self.blocks_multiply_xx_0, 0), (self.low_pass_filter_0, 0)) + self.connect((self.blocks_uchar_to_float_0, 0), (self.blocks_float_to_complex_0, 0)) + self.connect((self.blocks_uchar_to_float_0_0, 0), (self.blocks_float_to_complex_0, 1)) + self.connect((self.digital_binary_slicer_fb_0, 0), (self.blocks_file_sink_0, 0)) + self.connect((self.digital_diff_phasor_cc_0, 0), (self.blocks_complex_to_float_0, 0)) + self.connect((self.digital_mpsk_receiver_cc_0, 0), (self.digital_diff_phasor_cc_0, 0)) + self.connect((self.freq_xlating_fft_filter_ccc_0, 0), (self.analog_nbfm_rx_0, 0)) + self.connect((self.low_pass_filter_0, 0), (self.digital_mpsk_receiver_cc_0, 0)) + + def get_samp_rate(self): + return self.samp_rate + + def set_samp_rate(self, samp_rate): + self.samp_rate = samp_rate + + def get_taps(self): + return self.taps + + def set_taps(self, taps): + self.taps = taps + self.freq_xlating_fft_filter_ccc_0.set_taps((self.taps)) + + def get_decim(self): + return self.decim + + def set_decim(self, decim): + self.decim = decim + + def get_audio_rate(self): + return self.audio_rate + + def set_audio_rate(self, audio_rate): + self.audio_rate = audio_rate + self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.audio_rate, 200, 20, firdes.WIN_HAMMING, 6.76)) + self.analog_sig_source_x_1.set_sampling_freq(self.audio_rate) + + +def main(top_block_cls=analyse_capture, options=None): + + tb = top_block_cls() + tb.start() + tb.wait() + + +if __name__ == '__main__': + main() diff --git a/decoder/varidecode.py b/decoder/varidecode.py new file mode 100755 index 0000000..11b0ed0 --- /dev/null +++ b/decoder/varidecode.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +import re +import struct + +varicode = { # {{{ + '1010101011' : '\x00', '1011011011' : '\x01', + '1011101101' : '\x02', '1101110111' : '\x03', + '1011101011' : '\x04', '1101011111' : '\x05', + '1011101111' : '\x06', '1011111101' : '\x07', + '1011111111' : '\x08', '11101111' : '\x09', + '11101' : '\x0A', '1101101111' : '\x0B', + '1011011101' : '\x0C', '11111' : '\x0D', + '1101110101' : '\x0E', '1110101011' : '\x0F', + '1011110111' : '\x10', '1011110101' : '\x11', + '1110101101' : '\x12', '1110101111' : '\x13', + '1101011011' : '\x14', '1101101011' : '\x15', + '1101101101' : '\x16', '1101010111' : '\x17', + '1101111011' : '\x18', '1101111101' : '\x19', + '1110110111' : '\x1A', '1101010101' : '\x1B', + '1101011101' : '\x1C', '1110111011' : '\x1D', + '1011111011' : '\x1E', '1101111111' : '\x1F', + '1' : ' ', '111111111' : '!', + '101011111' : '"', '111110101' : '#', + '111011011' : '$', '1011010101' : '%', + '1010111011' : '&', '101111111' : '\'', + '11111011' : '(', '11110111' : ')', + '101101111' : '*', '111011111' : '+', + '1110101' : ',', '110101' : '-', + '1010111' : '.', '110101111' : '/', + '10110111' : '0', '10111101' : '1', + '11101101' : '2', '11111111' : '3', + '101110111' : '4', '101011011' : '5', + '101101011' : '6', '110101101' : '7', + '110101011' : '8', '110110111' : '9', + '11110101' : ':', '110111101' : ';', + '111101101' : '<', '1010101' : '=', + '111010111' : '>', '1010101111' : '?', + '1010111101' : '@', '1111101' : 'A', + '11101011' : 'B', '10101101' : 'C', + '10110101' : 'D', '1110111' : 'E', + '11011011' : 'F', '11111101' : 'G', + '101010101' : 'H', '1111111' : 'I', + '111111101' : 'J', '101111101' : 'K', + '11010111' : 'L', '10111011' : 'M', + '11011101' : 'N', '10101011' : 'O', + '11010101' : 'P', '111011101' : 'Q', + '10101111' : 'R', '1101111' : 'S', + '1101101' : 'T', '101010111' : 'U', + '110110101' : 'V', '101011101' : 'W', + '101110101' : 'X', '101111011' : 'Y', + '1010101101' : 'Z', '111110111' : '[', + '111101111' : '\\', '111111011' : ']', + '1010111111' : '^', '101101101' : '_', + '1011011111' : '`', '1011' : 'a', + '1011111' : 'b', '101111' : 'c', + '101101' : 'd', '11' : 'e', + '111101' : 'f', '1011011' : 'g', + '101011' : 'h', '1101' : 'i', + '111101011' : 'j', '10111111' : 'k', + '11011' : 'l', '111011' : 'm', + '1111' : 'n', '111' : 'o', + '111111' : 'p', '110111111' : 'q', + '10101' : 'r', '10111' : 's', + '101' : 't', '110111' : 'u', + '1111011' : 'v', '1101011' : 'w', + '11011111' : 'x', '1011101' : 'y', + '111010101' : 'z', '1010110111' : '{', + '110111011' : '|', '1010110101' : '}', + '1011010111' : '~', '1110110101' : '\x7F' } + # }}} + +infile = open('./psk125.bit', mode='rb') + +# Initialize the loop +bit_stream = '' + +# Read 1 byte at a time and add it to the bit stream. +curr_bit = infile.read(1) +while curr_bit != b"": + bit_stream = bit_stream+str(struct.unpack('B', curr_bit)[0]) + curr_bit = infile.read(1) + +#print("Bit Stream:", bit_stream) + +# Use regular expression to separate the characters +# by splitting on two or more 0s +char_list = re.split('00+', bit_stream) +#print("Character List:", char_list) + +# Use the dictionary to decode the characters +output_str = '' +for char in char_list: + if char in varicode: + output_str = output_str+varicode[char] + +start_ix = output_str.find("HB9G") + +if start_ix == -1: + start_ix = 0 + +output_str = output_str[start_ix:] + +end_ix = output_str.rfind("Sat GPS=") +if end_ix != -1: + while end_ix < len(output_str) and output_str[end_ix] != '\n': + end_ix += 1 + +output_str = output_str[:end_ix] + +outfile = open('./psk125.txt', 'w') +outfile.write(output_str) +outfile.write("\n") + -- cgit v1.2.3