blob: d4376e4148b34d57dda9cb20920702ec3cd1b3a7 [file] [log] [blame]
Piotr Krysik35582082015-09-02 21:49:12 +02001#!/usr/bin/env python2
Piotr Krysik6577ec22016-07-15 13:21:09 +02002# -*- coding: utf-8 -*-
Piotr Krysik35582082015-09-02 21:49:12 +02003##################################################
4# GNU Radio Python Flow Graph
Piotr Krysik332e0b52016-02-13 18:37:32 +01005# Title: Gr-gsm Livemon
Piotr Krysik6577ec22016-07-15 13:21:09 +02006# Author: Piotr Krysik
7# Description: Interactive monitor of a single C0 channel with analysis performed by Wireshark (command to run wireshark: sudo wireshark -k -f udp -Y gsmtap -i lo)
Piotr Krysikfe538eb2016-07-18 18:14:49 +02008# Generated: Mon Jul 18 18:08:34 2016
Piotr Krysik35582082015-09-02 21:49:12 +02009##################################################
10
11if __name__ == '__main__':
12 import ctypes
13 import sys
14 if sys.platform.startswith('linux'):
15 try:
16 x11 = ctypes.cdll.LoadLibrary('libX11.so')
17 x11.XInitThreads()
18 except:
19 print "Warning: failed to XInitThreads()"
20
21from PyQt4 import Qt
22from gnuradio import blocks
23from gnuradio import eng_notation
24from gnuradio import gr
25from gnuradio import qtgui
26from gnuradio.eng_option import eng_option
27from gnuradio.filter import firdes
28from gnuradio.qtgui import Range, RangeWidget
29from math import pi
30from optparse import OptionParser
31import grgsm
32import osmosdr
33import pmt
34import sip
35import sys
36import time
37
38
Piotr Krysik332e0b52016-02-13 18:37:32 +010039class grgsm_livemon(gr.top_block, Qt.QWidget):
Piotr Krysik35582082015-09-02 21:49:12 +020040
Piotr Krysikfe538eb2016-07-18 18:14:49 +020041 def __init__(self, args="", fc=939.4e6, gain=30, ppm=0, samp_rate=2000000.052982, shiftoff=400e3, osr=4):
Piotr Krysik332e0b52016-02-13 18:37:32 +010042 gr.top_block.__init__(self, "Gr-gsm Livemon")
Piotr Krysik35582082015-09-02 21:49:12 +020043 Qt.QWidget.__init__(self)
Piotr Krysik332e0b52016-02-13 18:37:32 +010044 self.setWindowTitle("Gr-gsm Livemon")
Piotr Krysik35582082015-09-02 21:49:12 +020045 try:
Piotr Krysik6577ec22016-07-15 13:21:09 +020046 self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
Piotr Krysik35582082015-09-02 21:49:12 +020047 except:
Piotr Krysik6577ec22016-07-15 13:21:09 +020048 pass
Piotr Krysik35582082015-09-02 21:49:12 +020049 self.top_scroll_layout = Qt.QVBoxLayout()
50 self.setLayout(self.top_scroll_layout)
51 self.top_scroll = Qt.QScrollArea()
52 self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
53 self.top_scroll_layout.addWidget(self.top_scroll)
54 self.top_scroll.setWidgetResizable(True)
55 self.top_widget = Qt.QWidget()
56 self.top_scroll.setWidget(self.top_widget)
57 self.top_layout = Qt.QVBoxLayout(self.top_widget)
58 self.top_grid_layout = Qt.QGridLayout()
59 self.top_layout.addLayout(self.top_grid_layout)
60
Piotr Krysik332e0b52016-02-13 18:37:32 +010061 self.settings = Qt.QSettings("GNU Radio", "grgsm_livemon")
Piotr Krysik35582082015-09-02 21:49:12 +020062 self.restoreGeometry(self.settings.value("geometry").toByteArray())
63
64 ##################################################
65 # Parameters
66 ##################################################
Piotr Krysik6577ec22016-07-15 13:21:09 +020067 self.args = args
Piotr Krysik35582082015-09-02 21:49:12 +020068 self.fc = fc
69 self.gain = gain
70 self.ppm = ppm
71 self.samp_rate = samp_rate
72 self.shiftoff = shiftoff
Piotr Krysikfe538eb2016-07-18 18:14:49 +020073 self.osr = osr
Piotr Krysik35582082015-09-02 21:49:12 +020074
75 ##################################################
76 # Variables
77 ##################################################
78 self.ppm_slider = ppm_slider = ppm
79 self.g_slider = g_slider = gain
80 self.fc_slider = fc_slider = fc
81
82 ##################################################
83 # Blocks
84 ##################################################
85 self._ppm_slider_range = Range(-150, 150, 1, ppm, 100)
86 self._ppm_slider_win = RangeWidget(self._ppm_slider_range, self.set_ppm_slider, "PPM Offset", "counter", float)
87 self.top_layout.addWidget(self._ppm_slider_win)
88 self._g_slider_range = Range(0, 50, 0.5, gain, 100)
89 self._g_slider_win = RangeWidget(self._g_slider_range, self.set_g_slider, "Gain", "counter", float)
90 self.top_layout.addWidget(self._g_slider_win)
91 self._fc_slider_range = Range(925e6, 1990e6, 2e5, fc, 100)
92 self._fc_slider_win = RangeWidget(self._fc_slider_range, self.set_fc_slider, "Frequency", "counter_slider", float)
93 self.top_layout.addWidget(self._fc_slider_win)
Piotr Krysik7185b662016-02-14 20:24:54 +010094 self.rtlsdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + args )
Piotr Krysik35582082015-09-02 21:49:12 +020095 self.rtlsdr_source_0.set_sample_rate(samp_rate)
96 self.rtlsdr_source_0.set_center_freq(fc_slider-shiftoff, 0)
97 self.rtlsdr_source_0.set_freq_corr(ppm_slider, 0)
98 self.rtlsdr_source_0.set_dc_offset_mode(2, 0)
99 self.rtlsdr_source_0.set_iq_balance_mode(2, 0)
100 self.rtlsdr_source_0.set_gain_mode(False, 0)
101 self.rtlsdr_source_0.set_gain(g_slider, 0)
102 self.rtlsdr_source_0.set_if_gain(20, 0)
103 self.rtlsdr_source_0.set_bb_gain(20, 0)
104 self.rtlsdr_source_0.set_antenna("", 0)
105 self.rtlsdr_source_0.set_bandwidth(250e3+abs(shiftoff), 0)
106
107 self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c(
108 1024, #size
109 firdes.WIN_BLACKMAN_hARRIS, #wintype
110 fc_slider, #fc
111 samp_rate, #bw
112 "", #name
113 1 #number of inputs
114 )
115 self.qtgui_freq_sink_x_0.set_update_time(0.10)
116 self.qtgui_freq_sink_x_0.set_y_axis(-140, 10)
Piotr Krysik6577ec22016-07-15 13:21:09 +0200117 self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "")
118 self.qtgui_freq_sink_x_0.enable_autoscale(False)
119 self.qtgui_freq_sink_x_0.enable_grid(False)
120 self.qtgui_freq_sink_x_0.set_fft_average(1.0)
121 self.qtgui_freq_sink_x_0.enable_control_panel(False)
122
123 if not True:
124 self.qtgui_freq_sink_x_0.disable_legend()
125
126 if "complex" == "float" or "complex" == "msg_float":
127 self.qtgui_freq_sink_x_0.set_plot_pos_half(not True)
128
129 labels = ["", "", "", "", "",
130 "", "", "", "", ""]
131 widths = [1, 1, 1, 1, 1,
132 1, 1, 1, 1, 1]
133 colors = ["blue", "red", "green", "black", "cyan",
134 "magenta", "yellow", "dark red", "dark green", "dark blue"]
135 alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
136 1.0, 1.0, 1.0, 1.0, 1.0]
137 for i in xrange(1):
138 if len(labels[i]) == 0:
139 self.qtgui_freq_sink_x_0.set_line_label(i, "Data {0}".format(i))
140 else:
141 self.qtgui_freq_sink_x_0.set_line_label(i, labels[i])
142 self.qtgui_freq_sink_x_0.set_line_width(i, widths[i])
143 self.qtgui_freq_sink_x_0.set_line_color(i, colors[i])
144 self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i])
Piotr Krysik35582082015-09-02 21:49:12 +0200145
146 self._qtgui_freq_sink_x_0_win = sip.wrapinstance(self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget)
147 self.top_layout.addWidget(self._qtgui_freq_sink_x_0_win)
Piotr Krysik6577ec22016-07-15 13:21:09 +0200148 self.gsm_sdcch8_demapper_0 = grgsm.gsm_sdcch8_demapper(
149 timeslot_nr=1,
150 )
151 self.gsm_receiver_0 = grgsm.receiver(4, ([0]), ([]), False)
152 self.gsm_message_printer_1 = grgsm.message_printer(pmt.intern(""), False,
153 False, False)
Piotr Krysik35582082015-09-02 21:49:12 +0200154 self.gsm_input_0 = grgsm.gsm_input(
155 ppm=0,
156 osr=4,
157 fc=fc,
158 samp_rate_in=samp_rate,
159 )
160 self.gsm_decryption_0 = grgsm.decryption(([]), 1)
161 self.gsm_control_channels_decoder_0_0 = grgsm.control_channels_decoder()
162 self.gsm_control_channels_decoder_0 = grgsm.control_channels_decoder()
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200163 self.gsm_clock_offset_control_0 = grgsm.clock_offset_control(fc-shiftoff, samp_rate, osr)
Piotr Krysik6577ec22016-07-15 13:21:09 +0200164 self.gsm_bcch_ccch_demapper_0 = grgsm.gsm_bcch_ccch_demapper(
165 timeslot_nr=0,
166 )
167 self.blocks_socket_pdu_0_0 = blocks.socket_pdu("UDP_SERVER", "127.0.0.1", "4729", 10000, False)
168 self.blocks_socket_pdu_0 = blocks.socket_pdu("UDP_CLIENT", "127.0.0.1", "4729", 10000, False)
Piotr Krysik35582082015-09-02 21:49:12 +0200169 self.blocks_rotator_cc_0 = blocks.rotator_cc(-2*pi*shiftoff/samp_rate)
170
171 ##################################################
172 # Connections
173 ##################################################
174 self.msg_connect((self.gsm_bcch_ccch_demapper_0, 'bursts'), (self.gsm_control_channels_decoder_0, 'bursts'))
Piotr Krysik6577ec22016-07-15 13:21:09 +0200175 self.msg_connect((self.gsm_clock_offset_control_0, 'ctrl'), (self.gsm_input_0, 'ctrl_in'))
Piotr Krysik35582082015-09-02 21:49:12 +0200176 self.msg_connect((self.gsm_control_channels_decoder_0, 'msgs'), (self.blocks_socket_pdu_0, 'pdus'))
177 self.msg_connect((self.gsm_control_channels_decoder_0, 'msgs'), (self.gsm_message_printer_1, 'msgs'))
178 self.msg_connect((self.gsm_control_channels_decoder_0_0, 'msgs'), (self.blocks_socket_pdu_0, 'pdus'))
179 self.msg_connect((self.gsm_control_channels_decoder_0_0, 'msgs'), (self.gsm_message_printer_1, 'msgs'))
180 self.msg_connect((self.gsm_decryption_0, 'bursts'), (self.gsm_control_channels_decoder_0_0, 'bursts'))
181 self.msg_connect((self.gsm_receiver_0, 'C0'), (self.gsm_bcch_ccch_demapper_0, 'bursts'))
182 self.msg_connect((self.gsm_receiver_0, 'measurements'), (self.gsm_clock_offset_control_0, 'measurements'))
183 self.msg_connect((self.gsm_receiver_0, 'C0'), (self.gsm_sdcch8_demapper_0, 'bursts'))
184 self.msg_connect((self.gsm_sdcch8_demapper_0, 'bursts'), (self.gsm_decryption_0, 'bursts'))
185 self.connect((self.blocks_rotator_cc_0, 0), (self.gsm_input_0, 0))
186 self.connect((self.blocks_rotator_cc_0, 0), (self.qtgui_freq_sink_x_0, 0))
187 self.connect((self.gsm_input_0, 0), (self.gsm_receiver_0, 0))
188 self.connect((self.rtlsdr_source_0, 0), (self.blocks_rotator_cc_0, 0))
189
190 def closeEvent(self, event):
Piotr Krysik332e0b52016-02-13 18:37:32 +0100191 self.settings = Qt.QSettings("GNU Radio", "grgsm_livemon")
Piotr Krysik35582082015-09-02 21:49:12 +0200192 self.settings.setValue("geometry", self.saveGeometry())
193 event.accept()
194
Piotr Krysik6577ec22016-07-15 13:21:09 +0200195
196 def get_args(self):
197 return self.args
198
199 def set_args(self, args):
200 self.args = args
201
Piotr Krysik35582082015-09-02 21:49:12 +0200202 def get_fc(self):
203 return self.fc
204
205 def set_fc(self, fc):
206 self.fc = fc
207 self.set_fc_slider(self.fc)
208 self.gsm_input_0.set_fc(self.fc)
209
210 def get_gain(self):
211 return self.gain
212
213 def set_gain(self, gain):
214 self.gain = gain
215 self.set_g_slider(self.gain)
216
217 def get_ppm(self):
218 return self.ppm
219
220 def set_ppm(self, ppm):
221 self.ppm = ppm
222 self.set_ppm_slider(self.ppm)
223
224 def get_samp_rate(self):
225 return self.samp_rate
226
227 def set_samp_rate(self, samp_rate):
228 self.samp_rate = samp_rate
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200229 self.gsm_input_0.set_samp_rate_in(self.samp_rate)
Piotr Krysik35582082015-09-02 21:49:12 +0200230 self.qtgui_freq_sink_x_0.set_frequency_range(self.fc_slider, self.samp_rate)
231 self.rtlsdr_source_0.set_sample_rate(self.samp_rate)
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200232 self.blocks_rotator_cc_0.set_phase_inc(-2*pi*self.shiftoff/self.samp_rate)
Piotr Krysik35582082015-09-02 21:49:12 +0200233
234 def get_shiftoff(self):
235 return self.shiftoff
236
237 def set_shiftoff(self, shiftoff):
238 self.shiftoff = shiftoff
Piotr Krysik35582082015-09-02 21:49:12 +0200239 self.rtlsdr_source_0.set_center_freq(self.fc_slider-self.shiftoff, 0)
240 self.rtlsdr_source_0.set_bandwidth(250e3+abs(self.shiftoff), 0)
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200241 self.blocks_rotator_cc_0.set_phase_inc(-2*pi*self.shiftoff/self.samp_rate)
242
243 def get_osr(self):
244 return self.osr
245
246 def set_osr(self, osr):
247 self.osr = osr
Piotr Krysik35582082015-09-02 21:49:12 +0200248
249 def get_ppm_slider(self):
250 return self.ppm_slider
251
252 def set_ppm_slider(self, ppm_slider):
253 self.ppm_slider = ppm_slider
254 self.rtlsdr_source_0.set_freq_corr(self.ppm_slider, 0)
255
256 def get_g_slider(self):
257 return self.g_slider
258
259 def set_g_slider(self, g_slider):
260 self.g_slider = g_slider
261 self.rtlsdr_source_0.set_gain(self.g_slider, 0)
262
263 def get_fc_slider(self):
264 return self.fc_slider
265
266 def set_fc_slider(self, fc_slider):
267 self.fc_slider = fc_slider
268 self.qtgui_freq_sink_x_0.set_frequency_range(self.fc_slider, self.samp_rate)
269 self.rtlsdr_source_0.set_center_freq(self.fc_slider-self.shiftoff, 0)
270
271
Piotr Krysik6577ec22016-07-15 13:21:09 +0200272def argument_parser():
Piotr Krysik35582082015-09-02 21:49:12 +0200273 parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200274 parser.add_option(
275 "", "--args", dest="args", type="string", default="",
276 help="Set Device Arguments [default=%default]")
277 parser.add_option(
278 "-f", "--fc", dest="fc", type="eng_float", default=eng_notation.num_to_str(939.4e6),
Piotr Krysik35582082015-09-02 21:49:12 +0200279 help="Set fc [default=%default]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200280 parser.add_option(
281 "-g", "--gain", dest="gain", type="eng_float", default=eng_notation.num_to_str(30),
Piotr Krysik35582082015-09-02 21:49:12 +0200282 help="Set gain [default=%default]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200283 parser.add_option(
284 "-p", "--ppm", dest="ppm", type="intx", default=0,
Piotr Krysik35582082015-09-02 21:49:12 +0200285 help="Set ppm [default=%default]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200286 parser.add_option(
287 "-s", "--samp-rate", dest="samp_rate", type="eng_float", default=eng_notation.num_to_str(2000000.052982),
Piotr Krysik35582082015-09-02 21:49:12 +0200288 help="Set samp_rate [default=%default]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200289 parser.add_option(
290 "-o", "--shiftoff", dest="shiftoff", type="eng_float", default=eng_notation.num_to_str(400e3),
Piotr Krysik35582082015-09-02 21:49:12 +0200291 help="Set shiftoff [default=%default]")
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200292 parser.add_option(
293 "", "--osr", dest="osr", type="intx", default=4,
294 help="Set OSR [default=%default]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200295 return parser
296
297
298def main(top_block_cls=grgsm_livemon, options=None):
299 if options is None:
300 options, _ = argument_parser().parse_args()
301
302 from distutils.version import StrictVersion
303 if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"):
304 style = gr.prefs().get_string('qtgui', 'style', 'raster')
305 Qt.QApplication.setGraphicsSystem(style)
Piotr Krysik35582082015-09-02 21:49:12 +0200306 qapp = Qt.QApplication(sys.argv)
Piotr Krysik6577ec22016-07-15 13:21:09 +0200307
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200308 tb = top_block_cls(args=options.args, fc=options.fc, gain=options.gain, ppm=options.ppm, samp_rate=options.samp_rate, shiftoff=options.shiftoff, osr=options.osr)
Piotr Krysik35582082015-09-02 21:49:12 +0200309 tb.start()
310 tb.show()
311
312 def quitting():
313 tb.stop()
314 tb.wait()
315 qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting)
316 qapp.exec_()
Piotr Krysik6577ec22016-07-15 13:21:09 +0200317
318
319if __name__ == '__main__':
320 main()