diff --git a/README.md b/README.md index 6fbb034..0cd3ef2 100644 --- a/README.md +++ b/README.md @@ -50,3 +50,4 @@ Any transmit capable device that can be used to transmit using a GNURadio gr-osm **lrs_pager.py** Generates a pager.bin file to be transmitted by lrs_tx.py. This code is based on [github.com/tony-tiger/lrs](https://github.com/tony-tiger/lrs)
**lrs_tx.py** Transmits an LRS signal, based on a pager.bin file generated by lrs_pager.py
**pocsagtx_osmocom.py** Transmits POCSAG messages using [gr-mixalot](https://github.com/unsynchronized/gr-mixalot)
+**gotenna_pro_bladerf.py** Transmits goTenna Pro broadcast messages using bladeRF and packet encoding from [gr-tenna](https://github.com/argilo/gr-tenna)
diff --git a/challengectl.py b/challengectl.py index 7966968..06937e8 100755 --- a/challengectl.py +++ b/challengectl.py @@ -15,6 +15,7 @@ import subprocess from challenges import ask, cw, usb_tx, nbfm, spectrum_paint, pocsagtx_osmocom, lrs_pager, lrs_tx +from challenges.gotenna import gotenna_pro_tx_bladerf, gotenna_pro_tx_usrp def build_database(flagfile, devicefile): """Create sqlite database based on flags file and devices file. Database file name will be based on @@ -232,6 +233,50 @@ def fire_lrs(self, device_string, flag_q, device_q, *flag_args): flag_q.put(flag_args[0]) print("Returned flag to pool") + def fire_gotenna_pro(self, device_string, flag_q, device_q, *flag_args): + print("\nTransmitting goTenna Pro\n") + flag_args = flag_args[0] + flag = flag_args[1] + modopts = flag_args[2] + mintime = flag_args[4] + maxtime = flag_args[5] + freq = int(flag_args[6]) * 1000 + norandsleep = flag_args[8] + + devargs = [arg.strip() for arg in device_string.split(",") if arg.strip() != ""] + devtypes = [arg.lower() for arg in devargs] + gotenna_module = None + if("uhd" in devtypes): + gotenna_module = gotenna_pro_tx_usrp + gotennaopts = gotenna_module.argument_parser().parse_args(modopts.split()) + gotennaopts.device_addr = ",".join([arg for arg in devargs if arg.lower() != "uhd"]) + elif(any(devtype.startswith("hackrf") for devtype in devtypes)): + print("goTenna Pro is not supported on HackRF, skipping device {}".format(device_string)) + elif(any(devtype.startswith("bladerf") for devtype in devtypes)): + gotenna_module = gotenna_pro_tx_bladerf + gotennaopts = gotenna_module.argument_parser().parse_args(modopts.split()) + gotennaopts.device_args = device_string + antenna = get_antenna_port(device_string) + if(antenna != ""): + gotennaopts.antenna = antenna + else: + print("goTenna Pro is not supported on device {}, skipping".format(device_string)) + + if(gotenna_module != None): + gotennaopts.message = flag + gotennaopts.frequency = freq + + gotenna_module.main(options=gotennaopts) + sleep(3) + disable_amp(device_string) + device_q.put(device_string) + + if(norandsleep == False): + sleep(randint(mintime, maxtime)) + replaceinqueue = flag_args[7] + if(replaceinqueue != False): + flag_q.put(flag_args[0]) + def select_freq(band): """Read from frequencies text file, select row that starts with band argument. diff --git a/challenges/gotenna/__init__.py b/challenges/gotenna/__init__.py new file mode 100644 index 0000000..98476f2 --- /dev/null +++ b/challenges/gotenna/__init__.py @@ -0,0 +1,4 @@ +# The flowgraphs in this package are generated by GNU Radio Companion from the +# .grc files beside them, so they import the packet library under its bare name. +# Importing challenges.gotenna_packet first registers it under that name. +#from challenges import gotenna_packet # noqa: F401 diff --git a/challenges/gotenna/gotenna_pro_tx_bladerf.grc b/challenges/gotenna/gotenna_pro_tx_bladerf.grc new file mode 100644 index 0000000..4d93c25 --- /dev/null +++ b/challenges/gotenna/gotenna_pro_tx_bladerf.grc @@ -0,0 +1,932 @@ +options: + parameters: + author: '' + catch_exceptions: 'True' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: no_gui + hier_block_src_path: '.:' + id: gotenna_pro_tx_bladerf + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: run + sizing_mode: fixed + thread_safe_setters: '' + title: '' + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: center_freq + id: variable + parameters: + comment: '' + value: frequency - offset + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [80, 460] + rotation: 0 + state: enabled +- name: control_chan + id: variable + parameters: + comment: '' + value: '2' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [120, 524] + rotation: 0 + state: enabled +- name: data_chan + id: variable + parameters: + comment: '' + value: '2' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [224, 524] + rotation: 0 + state: enabled +- name: fsk_deviation_hz + id: variable + parameters: + comment: '' + value: '{2400: 400, 4800: 750, 9600: 1100}[baud_rate]' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 332.0] + rotation: 0 + state: enabled +- name: hw_rate + id: variable + parameters: + comment: '' + value: '5760000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 460.0] + rotation: 0 + state: enabled +- name: interp + id: variable + parameters: + comment: '' + value: 480000 // baud_rate + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 460] + rotation: 0 + state: enabled +- name: offset + id: variable + parameters: + comment: '' + value: '250000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 268.0] + rotation: 0 + state: enabled +- name: packets + id: variable + parameters: + comment: '' + value: gotenna_packet.encode_pro_broadcast_packets(message_type, counter_num, + sender_gid, recipient_gid, callsign, message, publickey_data) + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 612.0] + rotation: 0 + state: enabled +- name: samp_per_sym + id: variable + parameters: + comment: '' + value: '4' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 524] + rotation: 0 + state: enabled +- name: samp_rate + id: variable + parameters: + comment: '' + value: baud_rate * samp_per_sym * interp + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 396] + rotation: 0 + state: enabled +- name: silence_time + id: variable + parameters: + comment: '' + value: '4000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [160, 612.0] + rotation: 0 + state: enabled +- name: taps + id: variable + parameters: + comment: '' + value: firdes.gaussian(1.0, samp_per_sym, 0.5, 64) + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 188.0] + rotation: 0 + state: enabled +- name: antenna + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Transmit antenna + short_id: '' + type: str + value: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 44.0] + rotation: 0 + state: true +- name: baud_rate + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Baud rate + short_id: '' + type: intx + value: '9600' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [768, 44.0] + rotation: 0 + state: enabled +- name: blocks_char_to_float_0 + id: blocks_char_to_float + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + scale: '1' + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [432, 196.0] + rotation: 180 + state: enabled +- name: blocks_multiply_xx_0 + id: blocks_multiply_xx + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_inputs: '2' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [632, 328.0] + rotation: 0 + state: enabled +- name: blocks_multiply_xx_1 + id: blocks_multiply_xx + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_inputs: '2' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [960, 408.0] + rotation: 0 + state: enabled +- name: blocks_repeat_0 + id: blocks_repeat + parameters: + affinity: '' + alias: '' + comment: '' + interp: 8 * samp_per_sym + maxoutbuf: '0' + minoutbuf: '0' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [448, 388.0] + rotation: 0 + state: enabled +- name: blocks_repeat_1 + id: blocks_repeat + parameters: + affinity: '' + alias: '' + comment: '' + interp: 8 * samp_per_sym * (hw_rate // (baud_rate * samp_per_sym)) + maxoutbuf: '0' + minoutbuf: '0' + type: float + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [592, 516.0] + rotation: 0 + state: enabled +- name: blocks_repeat_2 + id: blocks_repeat + parameters: + affinity: '' + alias: '' + comment: '' + interp: samp_per_sym + maxoutbuf: '0' + minoutbuf: '0' + type: float + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [256, 196.0] + rotation: 180 + state: enabled +- name: blocks_vco_c_0 + id: blocks_vco_c + parameters: + affinity: '' + alias: '' + amplitude: '0.9' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + samp_rate: hw_rate + sensitivity: 2*math.pi + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [768, 500.0] + rotation: 0 + state: enabled +- name: blocks_vco_c_1 + id: blocks_vco_c + parameters: + affinity: '' + alias: '' + amplitude: '1.0' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + samp_rate: baud_rate * samp_per_sym + sensitivity: 2 * math.pi * fsk_deviation_hz + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [440, 276.0] + rotation: 0 + state: enabled +- name: blocks_vector_source_x_0 + id: blocks_vector_source_x + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + repeat: 'False' + tags: '[]' + type: byte + vector: '[0]*silence_time+gotenna_packet.pro_gfsk_symbols(packets)+[0]*silence_time' + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [776, 180.0] + rotation: 180 + state: enabled +- name: blocks_vector_source_x_1 + id: blocks_vector_source_x + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + repeat: 'True' + tags: '[]' + type: complex + vector: '[1]' + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [216, 372.0] + rotation: 0 + state: enabled +- name: blocks_vector_source_x_2 + id: blocks_vector_source_x + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + repeat: 'True' + tags: '[]' + type: float + vector: '[offset]' + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [360, 500.0] + rotation: 0 + state: enabled +- name: callsign + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Sender callsign + short_id: '' + type: str + value: VE3IRR + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [512, 44.0] + rotation: 0 + state: true +- name: counter_num + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Counter + short_id: '' + type: intx + value: '0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1248, 44.0] + rotation: 0 + state: true +- name: device_args + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Osmocom device arguments + short_id: '' + type: str + value: bladerf=0,biastee=1 + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [136, 44.0] + rotation: 0 + state: true +- name: digital_map_bb_0 + id: digital_map_bb + parameters: + affinity: '' + alias: '' + comment: '' + map: '[-3, -1, 3, 1, 0]' + maxoutbuf: '0' + minoutbuf: '0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [600, 196.0] + rotation: 180 + state: enabled +- name: frequency + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Frequency + short_id: '' + type: eng_float + value: '450000000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [872, 44.0] + rotation: 0 + state: enabled +- name: import_0 + id: import + parameters: + alias: '' + comment: '' + imports: import gotenna_packet + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 92.0] + rotation: 0 + state: enabled +- name: import_1 + id: import + parameters: + alias: '' + comment: '' + imports: import math + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 140] + rotation: 0 + state: enabled +- name: interp_fir_filter_xxx_0 + id: interp_fir_filter_xxx + parameters: + affinity: '' + alias: '' + comment: '' + interp: '1' + maxoutbuf: '0' + minoutbuf: '0' + samp_delay: '0' + taps: taps + type: fff + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [216, 284.0] + rotation: 0 + state: enabled +- name: message + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Message + short_id: '' + type: str + value: Hello world! + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [648, 44.0] + rotation: 0 + state: true +- name: message_type + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: type + short_id: '' + type: str + value: BROADCAST + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [984, 44.0] + rotation: 0 + state: true +- name: osmosdr_sink_0 + id: osmosdr_sink + parameters: + affinity: '' + alias: '' + ant0: antenna + ant1: '' + ant10: '' + ant11: '' + ant12: '' + ant13: '' + ant14: '' + ant15: '' + ant16: '' + ant17: '' + ant18: '' + ant19: '' + ant2: '' + ant20: '' + ant21: '' + ant22: '' + ant23: '' + ant24: '' + ant25: '' + ant26: '' + ant27: '' + ant28: '' + ant29: '' + ant3: '' + ant30: '' + ant31: '' + ant4: '' + ant5: '' + ant6: '' + ant7: '' + ant8: '' + ant9: '' + args: device_args + bb_gain0: '0' + bb_gain1: '20' + bb_gain10: '20' + bb_gain11: '20' + bb_gain12: '20' + bb_gain13: '20' + bb_gain14: '20' + bb_gain15: '20' + bb_gain16: '20' + bb_gain17: '20' + bb_gain18: '20' + bb_gain19: '20' + bb_gain2: '20' + bb_gain20: '20' + bb_gain21: '20' + bb_gain22: '20' + bb_gain23: '20' + bb_gain24: '20' + bb_gain25: '20' + bb_gain26: '20' + bb_gain27: '20' + bb_gain28: '20' + bb_gain29: '20' + bb_gain3: '20' + bb_gain30: '20' + bb_gain31: '20' + bb_gain4: '20' + bb_gain5: '20' + bb_gain6: '20' + bb_gain7: '20' + bb_gain8: '20' + bb_gain9: '20' + bw0: '1000000' + bw1: '0' + bw10: '0' + bw11: '0' + bw12: '0' + bw13: '0' + bw14: '0' + bw15: '0' + bw16: '0' + bw17: '0' + bw18: '0' + bw19: '0' + bw2: '0' + bw20: '0' + bw21: '0' + bw22: '0' + bw23: '0' + bw24: '0' + bw25: '0' + bw26: '0' + bw27: '0' + bw28: '0' + bw29: '0' + bw3: '0' + bw30: '0' + bw31: '0' + bw4: '0' + bw5: '0' + bw6: '0' + bw7: '0' + bw8: '0' + bw9: '0' + clock_source0: '' + clock_source1: '' + clock_source2: '' + clock_source3: '' + clock_source4: '' + clock_source5: '' + clock_source6: '' + clock_source7: '' + comment: '' + corr0: '0' + corr1: '0' + corr10: '0' + corr11: '0' + corr12: '0' + corr13: '0' + corr14: '0' + corr15: '0' + corr16: '0' + corr17: '0' + corr18: '0' + corr19: '0' + corr2: '0' + corr20: '0' + corr21: '0' + corr22: '0' + corr23: '0' + corr24: '0' + corr25: '0' + corr26: '0' + corr27: '0' + corr28: '0' + corr29: '0' + corr3: '0' + corr30: '0' + corr31: '0' + corr4: '0' + corr5: '0' + corr6: '0' + corr7: '0' + corr8: '0' + corr9: '0' + freq0: center_freq + freq1: 100e6 + freq10: 100e6 + freq11: 100e6 + freq12: 100e6 + freq13: 100e6 + freq14: 100e6 + freq15: 100e6 + freq16: 100e6 + freq17: 100e6 + freq18: 100e6 + freq19: 100e6 + freq2: 100e6 + freq20: 100e6 + freq21: 100e6 + freq22: 100e6 + freq23: 100e6 + freq24: 100e6 + freq25: 100e6 + freq26: 100e6 + freq27: 100e6 + freq28: 100e6 + freq29: 100e6 + freq3: 100e6 + freq30: 100e6 + freq31: 100e6 + freq4: 100e6 + freq5: 100e6 + freq6: 100e6 + freq7: 100e6 + freq8: 100e6 + freq9: 100e6 + gain0: '60' + gain1: '10' + gain10: '10' + gain11: '10' + gain12: '10' + gain13: '10' + gain14: '10' + gain15: '10' + gain16: '10' + gain17: '10' + gain18: '10' + gain19: '10' + gain2: '10' + gain20: '10' + gain21: '10' + gain22: '10' + gain23: '10' + gain24: '10' + gain25: '10' + gain26: '10' + gain27: '10' + gain28: '10' + gain29: '10' + gain3: '10' + gain30: '10' + gain31: '10' + gain4: '10' + gain5: '10' + gain6: '10' + gain7: '10' + gain8: '10' + gain9: '10' + if_gain0: '0' + if_gain1: '20' + if_gain10: '20' + if_gain11: '20' + if_gain12: '20' + if_gain13: '20' + if_gain14: '20' + if_gain15: '20' + if_gain16: '20' + if_gain17: '20' + if_gain18: '20' + if_gain19: '20' + if_gain2: '20' + if_gain20: '20' + if_gain21: '20' + if_gain22: '20' + if_gain23: '20' + if_gain24: '20' + if_gain25: '20' + if_gain26: '20' + if_gain27: '20' + if_gain28: '20' + if_gain29: '20' + if_gain3: '20' + if_gain30: '20' + if_gain31: '20' + if_gain4: '20' + if_gain5: '20' + if_gain6: '20' + if_gain7: '20' + if_gain8: '20' + if_gain9: '20' + maxoutbuf: '0' + minoutbuf: '0' + nchan: '1' + num_mboards: '1' + sample_rate: hw_rate + sync: sync + time_source0: '' + time_source1: '' + time_source2: '' + time_source3: '' + time_source4: '' + time_source5: '' + time_source6: '' + time_source7: '' + type: fc32 + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1184, 332.0] + rotation: 0 + state: enabled +- name: publickey_data + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Sender Public Key + short_id: '' + type: str + value: base64key + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1104, 44.0] + rotation: 0 + state: true +- name: rational_resampler_xxx_0 + id: rational_resampler_xxx + parameters: + affinity: '' + alias: '' + comment: '' + decim: '1' + fbw: '0' + interp: hw_rate // (baud_rate * samp_per_sym) + maxoutbuf: '0' + minoutbuf: '0' + taps: '' + type: ccc + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [760, 316.0] + rotation: 0 + state: enabled +- name: recipient_gid + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Recipient GID + short_id: '' + type: intx + value: '1234567891' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [272, 44.0] + rotation: 0 + state: true +- name: sender_gid + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Sender GID + short_id: '' + type: intx + value: '1234567890' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [400, 44.0] + rotation: 0 + state: true + +connections: +- [blocks_char_to_float_0, '0', blocks_repeat_2, '0'] +- [blocks_multiply_xx_0, '0', rational_resampler_xxx_0, '0'] +- [blocks_multiply_xx_1, '0', osmosdr_sink_0, '0'] +- [blocks_repeat_0, '0', blocks_multiply_xx_0, '1'] +- [blocks_repeat_1, '0', blocks_vco_c_0, '0'] +- [blocks_repeat_2, '0', interp_fir_filter_xxx_0, '0'] +- [blocks_vco_c_0, '0', blocks_multiply_xx_1, '1'] +- [blocks_vco_c_1, '0', blocks_multiply_xx_0, '0'] +- [blocks_vector_source_x_0, '0', digital_map_bb_0, '0'] +- [blocks_vector_source_x_1, '0', blocks_repeat_0, '0'] +- [blocks_vector_source_x_2, '0', blocks_repeat_1, '0'] +- [digital_map_bb_0, '0', blocks_char_to_float_0, '0'] +- [interp_fir_filter_xxx_0, '0', blocks_vco_c_1, '0'] +- [rational_resampler_xxx_0, '0', blocks_multiply_xx_1, '0'] + +metadata: + file_format: 1 + grc_version: 3.10.7.0 diff --git a/challenges/gotenna/gotenna_pro_tx_bladerf.py b/challenges/gotenna/gotenna_pro_tx_bladerf.py new file mode 100755 index 0000000..5a8d886 --- /dev/null +++ b/challenges/gotenna/gotenna_pro_tx_bladerf.py @@ -0,0 +1,346 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# +# SPDX-License-Identifier: GPL-3.0 +# +# GNU Radio Python Flow Graph +# Title: Gotenna Pro Tx Bladerf +# GNU Radio version: 3.10.5.0 + +from gnuradio import blocks +from gnuradio import digital +from gnuradio import filter +from gnuradio.filter import firdes +from gnuradio import gr +from gnuradio.fft import window +import sys +import signal +from argparse import ArgumentParser +from gnuradio.eng_arg import eng_float, intx +from gnuradio import eng_notation +import gotenna_packet +import math +import osmosdr +import time + + + + +class gotenna_pro_tx_bladerf(gr.top_block): + + def __init__(self, antenna='', baud_rate=9600, callsign='VE3IRR', counter_num=0, device_args='bladerf=0,biastee=1', frequency=450000000, message='Hello world!', message_type='BROADCAST', publickey_data='base64key', recipient_gid=1234567891, sender_gid=1234567890): + gr.top_block.__init__(self, "Gotenna Pro Tx Bladerf", catch_exceptions=True) + + ################################################## + # Parameters + ################################################## + self.antenna = antenna + self.baud_rate = baud_rate + self.callsign = callsign + self.counter_num = counter_num + self.device_args = device_args + self.frequency = frequency + self.message = message + self.message_type = message_type + self.publickey_data = publickey_data + self.recipient_gid = recipient_gid + self.sender_gid = sender_gid + + ################################################## + # Variables + ################################################## + self.samp_per_sym = samp_per_sym = 4 + self.offset = offset = 250000 + self.interp = interp = 480000 // baud_rate + self.taps = taps = firdes.gaussian(1.0, samp_per_sym, 0.5, 64) + self.silence_time = silence_time = 4000 + self.samp_rate = samp_rate = baud_rate * samp_per_sym * interp + self.packets = packets = gotenna_packet.encode_pro_broadcast_packets(message_type, counter_num, sender_gid, recipient_gid, callsign, message, publickey_data) + self.hw_rate = hw_rate = 5760000 + self.fsk_deviation_hz = fsk_deviation_hz = {2400: 400, 4800: 750, 9600: 1100}[baud_rate] + self.data_chan = data_chan = 2 + self.control_chan = control_chan = 2 + self.center_freq = center_freq = frequency - offset + + ################################################## + # Blocks + ################################################## + self.rational_resampler_xxx_0 = filter.rational_resampler_ccc( + interpolation=(hw_rate // (baud_rate * samp_per_sym)), + decimation=1, + taps=[], + fractional_bw=0) + self.osmosdr_sink_0 = osmosdr.sink( + args="numchan=" + str(1) + " " + device_args + ) + self.osmosdr_sink_0.set_time_unknown_pps(osmosdr.time_spec_t()) + self.osmosdr_sink_0.set_sample_rate(hw_rate) + self.osmosdr_sink_0.set_center_freq(center_freq, 0) + self.osmosdr_sink_0.set_freq_corr(0, 0) + self.osmosdr_sink_0.set_gain(60, 0) + self.osmosdr_sink_0.set_if_gain(0, 0) + self.osmosdr_sink_0.set_bb_gain(0, 0) + self.osmosdr_sink_0.set_antenna(antenna, 0) + self.osmosdr_sink_0.set_bandwidth(1000000, 0) + self.interp_fir_filter_xxx_0 = filter.interp_fir_filter_fff(1, taps) + self.interp_fir_filter_xxx_0.declare_sample_delay(0) + self.digital_map_bb_0 = digital.map_bb([-3, -1, 3, 1, 0]) + self.blocks_vector_source_x_2 = blocks.vector_source_f([offset], True, 1, []) + self.blocks_vector_source_x_1 = blocks.vector_source_c([1], True, 1, []) + self.blocks_vector_source_x_0 = blocks.vector_source_b([0]*silence_time+gotenna_packet.pro_gfsk_symbols(packets)+[0]*silence_time, False, 1, []) + self.blocks_vco_c_1 = blocks.vco_c((baud_rate * samp_per_sym), (2 * math.pi * fsk_deviation_hz), 1.0) + self.blocks_vco_c_0 = blocks.vco_c(hw_rate, (2*math.pi), 0.9) + self.blocks_repeat_2 = blocks.repeat(gr.sizeof_float*1, samp_per_sym) + self.blocks_repeat_1 = blocks.repeat(gr.sizeof_float*1, (8 * samp_per_sym * (hw_rate // (baud_rate * samp_per_sym)))) + self.blocks_repeat_0 = blocks.repeat(gr.sizeof_gr_complex*1, (8 * samp_per_sym)) + self.blocks_multiply_xx_1 = blocks.multiply_vcc(1) + self.blocks_multiply_xx_0 = blocks.multiply_vcc(1) + self.blocks_char_to_float_0 = blocks.char_to_float(1, 1) + + + ################################################## + # Connections + ################################################## + self.connect((self.blocks_char_to_float_0, 0), (self.blocks_repeat_2, 0)) + self.connect((self.blocks_multiply_xx_0, 0), (self.rational_resampler_xxx_0, 0)) + self.connect((self.blocks_multiply_xx_1, 0), (self.osmosdr_sink_0, 0)) + self.connect((self.blocks_repeat_0, 0), (self.blocks_multiply_xx_0, 1)) + self.connect((self.blocks_repeat_1, 0), (self.blocks_vco_c_0, 0)) + self.connect((self.blocks_repeat_2, 0), (self.interp_fir_filter_xxx_0, 0)) + self.connect((self.blocks_vco_c_0, 0), (self.blocks_multiply_xx_1, 1)) + self.connect((self.blocks_vco_c_1, 0), (self.blocks_multiply_xx_0, 0)) + self.connect((self.blocks_vector_source_x_0, 0), (self.digital_map_bb_0, 0)) + self.connect((self.blocks_vector_source_x_1, 0), (self.blocks_repeat_0, 0)) + self.connect((self.blocks_vector_source_x_2, 0), (self.blocks_repeat_1, 0)) + self.connect((self.digital_map_bb_0, 0), (self.blocks_char_to_float_0, 0)) + self.connect((self.interp_fir_filter_xxx_0, 0), (self.blocks_vco_c_1, 0)) + self.connect((self.rational_resampler_xxx_0, 0), (self.blocks_multiply_xx_1, 0)) + + + def get_antenna(self): + return self.antenna + + def set_antenna(self, antenna): + self.antenna = antenna + self.osmosdr_sink_0.set_antenna(self.antenna, 0) + + def get_baud_rate(self): + return self.baud_rate + + def set_baud_rate(self, baud_rate): + self.baud_rate = baud_rate + self.set_fsk_deviation_hz({2400: 400, 4800: 750, 9600: 1100}[self.baud_rate]) + self.set_interp(480000 // self.baud_rate) + self.set_samp_rate(self.baud_rate * self.samp_per_sym * self.interp) + self.blocks_repeat_1.set_interpolation((8 * self.samp_per_sym * (self.hw_rate // (self.baud_rate * self.samp_per_sym)))) + + def get_callsign(self): + return self.callsign + + def set_callsign(self, callsign): + self.callsign = callsign + self.set_packets(gotenna_packet.encode_pro_broadcast_packets(self.message_type, self.counter_num, self.sender_gid, self.recipient_gid, self.callsign, self.message, self.publickey_data)) + + def get_counter_num(self): + return self.counter_num + + def set_counter_num(self, counter_num): + self.counter_num = counter_num + self.set_packets(gotenna_packet.encode_pro_broadcast_packets(self.message_type, self.counter_num, self.sender_gid, self.recipient_gid, self.callsign, self.message, self.publickey_data)) + + def get_device_args(self): + return self.device_args + + def set_device_args(self, device_args): + self.device_args = device_args + + def get_frequency(self): + return self.frequency + + def set_frequency(self, frequency): + self.frequency = frequency + self.set_center_freq(self.frequency - self.offset) + + def get_message(self): + return self.message + + def set_message(self, message): + self.message = message + self.set_packets(gotenna_packet.encode_pro_broadcast_packets(self.message_type, self.counter_num, self.sender_gid, self.recipient_gid, self.callsign, self.message, self.publickey_data)) + + def get_message_type(self): + return self.message_type + + def set_message_type(self, message_type): + self.message_type = message_type + self.set_packets(gotenna_packet.encode_pro_broadcast_packets(self.message_type, self.counter_num, self.sender_gid, self.recipient_gid, self.callsign, self.message, self.publickey_data)) + + def get_publickey_data(self): + return self.publickey_data + + def set_publickey_data(self, publickey_data): + self.publickey_data = publickey_data + self.set_packets(gotenna_packet.encode_pro_broadcast_packets(self.message_type, self.counter_num, self.sender_gid, self.recipient_gid, self.callsign, self.message, self.publickey_data)) + + def get_recipient_gid(self): + return self.recipient_gid + + def set_recipient_gid(self, recipient_gid): + self.recipient_gid = recipient_gid + self.set_packets(gotenna_packet.encode_pro_broadcast_packets(self.message_type, self.counter_num, self.sender_gid, self.recipient_gid, self.callsign, self.message, self.publickey_data)) + + def get_sender_gid(self): + return self.sender_gid + + def set_sender_gid(self, sender_gid): + self.sender_gid = sender_gid + self.set_packets(gotenna_packet.encode_pro_broadcast_packets(self.message_type, self.counter_num, self.sender_gid, self.recipient_gid, self.callsign, self.message, self.publickey_data)) + + def get_samp_per_sym(self): + return self.samp_per_sym + + def set_samp_per_sym(self, samp_per_sym): + self.samp_per_sym = samp_per_sym + self.set_samp_rate(self.baud_rate * self.samp_per_sym * self.interp) + self.set_taps(firdes.gaussian(1.0, self.samp_per_sym, 0.5, 64)) + self.blocks_repeat_0.set_interpolation((8 * self.samp_per_sym)) + self.blocks_repeat_1.set_interpolation((8 * self.samp_per_sym * (self.hw_rate // (self.baud_rate * self.samp_per_sym)))) + self.blocks_repeat_2.set_interpolation(self.samp_per_sym) + + def get_offset(self): + return self.offset + + def set_offset(self, offset): + self.offset = offset + self.set_center_freq(self.frequency - self.offset) + self.blocks_vector_source_x_2.set_data([self.offset], []) + + def get_interp(self): + return self.interp + + def set_interp(self, interp): + self.interp = interp + self.set_samp_rate(self.baud_rate * self.samp_per_sym * self.interp) + + def get_taps(self): + return self.taps + + def set_taps(self, taps): + self.taps = taps + self.interp_fir_filter_xxx_0.set_taps(self.taps) + + def get_silence_time(self): + return self.silence_time + + def set_silence_time(self, silence_time): + self.silence_time = silence_time + self.blocks_vector_source_x_0.set_data([0]*self.silence_time+gotenna_packet.pro_gfsk_symbols(self.packets)+[0]*self.silence_time, []) + + def get_samp_rate(self): + return self.samp_rate + + def set_samp_rate(self, samp_rate): + self.samp_rate = samp_rate + + def get_packets(self): + return self.packets + + def set_packets(self, packets): + self.packets = packets + self.blocks_vector_source_x_0.set_data([0]*self.silence_time+gotenna_packet.pro_gfsk_symbols(self.packets)+[0]*self.silence_time, []) + + def get_hw_rate(self): + return self.hw_rate + + def set_hw_rate(self, hw_rate): + self.hw_rate = hw_rate + self.blocks_repeat_1.set_interpolation((8 * self.samp_per_sym * (self.hw_rate // (self.baud_rate * self.samp_per_sym)))) + self.osmosdr_sink_0.set_sample_rate(self.hw_rate) + + def get_fsk_deviation_hz(self): + return self.fsk_deviation_hz + + def set_fsk_deviation_hz(self, fsk_deviation_hz): + self.fsk_deviation_hz = fsk_deviation_hz + + def get_data_chan(self): + return self.data_chan + + def set_data_chan(self, data_chan): + self.data_chan = data_chan + + def get_control_chan(self): + return self.control_chan + + def set_control_chan(self, control_chan): + self.control_chan = control_chan + + def get_center_freq(self): + return self.center_freq + + def set_center_freq(self, center_freq): + self.center_freq = center_freq + self.osmosdr_sink_0.set_center_freq(self.center_freq, 0) + + + +def argument_parser(): + parser = ArgumentParser() + parser.add_argument( + "--antenna", dest="antenna", type=str, default='', + help="Set Transmit antenna [default=%(default)r]") + parser.add_argument( + "--baud-rate", dest="baud_rate", type=intx, default=9600, + help="Set Baud rate [default=%(default)r]") + parser.add_argument( + "--callsign", dest="callsign", type=str, default='VE3IRR', + help="Set Sender callsign [default=%(default)r]") + parser.add_argument( + "--counter-num", dest="counter_num", type=intx, default=0, + help="Set Counter [default=%(default)r]") + parser.add_argument( + "--device-args", dest="device_args", type=str, default='bladerf=0,biastee=1', + help="Set Osmocom device arguments [default=%(default)r]") + parser.add_argument( + "--frequency", dest="frequency", type=eng_float, default=eng_notation.num_to_str(float(450000000)), + help="Set Frequency [default=%(default)r]") + parser.add_argument( + "--message", dest="message", type=str, default='Hello world!', + help="Set Message [default=%(default)r]") + parser.add_argument( + "--message-type", dest="message_type", type=str, default='BROADCAST', + help="Set type [default=%(default)r]") + parser.add_argument( + "--publickey-data", dest="publickey_data", type=str, default='base64key', + help="Set Sender Public Key [default=%(default)r]") + parser.add_argument( + "--recipient-gid", dest="recipient_gid", type=intx, default=1234567891, + help="Set Recipient GID [default=%(default)r]") + parser.add_argument( + "--sender-gid", dest="sender_gid", type=intx, default=1234567890, + help="Set Sender GID [default=%(default)r]") + return parser + + +def main(top_block_cls=gotenna_pro_tx_bladerf, options=None): + if options is None: + options = argument_parser().parse_args() + tb = top_block_cls(antenna=options.antenna, baud_rate=options.baud_rate, callsign=options.callsign, counter_num=options.counter_num, device_args=options.device_args, frequency=options.frequency, message=options.message, message_type=options.message_type, publickey_data=options.publickey_data, recipient_gid=options.recipient_gid, sender_gid=options.sender_gid) + + #def sig_handler(sig=None, frame=None): + # tb.stop() + # tb.wait() + + # sys.exit(0) + + #signal.signal(signal.SIGINT, sig_handler) + #signal.signal(signal.SIGTERM, sig_handler) + + tb.start() + + tb.wait() + + +if __name__ == '__main__': + main() diff --git a/challenges/gotenna/gotenna_pro_tx_usrp.grc b/challenges/gotenna/gotenna_pro_tx_usrp.grc new file mode 100644 index 0000000..43de67d --- /dev/null +++ b/challenges/gotenna/gotenna_pro_tx_usrp.grc @@ -0,0 +1,947 @@ +options: + parameters: + author: '' + catch_exceptions: 'True' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: no_gui + hier_block_src_path: '.:' + id: gotenna_pro_tx_usrp + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: run + sizing_mode: fixed + thread_safe_setters: '' + title: '' + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: center_freq + id: variable + parameters: + comment: '' + value: frequency - offset + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [80, 460] + rotation: 0 + state: enabled +- name: control_chan + id: variable + parameters: + comment: '' + value: '2' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [120, 524] + rotation: 0 + state: enabled +- name: data_chan + id: variable + parameters: + comment: '' + value: '2' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [224, 524] + rotation: 0 + state: enabled +- name: fsk_deviation_hz + id: variable + parameters: + comment: '' + value: '{2400: 400, 4800: 750, 9600: 1100}[baud_rate]' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 332.0] + rotation: 0 + state: enabled +- name: interp + id: variable + parameters: + comment: '' + value: 480000 // baud_rate + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 460] + rotation: 0 + state: enabled +- name: offset + id: variable + parameters: + comment: '' + value: '250000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 268.0] + rotation: 0 + state: enabled +- name: packets + id: variable + parameters: + comment: '' + value: gotenna_packet.encode_pro_broadcast_packets(message_type, counter_num, + sender_gid, recipient_gid, callsign, message, publickey_data) + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 612.0] + rotation: 0 + state: enabled +- name: samp_per_sym + id: variable + parameters: + comment: '' + value: '4' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 524] + rotation: 0 + state: enabled +- name: samp_rate + id: variable + parameters: + comment: '' + value: baud_rate * samp_per_sym * interp + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 396] + rotation: 0 + state: enabled +- name: taps + id: variable + parameters: + comment: '' + value: firdes.gaussian(1.0, samp_per_sym, 0.5, 64) + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 188.0] + rotation: 0 + state: enabled +- name: baud_rate + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Baud rate + short_id: '' + type: intx + value: '9600' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [768, 44.0] + rotation: 0 + state: enabled +- name: blocks_char_to_float_0 + id: blocks_char_to_float + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + scale: '1' + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [432, 196.0] + rotation: 180 + state: enabled +- name: blocks_file_sink_0 + id: blocks_file_sink + parameters: + affinity: '' + alias: '' + append: 'False' + comment: '' + file: pro_synth.cf32 + type: complex + unbuffered: 'False' + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1136, 492.0] + rotation: 0 + state: disabled +- name: blocks_multiply_xx_0 + id: blocks_multiply_xx + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_inputs: '2' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [632, 328.0] + rotation: 0 + state: enabled +- name: blocks_multiply_xx_1 + id: blocks_multiply_xx + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_inputs: '2' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [960, 408.0] + rotation: 0 + state: enabled +- name: blocks_repeat_0 + id: blocks_repeat + parameters: + affinity: '' + alias: '' + comment: '' + interp: 8 * samp_per_sym + maxoutbuf: '0' + minoutbuf: '0' + type: complex + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [448, 388.0] + rotation: 0 + state: enabled +- name: blocks_repeat_1 + id: blocks_repeat + parameters: + affinity: '' + alias: '' + comment: '' + interp: 8 * samp_per_sym * interp + maxoutbuf: '0' + minoutbuf: '0' + type: float + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [592, 516.0] + rotation: 0 + state: enabled +- name: blocks_repeat_2 + id: blocks_repeat + parameters: + affinity: '' + alias: '' + comment: '' + interp: samp_per_sym + maxoutbuf: '0' + minoutbuf: '0' + type: float + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [256, 196.0] + rotation: 180 + state: enabled +- name: blocks_vco_c_0 + id: blocks_vco_c + parameters: + affinity: '' + alias: '' + amplitude: '0.9' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + samp_rate: samp_rate + sensitivity: 2*math.pi + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [768, 500.0] + rotation: 0 + state: enabled +- name: blocks_vco_c_1 + id: blocks_vco_c + parameters: + affinity: '' + alias: '' + amplitude: '1.0' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + samp_rate: baud_rate * samp_per_sym + sensitivity: 2 * math.pi * fsk_deviation_hz + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [440, 276.0] + rotation: 0 + state: enabled +- name: blocks_vector_source_x_0 + id: blocks_vector_source_x + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + repeat: 'False' + tags: '[]' + type: byte + vector: gotenna_packet.pro_gfsk_symbols(packets) + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [776, 180.0] + rotation: 180 + state: enabled +- name: blocks_vector_source_x_1 + id: blocks_vector_source_x + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + repeat: 'True' + tags: '[]' + type: complex + vector: '[1]' + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [216, 372.0] + rotation: 0 + state: enabled +- name: blocks_vector_source_x_2 + id: blocks_vector_source_x + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + repeat: 'True' + tags: '[]' + type: float + vector: '[offset]' + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [360, 500.0] + rotation: 0 + state: enabled +- name: callsign + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Sender callsign + short_id: '' + type: str + value: VE3IRR + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [512, 44.0] + rotation: 0 + state: true +- name: counter_num + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Counter + short_id: '' + type: intx + value: '0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1288, 44.0] + rotation: 0 + state: true +- name: device_addr + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: UHD device address + short_id: '' + type: str + value: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 44.0] + rotation: 0 + state: true +- name: digital_map_bb_0 + id: digital_map_bb + parameters: + affinity: '' + alias: '' + comment: '' + map: '[-3, -1, 3, 1, 0]' + maxoutbuf: '0' + minoutbuf: '0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [600, 196.0] + rotation: 180 + state: enabled +- name: frequency + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Frequency + short_id: '' + type: eng_float + value: '450000000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [872, 44.0] + rotation: 0 + state: enabled +- name: import_0 + id: import + parameters: + alias: '' + comment: '' + imports: import gotenna_packet + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 92.0] + rotation: 0 + state: enabled +- name: import_1 + id: import + parameters: + alias: '' + comment: '' + imports: import math + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 140] + rotation: 0 + state: enabled +- name: interp_fir_filter_xxx_0 + id: interp_fir_filter_xxx + parameters: + affinity: '' + alias: '' + comment: '' + interp: '1' + maxoutbuf: '0' + minoutbuf: '0' + samp_delay: '0' + taps: taps + type: fff + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [216, 284.0] + rotation: 0 + state: enabled +- name: message + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Message + short_id: '' + type: str + value: Hello world! + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [648, 44.0] + rotation: 0 + state: true +- name: message_type + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: type + short_id: '' + type: str + value: BROADCAST + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [984, 44.0] + rotation: 0 + state: true +- name: publickey_data + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Sender Public Key + short_id: '' + type: str + value: base64key + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1104, 44.0] + rotation: 0 + state: true +- name: rational_resampler_xxx_0 + id: rational_resampler_xxx + parameters: + affinity: '' + alias: '' + comment: '' + decim: '1' + fbw: '0' + interp: interp + maxoutbuf: '0' + minoutbuf: '0' + taps: '' + type: ccc + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [760, 316.0] + rotation: 0 + state: enabled +- name: rational_resampler_xxx_1 + id: rational_resampler_xxx + parameters: + affinity: '' + alias: '' + comment: '' + decim: '48' + fbw: '0' + interp: '25' + maxoutbuf: '0' + minoutbuf: '0' + taps: '[]' + type: ccc + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [992, 580.0] + rotation: 0 + state: disabled +- name: recipient_gid + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Recipient GID + short_id: '' + type: intx + value: '1234567891' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [272, 44.0] + rotation: 0 + state: true +- name: sender_gid + id: parameter + parameters: + alias: '' + comment: '' + hide: none + label: Sender GID + short_id: '' + type: intx + value: '1234567890' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [400, 44.0] + rotation: 0 + state: true +- name: uhd_usrp_sink_0 + id: uhd_usrp_sink + parameters: + affinity: '' + alias: '' + ant0: '"TX/RX"' + ant1: '' + ant10: '' + ant11: '' + ant12: '' + ant13: '' + ant14: '' + ant15: '' + ant16: '' + ant17: '' + ant18: '' + ant19: '' + ant2: '' + ant20: '' + ant21: '' + ant22: '' + ant23: '' + ant24: '' + ant25: '' + ant26: '' + ant27: '' + ant28: '' + ant29: '' + ant3: '' + ant30: '' + ant31: '' + ant4: '' + ant5: '' + ant6: '' + ant7: '' + ant8: '' + ant9: '' + bw0: '0' + bw1: '0' + bw10: '0' + bw11: '0' + bw12: '0' + bw13: '0' + bw14: '0' + bw15: '0' + bw16: '0' + bw17: '0' + bw18: '0' + bw19: '0' + bw2: '0' + bw20: '0' + bw21: '0' + bw22: '0' + bw23: '0' + bw24: '0' + bw25: '0' + bw26: '0' + bw27: '0' + bw28: '0' + bw29: '0' + bw3: '0' + bw30: '0' + bw31: '0' + bw4: '0' + bw5: '0' + bw6: '0' + bw7: '0' + bw8: '0' + bw9: '0' + center_freq0: center_freq + center_freq1: '0' + center_freq10: '0' + center_freq11: '0' + center_freq12: '0' + center_freq13: '0' + center_freq14: '0' + center_freq15: '0' + center_freq16: '0' + center_freq17: '0' + center_freq18: '0' + center_freq19: '0' + center_freq2: '0' + center_freq20: '0' + center_freq21: '0' + center_freq22: '0' + center_freq23: '0' + center_freq24: '0' + center_freq25: '0' + center_freq26: '0' + center_freq27: '0' + center_freq28: '0' + center_freq29: '0' + center_freq3: '0' + center_freq30: '0' + center_freq31: '0' + center_freq4: '0' + center_freq5: '0' + center_freq6: '0' + center_freq7: '0' + center_freq8: '0' + center_freq9: '0' + clock_rate: '0.0' + clock_source0: '' + clock_source1: '' + clock_source2: '' + clock_source3: '' + clock_source4: '' + clock_source5: '' + clock_source6: '' + clock_source7: '' + comment: '' + dev_addr: device_addr + dev_args: '""' + gain0: '70' + gain1: '0' + gain10: '0' + gain11: '0' + gain12: '0' + gain13: '0' + gain14: '0' + gain15: '0' + gain16: '0' + gain17: '0' + gain18: '0' + gain19: '0' + gain2: '0' + gain20: '0' + gain21: '0' + gain22: '0' + gain23: '0' + gain24: '0' + gain25: '0' + gain26: '0' + gain27: '0' + gain28: '0' + gain29: '0' + gain3: '0' + gain30: '0' + gain31: '0' + gain4: '0' + gain5: '0' + gain6: '0' + gain7: '0' + gain8: '0' + gain9: '0' + gain_type0: default + gain_type1: default + gain_type10: default + gain_type11: default + gain_type12: default + gain_type13: default + gain_type14: default + gain_type15: default + gain_type16: default + gain_type17: default + gain_type18: default + gain_type19: default + gain_type2: default + gain_type20: default + gain_type21: default + gain_type22: default + gain_type23: default + gain_type24: default + gain_type25: default + gain_type26: default + gain_type27: default + gain_type28: default + gain_type29: default + gain_type3: default + gain_type30: default + gain_type31: default + gain_type4: default + gain_type5: default + gain_type6: default + gain_type7: default + gain_type8: default + gain_type9: default + len_tag_name: '' + lo_export0: 'False' + lo_export1: 'False' + lo_export10: 'False' + lo_export11: 'False' + lo_export12: 'False' + lo_export13: 'False' + lo_export14: 'False' + lo_export15: 'False' + lo_export16: 'False' + lo_export17: 'False' + lo_export18: 'False' + lo_export19: 'False' + lo_export2: 'False' + lo_export20: 'False' + lo_export21: 'False' + lo_export22: 'False' + lo_export23: 'False' + lo_export24: 'False' + lo_export25: 'False' + lo_export26: 'False' + lo_export27: 'False' + lo_export28: 'False' + lo_export29: 'False' + lo_export3: 'False' + lo_export30: 'False' + lo_export31: 'False' + lo_export4: 'False' + lo_export5: 'False' + lo_export6: 'False' + lo_export7: 'False' + lo_export8: 'False' + lo_export9: 'False' + lo_source0: internal + lo_source1: internal + lo_source10: internal + lo_source11: internal + lo_source12: internal + lo_source13: internal + lo_source14: internal + lo_source15: internal + lo_source16: internal + lo_source17: internal + lo_source18: internal + lo_source19: internal + lo_source2: internal + lo_source20: internal + lo_source21: internal + lo_source22: internal + lo_source23: internal + lo_source24: internal + lo_source25: internal + lo_source26: internal + lo_source27: internal + lo_source28: internal + lo_source29: internal + lo_source3: internal + lo_source30: internal + lo_source31: internal + lo_source4: internal + lo_source5: internal + lo_source6: internal + lo_source7: internal + lo_source8: internal + lo_source9: internal + maxoutbuf: '0' + minoutbuf: '0' + nchan: '1' + num_mboards: '1' + otw: '' + samp_rate: samp_rate + sd_spec0: '' + sd_spec1: '' + sd_spec2: '' + sd_spec3: '' + sd_spec4: '' + sd_spec5: '' + sd_spec6: '' + sd_spec7: '' + show_lo_controls: 'False' + start_time: '-1.0' + stream_args: '' + stream_chans: '[]' + sync: sync + time_source0: '' + time_source1: '' + time_source2: '' + time_source3: '' + time_source4: '' + time_source5: '' + time_source6: '' + time_source7: '' + type: fc32 + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1144, 380.0] + rotation: 0 + state: enabled + +connections: +- [blocks_char_to_float_0, '0', blocks_repeat_2, '0'] +- [blocks_multiply_xx_0, '0', rational_resampler_xxx_0, '0'] +- [blocks_multiply_xx_1, '0', rational_resampler_xxx_1, '0'] +- [blocks_multiply_xx_1, '0', uhd_usrp_sink_0, '0'] +- [blocks_repeat_0, '0', blocks_multiply_xx_0, '1'] +- [blocks_repeat_1, '0', blocks_vco_c_0, '0'] +- [blocks_repeat_2, '0', interp_fir_filter_xxx_0, '0'] +- [blocks_vco_c_0, '0', blocks_multiply_xx_1, '1'] +- [blocks_vco_c_1, '0', blocks_multiply_xx_0, '0'] +- [blocks_vector_source_x_0, '0', digital_map_bb_0, '0'] +- [blocks_vector_source_x_1, '0', blocks_repeat_0, '0'] +- [blocks_vector_source_x_2, '0', blocks_repeat_1, '0'] +- [digital_map_bb_0, '0', blocks_char_to_float_0, '0'] +- [interp_fir_filter_xxx_0, '0', blocks_vco_c_1, '0'] +- [rational_resampler_xxx_0, '0', blocks_multiply_xx_1, '0'] +- [rational_resampler_xxx_1, '0', blocks_file_sink_0, '0'] + +metadata: + file_format: 1 + grc_version: 3.10.9.2 diff --git a/challenges/gotenna/gotenna_pro_tx_usrp.py b/challenges/gotenna/gotenna_pro_tx_usrp.py new file mode 100755 index 0000000..06982dd --- /dev/null +++ b/challenges/gotenna/gotenna_pro_tx_usrp.py @@ -0,0 +1,322 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# +# SPDX-License-Identifier: GPL-3.0 +# +# GNU Radio Python Flow Graph +# Title: Gotenna Pro Tx Usrp +# GNU Radio version: 3.10.5.0 + +from gnuradio import blocks +from gnuradio import digital +from gnuradio import filter +from gnuradio.filter import firdes +from gnuradio import gr +from gnuradio.fft import window +import sys +import signal +from argparse import ArgumentParser +from gnuradio.eng_arg import eng_float, intx +from gnuradio import eng_notation +from gnuradio import uhd +import time +import gotenna_packet +import math + + + + +class gotenna_pro_tx_usrp(gr.top_block): + + def __init__(self, baud_rate=9600, callsign='VE3IRR', counter_num=0, device_addr='', frequency=450000000, message='Hello world!', message_type='BROADCAST', publickey_data='base64key', recipient_gid=1234567891, sender_gid=1234567890): + gr.top_block.__init__(self, "Gotenna Pro Tx Usrp", catch_exceptions=True) + + ################################################## + # Parameters + ################################################## + self.baud_rate = baud_rate + self.callsign = callsign + self.counter_num = counter_num + self.device_addr = device_addr + self.frequency = frequency + self.message = message + self.message_type = message_type + self.publickey_data = publickey_data + self.recipient_gid = recipient_gid + self.sender_gid = sender_gid + + ################################################## + # Variables + ################################################## + self.samp_per_sym = samp_per_sym = 4 + self.offset = offset = 250000 + self.interp = interp = 480000 // baud_rate + self.taps = taps = firdes.gaussian(1.0, samp_per_sym, 0.5, 64) + self.samp_rate = samp_rate = baud_rate * samp_per_sym * interp + self.packets = packets = gotenna_packet.encode_pro_broadcast_packets(message_type, counter_num, sender_gid, recipient_gid, callsign, message, publickey_data) + self.fsk_deviation_hz = fsk_deviation_hz = {2400: 400, 4800: 750, 9600: 1100}[baud_rate] + self.data_chan = data_chan = 2 + self.control_chan = control_chan = 2 + self.center_freq = center_freq = frequency - offset + + ################################################## + # Blocks + ################################################## + self.uhd_usrp_sink_0 = uhd.usrp_sink( + ",".join((device_addr, "")), + uhd.stream_args( + cpu_format="fc32", + args='', + channels=list(range(0,1)), + ), + '', + ) + self.uhd_usrp_sink_0.set_samp_rate(samp_rate) + self.uhd_usrp_sink_0.set_time_unknown_pps(uhd.time_spec(0)) + + self.uhd_usrp_sink_0.set_center_freq(center_freq, 0) + self.uhd_usrp_sink_0.set_antenna("TX/RX", 0) + self.uhd_usrp_sink_0.set_gain(70, 0) + self.rational_resampler_xxx_0 = filter.rational_resampler_ccc( + interpolation=interp, + decimation=1, + taps=[], + fractional_bw=0) + self.interp_fir_filter_xxx_0 = filter.interp_fir_filter_fff(1, taps) + self.interp_fir_filter_xxx_0.declare_sample_delay(0) + self.digital_map_bb_0 = digital.map_bb([-3, -1, 3, 1, 0]) + self.blocks_vector_source_x_2 = blocks.vector_source_f([offset], True, 1, []) + self.blocks_vector_source_x_1 = blocks.vector_source_c([1], True, 1, []) + self.blocks_vector_source_x_0 = blocks.vector_source_b(gotenna_packet.pro_gfsk_symbols(packets), False, 1, []) + self.blocks_vco_c_1 = blocks.vco_c((baud_rate * samp_per_sym), (2 * math.pi * fsk_deviation_hz), 1.0) + self.blocks_vco_c_0 = blocks.vco_c(samp_rate, (2*math.pi), 0.9) + self.blocks_repeat_2 = blocks.repeat(gr.sizeof_float*1, samp_per_sym) + self.blocks_repeat_1 = blocks.repeat(gr.sizeof_float*1, (8 * samp_per_sym * interp)) + self.blocks_repeat_0 = blocks.repeat(gr.sizeof_gr_complex*1, (8 * samp_per_sym)) + self.blocks_multiply_xx_1 = blocks.multiply_vcc(1) + self.blocks_multiply_xx_0 = blocks.multiply_vcc(1) + self.blocks_char_to_float_0 = blocks.char_to_float(1, 1) + + + ################################################## + # Connections + ################################################## + self.connect((self.blocks_char_to_float_0, 0), (self.blocks_repeat_2, 0)) + self.connect((self.blocks_multiply_xx_0, 0), (self.rational_resampler_xxx_0, 0)) + self.connect((self.blocks_multiply_xx_1, 0), (self.uhd_usrp_sink_0, 0)) + self.connect((self.blocks_repeat_0, 0), (self.blocks_multiply_xx_0, 1)) + self.connect((self.blocks_repeat_1, 0), (self.blocks_vco_c_0, 0)) + self.connect((self.blocks_repeat_2, 0), (self.interp_fir_filter_xxx_0, 0)) + self.connect((self.blocks_vco_c_0, 0), (self.blocks_multiply_xx_1, 1)) + self.connect((self.blocks_vco_c_1, 0), (self.blocks_multiply_xx_0, 0)) + self.connect((self.blocks_vector_source_x_0, 0), (self.digital_map_bb_0, 0)) + self.connect((self.blocks_vector_source_x_1, 0), (self.blocks_repeat_0, 0)) + self.connect((self.blocks_vector_source_x_2, 0), (self.blocks_repeat_1, 0)) + self.connect((self.digital_map_bb_0, 0), (self.blocks_char_to_float_0, 0)) + self.connect((self.interp_fir_filter_xxx_0, 0), (self.blocks_vco_c_1, 0)) + self.connect((self.rational_resampler_xxx_0, 0), (self.blocks_multiply_xx_1, 0)) + + + def get_baud_rate(self): + return self.baud_rate + + def set_baud_rate(self, baud_rate): + self.baud_rate = baud_rate + self.set_fsk_deviation_hz({2400: 400, 4800: 750, 9600: 1100}[self.baud_rate]) + self.set_interp(480000 // self.baud_rate) + self.set_samp_rate(self.baud_rate * self.samp_per_sym * self.interp) + + def get_callsign(self): + return self.callsign + + def set_callsign(self, callsign): + self.callsign = callsign + self.set_packets(gotenna_packet.encode_pro_broadcast_packets(self.message_type, self.counter_num, self.sender_gid, self.recipient_gid, self.callsign, self.message, self.publickey_data)) + + def get_counter_num(self): + return self.counter_num + + def set_counter_num(self, counter_num): + self.counter_num = counter_num + self.set_packets(gotenna_packet.encode_pro_broadcast_packets(self.message_type, self.counter_num, self.sender_gid, self.recipient_gid, self.callsign, self.message, self.publickey_data)) + + def get_device_addr(self): + return self.device_addr + + def set_device_addr(self, device_addr): + self.device_addr = device_addr + + def get_frequency(self): + return self.frequency + + def set_frequency(self, frequency): + self.frequency = frequency + self.set_center_freq(self.frequency - self.offset) + + def get_message(self): + return self.message + + def set_message(self, message): + self.message = message + self.set_packets(gotenna_packet.encode_pro_broadcast_packets(self.message_type, self.counter_num, self.sender_gid, self.recipient_gid, self.callsign, self.message, self.publickey_data)) + + def get_message_type(self): + return self.message_type + + def set_message_type(self, message_type): + self.message_type = message_type + self.set_packets(gotenna_packet.encode_pro_broadcast_packets(self.message_type, self.counter_num, self.sender_gid, self.recipient_gid, self.callsign, self.message, self.publickey_data)) + + def get_publickey_data(self): + return self.publickey_data + + def set_publickey_data(self, publickey_data): + self.publickey_data = publickey_data + self.set_packets(gotenna_packet.encode_pro_broadcast_packets(self.message_type, self.counter_num, self.sender_gid, self.recipient_gid, self.callsign, self.message, self.publickey_data)) + + def get_recipient_gid(self): + return self.recipient_gid + + def set_recipient_gid(self, recipient_gid): + self.recipient_gid = recipient_gid + self.set_packets(gotenna_packet.encode_pro_broadcast_packets(self.message_type, self.counter_num, self.sender_gid, self.recipient_gid, self.callsign, self.message, self.publickey_data)) + + def get_sender_gid(self): + return self.sender_gid + + def set_sender_gid(self, sender_gid): + self.sender_gid = sender_gid + self.set_packets(gotenna_packet.encode_pro_broadcast_packets(self.message_type, self.counter_num, self.sender_gid, self.recipient_gid, self.callsign, self.message, self.publickey_data)) + + def get_samp_per_sym(self): + return self.samp_per_sym + + def set_samp_per_sym(self, samp_per_sym): + self.samp_per_sym = samp_per_sym + self.set_samp_rate(self.baud_rate * self.samp_per_sym * self.interp) + self.set_taps(firdes.gaussian(1.0, self.samp_per_sym, 0.5, 64)) + self.blocks_repeat_0.set_interpolation((8 * self.samp_per_sym)) + self.blocks_repeat_1.set_interpolation((8 * self.samp_per_sym * self.interp)) + self.blocks_repeat_2.set_interpolation(self.samp_per_sym) + + def get_offset(self): + return self.offset + + def set_offset(self, offset): + self.offset = offset + self.set_center_freq(self.frequency - self.offset) + self.blocks_vector_source_x_2.set_data([self.offset], []) + + def get_interp(self): + return self.interp + + def set_interp(self, interp): + self.interp = interp + self.set_samp_rate(self.baud_rate * self.samp_per_sym * self.interp) + self.blocks_repeat_1.set_interpolation((8 * self.samp_per_sym * self.interp)) + + def get_taps(self): + return self.taps + + def set_taps(self, taps): + self.taps = taps + self.interp_fir_filter_xxx_0.set_taps(self.taps) + + def get_samp_rate(self): + return self.samp_rate + + def set_samp_rate(self, samp_rate): + self.samp_rate = samp_rate + self.uhd_usrp_sink_0.set_samp_rate(self.samp_rate) + + def get_packets(self): + return self.packets + + def set_packets(self, packets): + self.packets = packets + self.blocks_vector_source_x_0.set_data(gotenna_packet.pro_gfsk_symbols(self.packets), []) + + def get_fsk_deviation_hz(self): + return self.fsk_deviation_hz + + def set_fsk_deviation_hz(self, fsk_deviation_hz): + self.fsk_deviation_hz = fsk_deviation_hz + + def get_data_chan(self): + return self.data_chan + + def set_data_chan(self, data_chan): + self.data_chan = data_chan + + def get_control_chan(self): + return self.control_chan + + def set_control_chan(self, control_chan): + self.control_chan = control_chan + + def get_center_freq(self): + return self.center_freq + + def set_center_freq(self, center_freq): + self.center_freq = center_freq + self.uhd_usrp_sink_0.set_center_freq(self.center_freq, 0) + + + +def argument_parser(): + parser = ArgumentParser() + parser.add_argument( + "--baud-rate", dest="baud_rate", type=intx, default=9600, + help="Set Baud rate [default=%(default)r]") + parser.add_argument( + "--callsign", dest="callsign", type=str, default='VE3IRR', + help="Set Sender callsign [default=%(default)r]") + parser.add_argument( + "--counter-num", dest="counter_num", type=intx, default=0, + help="Set Counter [default=%(default)r]") + parser.add_argument( + "--device-addr", dest="device_addr", type=str, default='', + help="Set UHD device address [default=%(default)r]") + parser.add_argument( + "--frequency", dest="frequency", type=eng_float, default=eng_notation.num_to_str(float(450000000)), + help="Set Frequency [default=%(default)r]") + parser.add_argument( + "--message", dest="message", type=str, default='Hello world!', + help="Set Message [default=%(default)r]") + parser.add_argument( + "--message-type", dest="message_type", type=str, default='BROADCAST', + help="Set type [default=%(default)r]") + parser.add_argument( + "--publickey-data", dest="publickey_data", type=str, default='base64key', + help="Set Sender Public Key [default=%(default)r]") + parser.add_argument( + "--recipient-gid", dest="recipient_gid", type=intx, default=1234567891, + help="Set Recipient GID [default=%(default)r]") + parser.add_argument( + "--sender-gid", dest="sender_gid", type=intx, default=1234567890, + help="Set Sender GID [default=%(default)r]") + return parser + + +def main(top_block_cls=gotenna_pro_tx_usrp, options=None): + if options is None: + options = argument_parser().parse_args() + tb = top_block_cls(baud_rate=options.baud_rate, callsign=options.callsign, counter_num=options.counter_num, device_addr=options.device_addr, frequency=options.frequency, message=options.message, message_type=options.message_type, publickey_data=options.publickey_data, recipient_gid=options.recipient_gid, sender_gid=options.sender_gid) + + #def sig_handler(sig=None, frame=None): + # tb.stop() + # tb.wait() + + # sys.exit(0) + + #signal.signal(signal.SIGINT, sig_handler) + #signal.signal(signal.SIGTERM, sig_handler) + + tb.start() + + tb.wait() + + +if __name__ == '__main__': + main() diff --git a/flags.txt.ci b/flags.txt.ci index 6a87785..2fcf093 100644 --- a/flags.txt.ci +++ b/flags.txt.ci @@ -5,3 +5,4 @@ testflagsfile,1660312800,1660496400 3,SDR_ASK_1,The Silence of the Lambs was filmed in Pittsburgh Pennsylvania.,ask,,,60,90,ham_440,, 4,POCSAG_RX,The Clock That Went Backward,pocsag,198468,,60,90,444500,, 5,LRS_RX,-s 20 -p 238 -pf 1,lrs,,,60,90,467750,, +6,GOTENNA_PRO,RFCTF{gotenna_pro_test},gotenna_pro,"--callsign RFCTF --sender-gid 1234567890 --recipient-gid 1234567891 --baud-rate 9600 --message-type BROADCAST --counter-num 0",,60,90,450000,,