From b2dbe95d2f053aa18773274e52b42a32259a0a8c Mon Sep 17 00:00:00 2001 From: Brandon Rozek Date: Sun, 2 Jun 2019 10:46:00 -0400 Subject: [PATCH] Added gnuradio flowgraph in case people are curious. Added the start script which controls the flow of the server application. Still need to add functionality to listen to audio in the client side. They will need to listen to serverip:6003 --- radio_tuner.grc | 1774 +++++++++++++++++++++++++++++++++++++++++++++++ start | 24 + tuner.py | 124 ++-- 3 files changed, 1872 insertions(+), 50 deletions(-) create mode 100644 radio_tuner.grc create mode 100755 start diff --git a/radio_tuner.grc b/radio_tuner.grc new file mode 100644 index 0000000..feed17f --- /dev/null +++ b/radio_tuner.grc @@ -0,0 +1,1774 @@ + + + + Wed May 8 18:18:26 2019 + + options + + author + + + + window_size + + + + category + [GRC Hier Blocks] + + + comment + + + + description + + + + _enabled + True + + + _coordinate + (8, 8) + + + _rotation + 0 + + + generate_options + no_gui + + + hier_block_src_path + .: + + + id + top_block + + + max_nouts + 0 + + + qt_qss_theme + + + + realtime_scheduling + + + + run_command + {python} -u {filename} + + + run_options + prompt + + + run + True + + + thread_safe_setters + + + + title + + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (272, 16) + + + _rotation + 0 + + + id + audio_interp + + + value + 4 + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (376, 16) + + + _rotation + 0 + + + id + audio_rate + + + value + 48000 + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (472, 16) + + + _rotation + 0 + + + id + freq + + + value + 101.5e6 + + + + variable + + comment + + + + _enabled + True + + + _coordinate + (176, 16) + + + _rotation + 0 + + + id + samp_rate + + + value + 2.2e6 + + + + analog_wfm_rcv + + audio_decimation + audio_interp + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (472, 208) + + + _rotation + 0 + + + id + analog_wfm_rcv_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + quad_rate + audio_rate * audio_interp + + + + blocks_file_sink + + append + False + + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + file + raw_audio_pipe + + + _coordinate + (672, 200) + + + _rotation + 0 + + + id + blocks_file_sink_0 + + + type + float + + + unbuffered + False + + + vlen + 1 + + + + rational_resampler_xxx + + alias + + + + comment + + + + affinity + + + + decim + int(samp_rate) + + + _enabled + True + + + fbw + 0 + + + _coordinate + (288, 192) + + + _rotation + 0 + + + id + rational_resampler_xxx_0 + + + interp + audio_rate * audio_interp + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + taps + + + + type + ccc + + + + rtlsdr_source + + alias + + + + ant0 + + + + bb_gain0 + 0 + + + bw0 + 0 + + + dc_offset_mode0 + 2 + + + corr0 + 0 + + + freq0 + freq + + + gain_mode0 + True + + + if_gain0 + 0 + + + iq_balance_mode0 + 2 + + + gain0 + 0 + + + ant10 + + + + bb_gain10 + 20 + + + bw10 + 0 + + + dc_offset_mode10 + 0 + + + corr10 + 0 + + + freq10 + 100e6 + + + gain_mode10 + False + + + if_gain10 + 20 + + + iq_balance_mode10 + 0 + + + gain10 + 10 + + + ant11 + + + + bb_gain11 + 20 + + + bw11 + 0 + + + dc_offset_mode11 + 0 + + + corr11 + 0 + + + freq11 + 100e6 + + + gain_mode11 + False + + + if_gain11 + 20 + + + iq_balance_mode11 + 0 + + + gain11 + 10 + + + ant12 + + + + bb_gain12 + 20 + + + bw12 + 0 + + + dc_offset_mode12 + 0 + + + corr12 + 0 + + + freq12 + 100e6 + + + gain_mode12 + False + + + if_gain12 + 20 + + + iq_balance_mode12 + 0 + + + gain12 + 10 + + + ant13 + + + + bb_gain13 + 20 + + + bw13 + 0 + + + dc_offset_mode13 + 0 + + + corr13 + 0 + + + freq13 + 100e6 + + + gain_mode13 + False + + + if_gain13 + 20 + + + iq_balance_mode13 + 0 + + + gain13 + 10 + + + ant14 + + + + bb_gain14 + 20 + + + bw14 + 0 + + + dc_offset_mode14 + 0 + + + corr14 + 0 + + + freq14 + 100e6 + + + gain_mode14 + False + + + if_gain14 + 20 + + + iq_balance_mode14 + 0 + + + gain14 + 10 + + + ant15 + + + + bb_gain15 + 20 + + + bw15 + 0 + + + dc_offset_mode15 + 0 + + + corr15 + 0 + + + freq15 + 100e6 + + + gain_mode15 + False + + + if_gain15 + 20 + + + iq_balance_mode15 + 0 + + + gain15 + 10 + + + ant16 + + + + bb_gain16 + 20 + + + bw16 + 0 + + + dc_offset_mode16 + 0 + + + corr16 + 0 + + + freq16 + 100e6 + + + gain_mode16 + False + + + if_gain16 + 20 + + + iq_balance_mode16 + 0 + + + gain16 + 10 + + + ant17 + + + + bb_gain17 + 20 + + + bw17 + 0 + + + dc_offset_mode17 + 0 + + + corr17 + 0 + + + freq17 + 100e6 + + + gain_mode17 + False + + + if_gain17 + 20 + + + iq_balance_mode17 + 0 + + + gain17 + 10 + + + ant18 + + + + bb_gain18 + 20 + + + bw18 + 0 + + + dc_offset_mode18 + 0 + + + corr18 + 0 + + + freq18 + 100e6 + + + gain_mode18 + False + + + if_gain18 + 20 + + + iq_balance_mode18 + 0 + + + gain18 + 10 + + + ant19 + + + + bb_gain19 + 20 + + + bw19 + 0 + + + dc_offset_mode19 + 0 + + + corr19 + 0 + + + freq19 + 100e6 + + + gain_mode19 + False + + + if_gain19 + 20 + + + iq_balance_mode19 + 0 + + + gain19 + 10 + + + ant1 + + + + bb_gain1 + 20 + + + bw1 + 0 + + + dc_offset_mode1 + 0 + + + corr1 + 0 + + + freq1 + 100e6 + + + gain_mode1 + False + + + if_gain1 + 20 + + + iq_balance_mode1 + 0 + + + gain1 + 10 + + + ant20 + + + + bb_gain20 + 20 + + + bw20 + 0 + + + dc_offset_mode20 + 0 + + + corr20 + 0 + + + freq20 + 100e6 + + + gain_mode20 + False + + + if_gain20 + 20 + + + iq_balance_mode20 + 0 + + + gain20 + 10 + + + ant21 + + + + bb_gain21 + 20 + + + bw21 + 0 + + + dc_offset_mode21 + 0 + + + corr21 + 0 + + + freq21 + 100e6 + + + gain_mode21 + False + + + if_gain21 + 20 + + + iq_balance_mode21 + 0 + + + gain21 + 10 + + + ant22 + + + + bb_gain22 + 20 + + + bw22 + 0 + + + dc_offset_mode22 + 0 + + + corr22 + 0 + + + freq22 + 100e6 + + + gain_mode22 + False + + + if_gain22 + 20 + + + iq_balance_mode22 + 0 + + + gain22 + 10 + + + ant23 + + + + bb_gain23 + 20 + + + bw23 + 0 + + + dc_offset_mode23 + 0 + + + corr23 + 0 + + + freq23 + 100e6 + + + gain_mode23 + False + + + if_gain23 + 20 + + + iq_balance_mode23 + 0 + + + gain23 + 10 + + + ant24 + + + + bb_gain24 + 20 + + + bw24 + 0 + + + dc_offset_mode24 + 0 + + + corr24 + 0 + + + freq24 + 100e6 + + + gain_mode24 + False + + + if_gain24 + 20 + + + iq_balance_mode24 + 0 + + + gain24 + 10 + + + ant25 + + + + bb_gain25 + 20 + + + bw25 + 0 + + + dc_offset_mode25 + 0 + + + corr25 + 0 + + + freq25 + 100e6 + + + gain_mode25 + False + + + if_gain25 + 20 + + + iq_balance_mode25 + 0 + + + gain25 + 10 + + + ant26 + + + + bb_gain26 + 20 + + + bw26 + 0 + + + dc_offset_mode26 + 0 + + + corr26 + 0 + + + freq26 + 100e6 + + + gain_mode26 + False + + + if_gain26 + 20 + + + iq_balance_mode26 + 0 + + + gain26 + 10 + + + ant27 + + + + bb_gain27 + 20 + + + bw27 + 0 + + + dc_offset_mode27 + 0 + + + corr27 + 0 + + + freq27 + 100e6 + + + gain_mode27 + False + + + if_gain27 + 20 + + + iq_balance_mode27 + 0 + + + gain27 + 10 + + + ant28 + + + + bb_gain28 + 20 + + + bw28 + 0 + + + dc_offset_mode28 + 0 + + + corr28 + 0 + + + freq28 + 100e6 + + + gain_mode28 + False + + + if_gain28 + 20 + + + iq_balance_mode28 + 0 + + + gain28 + 10 + + + ant29 + + + + bb_gain29 + 20 + + + bw29 + 0 + + + dc_offset_mode29 + 0 + + + corr29 + 0 + + + freq29 + 100e6 + + + gain_mode29 + False + + + if_gain29 + 20 + + + iq_balance_mode29 + 0 + + + gain29 + 10 + + + ant2 + + + + bb_gain2 + 20 + + + bw2 + 0 + + + dc_offset_mode2 + 0 + + + corr2 + 0 + + + freq2 + 100e6 + + + gain_mode2 + False + + + if_gain2 + 20 + + + iq_balance_mode2 + 0 + + + gain2 + 10 + + + ant30 + + + + bb_gain30 + 20 + + + bw30 + 0 + + + dc_offset_mode30 + 0 + + + corr30 + 0 + + + freq30 + 100e6 + + + gain_mode30 + False + + + if_gain30 + 20 + + + iq_balance_mode30 + 0 + + + gain30 + 10 + + + ant31 + + + + bb_gain31 + 20 + + + bw31 + 0 + + + dc_offset_mode31 + 0 + + + corr31 + 0 + + + freq31 + 100e6 + + + gain_mode31 + False + + + if_gain31 + 20 + + + iq_balance_mode31 + 0 + + + gain31 + 10 + + + ant3 + + + + bb_gain3 + 20 + + + bw3 + 0 + + + dc_offset_mode3 + 0 + + + corr3 + 0 + + + freq3 + 100e6 + + + gain_mode3 + False + + + if_gain3 + 20 + + + iq_balance_mode3 + 0 + + + gain3 + 10 + + + ant4 + + + + bb_gain4 + 20 + + + bw4 + 0 + + + dc_offset_mode4 + 0 + + + corr4 + 0 + + + freq4 + 100e6 + + + gain_mode4 + False + + + if_gain4 + 20 + + + iq_balance_mode4 + 0 + + + gain4 + 10 + + + ant5 + + + + bb_gain5 + 20 + + + bw5 + 0 + + + dc_offset_mode5 + 0 + + + corr5 + 0 + + + freq5 + 100e6 + + + gain_mode5 + False + + + if_gain5 + 20 + + + iq_balance_mode5 + 0 + + + gain5 + 10 + + + ant6 + + + + bb_gain6 + 20 + + + bw6 + 0 + + + dc_offset_mode6 + 0 + + + corr6 + 0 + + + freq6 + 100e6 + + + gain_mode6 + False + + + if_gain6 + 20 + + + iq_balance_mode6 + 0 + + + gain6 + 10 + + + ant7 + + + + bb_gain7 + 20 + + + bw7 + 0 + + + dc_offset_mode7 + 0 + + + corr7 + 0 + + + freq7 + 100e6 + + + gain_mode7 + False + + + if_gain7 + 20 + + + iq_balance_mode7 + 0 + + + gain7 + 10 + + + ant8 + + + + bb_gain8 + 20 + + + bw8 + 0 + + + dc_offset_mode8 + 0 + + + corr8 + 0 + + + freq8 + 100e6 + + + gain_mode8 + False + + + if_gain8 + 20 + + + iq_balance_mode8 + 0 + + + gain8 + 10 + + + ant9 + + + + bb_gain9 + 20 + + + bw9 + 0 + + + dc_offset_mode9 + 0 + + + corr9 + 0 + + + freq9 + 100e6 + + + gain_mode9 + False + + + if_gain9 + 20 + + + iq_balance_mode9 + 0 + + + gain9 + 10 + + + comment + + + + affinity + + + + args + + + + _enabled + True + + + _coordinate + (40, 148) + + + _rotation + 0 + + + id + rtlsdr_source_0 + + + maxoutbuf + 0 + + + clock_source0 + + + + time_source0 + + + + clock_source1 + + + + time_source1 + + + + clock_source2 + + + + time_source2 + + + + clock_source3 + + + + time_source3 + + + + clock_source4 + + + + time_source4 + + + + clock_source5 + + + + time_source5 + + + + clock_source6 + + + + time_source6 + + + + clock_source7 + + + + time_source7 + + + + minoutbuf + 0 + + + nchan + 1 + + + num_mboards + 1 + + + type + fc32 + + + sample_rate + samp_rate + + + sync + + + + + analog_wfm_rcv_0 + blocks_file_sink_0 + 0 + 0 + + + rational_resampler_xxx_0 + analog_wfm_rcv_0 + 0 + 0 + + + rtlsdr_source_0 + rational_resampler_xxx_0 + 0 + 0 + + diff --git a/start b/start new file mode 100755 index 0000000..0cbac1b --- /dev/null +++ b/start @@ -0,0 +1,24 @@ +#!/bin/bash +compress=1 + +function cleanup() { + echo "Shutting Down" + rm ./raw_audio_pipe + kill $child_pid +} + +mkfifo ./raw_audio_pipe + +# Run Radio Server Program in Background +./tuner.py & +child_pid=$! + +if [ $compress -eq 1 ] +then + ffmpeg -f f32le -ar 48k -ac 1 -i pipe:0 -f ogg -ab 32k pipe:1 < ./raw_audio_pipe | nc -kl 127.0.0.1 6003 + +else + tail -f raw_audio_pipe | nc -kl 127.0.0.1 6003 +fi + +cleanup diff --git a/tuner.py b/tuner.py index 37691a1..23bad10 100755 --- a/tuner.py +++ b/tuner.py @@ -3,12 +3,11 @@ ################################################## # GNU Radio Python Flow Graph # Title: Top Block -# Generated: Sun May 12 22:10:45 2019 +# Generated: Sat Jun 1 12:54:09 2019 ################################################## from gnuradio import analog -from gnuradio import audio from gnuradio import blocks from gnuradio import eng_notation from gnuradio import filter @@ -21,6 +20,7 @@ import time import socket import re + class top_block(gr.top_block): def __init__(self): @@ -29,15 +29,17 @@ class top_block(gr.top_block): ################################################## # Variables ################################################## - self.samp_rate = samp_rate = 1536000 - self.frequency = frequency = 96900000 + self.samp_rate = samp_rate = 2.2e6 + self.freq = freq = 101.5e6 + self.audio_rate = audio_rate = 48000 + self.audio_interp = audio_interp = 4 ################################################## # Blocks ################################################## self.rtlsdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + '' ) self.rtlsdr_source_0.set_sample_rate(samp_rate) - self.rtlsdr_source_0.set_center_freq(frequency, 0) + self.rtlsdr_source_0.set_center_freq(freq, 0) self.rtlsdr_source_0.set_freq_corr(0, 0) self.rtlsdr_source_0.set_dc_offset_mode(2, 0) self.rtlsdr_source_0.set_iq_balance_mode(2, 0) @@ -48,22 +50,25 @@ class top_block(gr.top_block): self.rtlsdr_source_0.set_antenna('', 0) self.rtlsdr_source_0.set_bandwidth(0, 0) - self.low_pass_filter_0 = filter.fir_filter_ccf(4, firdes.low_pass( - 1, samp_rate, 500000, 60000, firdes.WIN_KAISER, 6.76)) - self.blocks_udp_sink_0 = blocks.udp_sink(gr.sizeof_float*1, '127.0.0.1', 7654, 1472, True) - self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, samp_rate,True) + self.rational_resampler_xxx_0 = filter.rational_resampler_ccc( + interpolation=audio_rate * audio_interp, + decimation=int(samp_rate), + taps=None, + fractional_bw=None, + ) + self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_float*1, 'raw_audio_pipe', False) + self.blocks_file_sink_0.set_unbuffered(False) self.analog_wfm_rcv_0 = analog.wfm_rcv( - quad_rate=384000, - audio_decimation=8, + quad_rate=audio_rate * audio_interp, + audio_decimation=audio_interp, ) ################################################## # Connections ################################################## - self.connect((self.analog_wfm_rcv_0, 0), (self.blocks_udp_sink_0, 0)) - self.connect((self.blocks_throttle_0, 0), (self.low_pass_filter_0, 0)) - self.connect((self.low_pass_filter_0, 0), (self.analog_wfm_rcv_0, 0)) - self.connect((self.rtlsdr_source_0, 0), (self.blocks_throttle_0, 0)) + self.connect((self.analog_wfm_rcv_0, 0), (self.blocks_file_sink_0, 0)) + self.connect((self.rational_resampler_xxx_0, 0), (self.analog_wfm_rcv_0, 0)) + self.connect((self.rtlsdr_source_0, 0), (self.rational_resampler_xxx_0, 0)) def get_samp_rate(self): return self.samp_rate @@ -71,20 +76,64 @@ class top_block(gr.top_block): def set_samp_rate(self, samp_rate): self.samp_rate = samp_rate self.rtlsdr_source_0.set_sample_rate(self.samp_rate) - self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.samp_rate, 500000, 60000, firdes.WIN_KAISER, 6.76)) - self.blocks_throttle_0.set_sample_rate(self.samp_rate) - def get_frequency(self): - return self.frequency + def get_freq(self): + return self.freq - def set_frequency(self, frequency): - self.frequency = frequency - self.rtlsdr_source_0.set_center_freq(self.frequency, 0) + def set_freq(self, freq): + self.freq = freq + self.rtlsdr_source_0.set_center_freq(self.freq, 0) + + def get_audio_rate(self): + return self.audio_rate + + def set_audio_rate(self, audio_rate): + self.audio_rate = audio_rate + + def get_audio_interp(self): + return self.audio_interp + + def set_audio_interp(self, audio_interp): + self.audio_interp = audio_interp + +def is_valid_frequency(frequency): + return frequency >= 87500000 and frequency <= 108000000 + +def parse_commands(conn, tb, commands): + quit = False + for command in commands: + if command == "": + continue + elif command[0] == '?': # Query Section + if command[1:] == "VER": + conn.sendall("Version 0.1\n") + elif command[1:] == "FREQ": + conn.sendall(str(tb.get_freq()) + '\n') + else: + print("UNKNOWN COMMAND: ", command) + elif command[0] == ':': # Setter Section + if command[1:5] == "FREQ": + print("FREQUENCY SET") + frequency = float(command[6:]) + if is_valid_frequency(frequency): + tb.set_freq(frequency) + else: + print("ERROR: Invalid Frequency ", frequency) + elif command[1:] == "QUIT": + print("QUITTING") + quit = True + else: + print("UNKNOWN COMMAND: ", command) + else: + print("UNKNOWN COMMAND", command) + # Return state back to application + return {'quit': quit} def main(top_block_cls=top_block, options=None): tb = top_block_cls() tb.start() + HOST = '127.0.0.1' # Loopback Address (Localhost) PORT = 65432 # Semi-Random Port that is non-priviledged (> 1023) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -103,34 +152,9 @@ def main(top_block_cls=top_block, options=None): commands = re.split(";", data) if data == "": break - for command in commands: - if command == "": - continue - elif command[0] == '?': - # Query Section - if command[1:] == "VER": - conn.sendall("Version 0.1\n") - elif command[1:] == "FREQ": - conn.sendall(str(tb.get_frequency()) + '\n') - else: - print("UNKNOWN COMMAND: ", command) - elif command[0] == ':': - # Setter Section - if command[1:5] == "FREQ": - print("FREQUENCY SET") - frequency = float(command[6:]) - if frequency >= 87500000 and frequency <= 108000000: - tb.set_frequency(frequency) - else: - print("ERROR: Invalid Frequency ", frequency) - elif command[1:] == "QUIT": - print("QUITTING") - quit = True - else: - print("UNKNOWN COMMAND: ", command) - else: - print("UNKNOWN COMMAND", command) - + state = parse_commands(conn, tb, commands) + if state['quit']: + quit = True conn.close() s.close()