blob: 765ebae1671b2744f21ac96b0a1a371a170ddd2b [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 Krysik93ba6bc2017-01-23 21:33:09 +01008# Generated: Mon Jan 23 21:28:25 2017
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 ##################################################
Piotr Krysik93ba6bc2017-01-23 21:33:09 +010085 self._ppm_slider_range = Range(-150, 150, 0.1, ppm, 100)
Piotr Krysik35582082015-09-02 21:49:12 +020086 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)
Piotr Krysik93ba6bc2017-01-23 21:33:09 +010091 self._fc_slider_range = Range(800e6, 1990e6, 2e5, fc, 100)
Piotr Krysik35582082015-09-02 21:49:12 +020092 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(
Piotr Krysik93ba6bc2017-01-23 21:33:09 +0100155 ppm=ppm-int(ppm),
Piotr Krysik35582082015-09-02 21:49:12 +0200156 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)
Piotr Krysik93ba6bc2017-01-23 21:33:09 +0100223 self.gsm_input_0.set_ppm(self.ppm-int(self.ppm))
Piotr Krysik35582082015-09-02 21:49:12 +0200224
225 def get_samp_rate(self):
226 return self.samp_rate
227
228 def set_samp_rate(self, samp_rate):
229 self.samp_rate = samp_rate
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200230 self.gsm_input_0.set_samp_rate_in(self.samp_rate)
Piotr Krysik35582082015-09-02 21:49:12 +0200231 self.qtgui_freq_sink_x_0.set_frequency_range(self.fc_slider, self.samp_rate)
232 self.rtlsdr_source_0.set_sample_rate(self.samp_rate)
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200233 self.blocks_rotator_cc_0.set_phase_inc(-2*pi*self.shiftoff/self.samp_rate)
Piotr Krysik35582082015-09-02 21:49:12 +0200234
235 def get_shiftoff(self):
236 return self.shiftoff
237
238 def set_shiftoff(self, shiftoff):
239 self.shiftoff = shiftoff
Piotr Krysik35582082015-09-02 21:49:12 +0200240 self.rtlsdr_source_0.set_center_freq(self.fc_slider-self.shiftoff, 0)
241 self.rtlsdr_source_0.set_bandwidth(250e3+abs(self.shiftoff), 0)
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200242 self.blocks_rotator_cc_0.set_phase_inc(-2*pi*self.shiftoff/self.samp_rate)
243
244 def get_osr(self):
245 return self.osr
246
247 def set_osr(self, osr):
248 self.osr = osr
Piotr Krysik35582082015-09-02 21:49:12 +0200249
250 def get_ppm_slider(self):
251 return self.ppm_slider
252
253 def set_ppm_slider(self, ppm_slider):
254 self.ppm_slider = ppm_slider
255 self.rtlsdr_source_0.set_freq_corr(self.ppm_slider, 0)
256
257 def get_g_slider(self):
258 return self.g_slider
259
260 def set_g_slider(self, g_slider):
261 self.g_slider = g_slider
262 self.rtlsdr_source_0.set_gain(self.g_slider, 0)
263
264 def get_fc_slider(self):
265 return self.fc_slider
266
267 def set_fc_slider(self, fc_slider):
268 self.fc_slider = fc_slider
269 self.qtgui_freq_sink_x_0.set_frequency_range(self.fc_slider, self.samp_rate)
270 self.rtlsdr_source_0.set_center_freq(self.fc_slider-self.shiftoff, 0)
271
272
Piotr Krysik6577ec22016-07-15 13:21:09 +0200273def argument_parser():
Piotr Krysik35582082015-09-02 21:49:12 +0200274 parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200275 parser.add_option(
276 "", "--args", dest="args", type="string", default="",
277 help="Set Device Arguments [default=%default]")
278 parser.add_option(
279 "-f", "--fc", dest="fc", type="eng_float", default=eng_notation.num_to_str(939.4e6),
Piotr Krysik35582082015-09-02 21:49:12 +0200280 help="Set fc [default=%default]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200281 parser.add_option(
282 "-g", "--gain", dest="gain", type="eng_float", default=eng_notation.num_to_str(30),
Piotr Krysik35582082015-09-02 21:49:12 +0200283 help="Set gain [default=%default]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200284 parser.add_option(
Piotr Krysik93ba6bc2017-01-23 21:33:09 +0100285 "-p", "--ppm", dest="ppm", type="eng_float", default=eng_notation.num_to_str(0),
Piotr Krysik35582082015-09-02 21:49:12 +0200286 help="Set ppm [default=%default]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200287 parser.add_option(
288 "-s", "--samp-rate", dest="samp_rate", type="eng_float", default=eng_notation.num_to_str(2000000.052982),
Piotr Krysik35582082015-09-02 21:49:12 +0200289 help="Set samp_rate [default=%default]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200290 parser.add_option(
291 "-o", "--shiftoff", dest="shiftoff", type="eng_float", default=eng_notation.num_to_str(400e3),
Piotr Krysik35582082015-09-02 21:49:12 +0200292 help="Set shiftoff [default=%default]")
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200293 parser.add_option(
294 "", "--osr", dest="osr", type="intx", default=4,
295 help="Set OSR [default=%default]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200296 return parser
297
298
299def main(top_block_cls=grgsm_livemon, options=None):
300 if options is None:
301 options, _ = argument_parser().parse_args()
302
303 from distutils.version import StrictVersion
304 if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"):
305 style = gr.prefs().get_string('qtgui', 'style', 'raster')
306 Qt.QApplication.setGraphicsSystem(style)
Piotr Krysik35582082015-09-02 21:49:12 +0200307 qapp = Qt.QApplication(sys.argv)
Piotr Krysik6577ec22016-07-15 13:21:09 +0200308
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200309 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 +0200310 tb.start()
311 tb.show()
312
313 def quitting():
314 tb.stop()
315 tb.wait()
316 qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting)
317 qapp.exec_()
Piotr Krysik6577ec22016-07-15 13:21:09 +0200318
319
320if __name__ == '__main__':
321 main()