blob: c51485ccdc747bfe46a6d4e1dd3495b02dfa65c7 [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 Krysikea34c012016-10-02 18:53:43 +02003# @file
4# @author Piotr Krysik <ptrkrysik@gmail.com>
5# @section LICENSE
6#
7# Gr-gsm is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 3, or (at your option)
10# any later version.
11#
12# Gr-gsm is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with gr-gsm; see the file COPYING. If not, write to
19# the Free Software Foundation, Inc., 51 Franklin Street,
20# Boston, MA 02110-1301, USA.
21#
22#
Piotr Krysik35582082015-09-02 21:49:12 +020023##################################################
24# GNU Radio Python Flow Graph
Piotr Krysik332e0b52016-02-13 18:37:32 +010025# Title: Gr-gsm Livemon
Piotr Krysik6577ec22016-07-15 13:21:09 +020026# Author: Piotr Krysik
27# 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 +020028# Generated: Mon Jul 18 18:08:34 2016
Piotr Krysik35582082015-09-02 21:49:12 +020029##################################################
30
31if __name__ == '__main__':
32 import ctypes
33 import sys
34 if sys.platform.startswith('linux'):
35 try:
36 x11 = ctypes.cdll.LoadLibrary('libX11.so')
37 x11.XInitThreads()
38 except:
39 print "Warning: failed to XInitThreads()"
40
41from PyQt4 import Qt
42from gnuradio import blocks
43from gnuradio import eng_notation
44from gnuradio import gr
45from gnuradio import qtgui
46from gnuradio.eng_option import eng_option
47from gnuradio.filter import firdes
48from gnuradio.qtgui import Range, RangeWidget
49from math import pi
50from optparse import OptionParser
51import grgsm
52import osmosdr
53import pmt
54import sip
55import sys
56import time
57
58
Piotr Krysik332e0b52016-02-13 18:37:32 +010059class grgsm_livemon(gr.top_block, Qt.QWidget):
Piotr Krysik35582082015-09-02 21:49:12 +020060
Piotr Krysikfe538eb2016-07-18 18:14:49 +020061 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 +010062 gr.top_block.__init__(self, "Gr-gsm Livemon")
Piotr Krysik35582082015-09-02 21:49:12 +020063 Qt.QWidget.__init__(self)
Piotr Krysik332e0b52016-02-13 18:37:32 +010064 self.setWindowTitle("Gr-gsm Livemon")
Piotr Krysik35582082015-09-02 21:49:12 +020065 try:
Piotr Krysik6577ec22016-07-15 13:21:09 +020066 self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
Piotr Krysik35582082015-09-02 21:49:12 +020067 except:
Piotr Krysik6577ec22016-07-15 13:21:09 +020068 pass
Piotr Krysik35582082015-09-02 21:49:12 +020069 self.top_scroll_layout = Qt.QVBoxLayout()
70 self.setLayout(self.top_scroll_layout)
71 self.top_scroll = Qt.QScrollArea()
72 self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
73 self.top_scroll_layout.addWidget(self.top_scroll)
74 self.top_scroll.setWidgetResizable(True)
75 self.top_widget = Qt.QWidget()
76 self.top_scroll.setWidget(self.top_widget)
77 self.top_layout = Qt.QVBoxLayout(self.top_widget)
78 self.top_grid_layout = Qt.QGridLayout()
79 self.top_layout.addLayout(self.top_grid_layout)
80
Piotr Krysik332e0b52016-02-13 18:37:32 +010081 self.settings = Qt.QSettings("GNU Radio", "grgsm_livemon")
Piotr Krysik35582082015-09-02 21:49:12 +020082 self.restoreGeometry(self.settings.value("geometry").toByteArray())
83
84 ##################################################
85 # Parameters
86 ##################################################
Piotr Krysik6577ec22016-07-15 13:21:09 +020087 self.args = args
Piotr Krysik35582082015-09-02 21:49:12 +020088 self.fc = fc
89 self.gain = gain
90 self.ppm = ppm
91 self.samp_rate = samp_rate
92 self.shiftoff = shiftoff
Piotr Krysikfe538eb2016-07-18 18:14:49 +020093 self.osr = osr
Piotr Krysik35582082015-09-02 21:49:12 +020094
95 ##################################################
96 # Variables
97 ##################################################
98 self.ppm_slider = ppm_slider = ppm
99 self.g_slider = g_slider = gain
100 self.fc_slider = fc_slider = fc
101
102 ##################################################
103 # Blocks
104 ##################################################
105 self._ppm_slider_range = Range(-150, 150, 1, ppm, 100)
106 self._ppm_slider_win = RangeWidget(self._ppm_slider_range, self.set_ppm_slider, "PPM Offset", "counter", float)
107 self.top_layout.addWidget(self._ppm_slider_win)
108 self._g_slider_range = Range(0, 50, 0.5, gain, 100)
109 self._g_slider_win = RangeWidget(self._g_slider_range, self.set_g_slider, "Gain", "counter", float)
110 self.top_layout.addWidget(self._g_slider_win)
111 self._fc_slider_range = Range(925e6, 1990e6, 2e5, fc, 100)
112 self._fc_slider_win = RangeWidget(self._fc_slider_range, self.set_fc_slider, "Frequency", "counter_slider", float)
113 self.top_layout.addWidget(self._fc_slider_win)
Piotr Krysik7185b662016-02-14 20:24:54 +0100114 self.rtlsdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + args )
Piotr Krysik35582082015-09-02 21:49:12 +0200115 self.rtlsdr_source_0.set_sample_rate(samp_rate)
116 self.rtlsdr_source_0.set_center_freq(fc_slider-shiftoff, 0)
117 self.rtlsdr_source_0.set_freq_corr(ppm_slider, 0)
118 self.rtlsdr_source_0.set_dc_offset_mode(2, 0)
119 self.rtlsdr_source_0.set_iq_balance_mode(2, 0)
120 self.rtlsdr_source_0.set_gain_mode(False, 0)
121 self.rtlsdr_source_0.set_gain(g_slider, 0)
122 self.rtlsdr_source_0.set_if_gain(20, 0)
123 self.rtlsdr_source_0.set_bb_gain(20, 0)
124 self.rtlsdr_source_0.set_antenna("", 0)
125 self.rtlsdr_source_0.set_bandwidth(250e3+abs(shiftoff), 0)
126
127 self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c(
128 1024, #size
129 firdes.WIN_BLACKMAN_hARRIS, #wintype
130 fc_slider, #fc
131 samp_rate, #bw
132 "", #name
133 1 #number of inputs
134 )
135 self.qtgui_freq_sink_x_0.set_update_time(0.10)
136 self.qtgui_freq_sink_x_0.set_y_axis(-140, 10)
Piotr Krysik6577ec22016-07-15 13:21:09 +0200137 self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "")
138 self.qtgui_freq_sink_x_0.enable_autoscale(False)
139 self.qtgui_freq_sink_x_0.enable_grid(False)
140 self.qtgui_freq_sink_x_0.set_fft_average(1.0)
141 self.qtgui_freq_sink_x_0.enable_control_panel(False)
142
143 if not True:
144 self.qtgui_freq_sink_x_0.disable_legend()
145
146 if "complex" == "float" or "complex" == "msg_float":
147 self.qtgui_freq_sink_x_0.set_plot_pos_half(not True)
148
149 labels = ["", "", "", "", "",
150 "", "", "", "", ""]
151 widths = [1, 1, 1, 1, 1,
152 1, 1, 1, 1, 1]
153 colors = ["blue", "red", "green", "black", "cyan",
154 "magenta", "yellow", "dark red", "dark green", "dark blue"]
155 alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
156 1.0, 1.0, 1.0, 1.0, 1.0]
157 for i in xrange(1):
158 if len(labels[i]) == 0:
159 self.qtgui_freq_sink_x_0.set_line_label(i, "Data {0}".format(i))
160 else:
161 self.qtgui_freq_sink_x_0.set_line_label(i, labels[i])
162 self.qtgui_freq_sink_x_0.set_line_width(i, widths[i])
163 self.qtgui_freq_sink_x_0.set_line_color(i, colors[i])
164 self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i])
Piotr Krysik35582082015-09-02 21:49:12 +0200165
166 self._qtgui_freq_sink_x_0_win = sip.wrapinstance(self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget)
167 self.top_layout.addWidget(self._qtgui_freq_sink_x_0_win)
Piotr Krysik6577ec22016-07-15 13:21:09 +0200168 self.gsm_sdcch8_demapper_0 = grgsm.gsm_sdcch8_demapper(
169 timeslot_nr=1,
170 )
171 self.gsm_receiver_0 = grgsm.receiver(4, ([0]), ([]), False)
172 self.gsm_message_printer_1 = grgsm.message_printer(pmt.intern(""), False,
173 False, False)
Piotr Krysik35582082015-09-02 21:49:12 +0200174 self.gsm_input_0 = grgsm.gsm_input(
175 ppm=0,
176 osr=4,
177 fc=fc,
178 samp_rate_in=samp_rate,
179 )
180 self.gsm_decryption_0 = grgsm.decryption(([]), 1)
181 self.gsm_control_channels_decoder_0_0 = grgsm.control_channels_decoder()
182 self.gsm_control_channels_decoder_0 = grgsm.control_channels_decoder()
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200183 self.gsm_clock_offset_control_0 = grgsm.clock_offset_control(fc-shiftoff, samp_rate, osr)
Piotr Krysik6577ec22016-07-15 13:21:09 +0200184 self.gsm_bcch_ccch_demapper_0 = grgsm.gsm_bcch_ccch_demapper(
185 timeslot_nr=0,
186 )
187 self.blocks_socket_pdu_0_0 = blocks.socket_pdu("UDP_SERVER", "127.0.0.1", "4729", 10000, False)
188 self.blocks_socket_pdu_0 = blocks.socket_pdu("UDP_CLIENT", "127.0.0.1", "4729", 10000, False)
Piotr Krysik35582082015-09-02 21:49:12 +0200189 self.blocks_rotator_cc_0 = blocks.rotator_cc(-2*pi*shiftoff/samp_rate)
190
191 ##################################################
192 # Connections
193 ##################################################
194 self.msg_connect((self.gsm_bcch_ccch_demapper_0, 'bursts'), (self.gsm_control_channels_decoder_0, 'bursts'))
Piotr Krysik6577ec22016-07-15 13:21:09 +0200195 self.msg_connect((self.gsm_clock_offset_control_0, 'ctrl'), (self.gsm_input_0, 'ctrl_in'))
Piotr Krysik35582082015-09-02 21:49:12 +0200196 self.msg_connect((self.gsm_control_channels_decoder_0, 'msgs'), (self.blocks_socket_pdu_0, 'pdus'))
197 self.msg_connect((self.gsm_control_channels_decoder_0, 'msgs'), (self.gsm_message_printer_1, 'msgs'))
198 self.msg_connect((self.gsm_control_channels_decoder_0_0, 'msgs'), (self.blocks_socket_pdu_0, 'pdus'))
199 self.msg_connect((self.gsm_control_channels_decoder_0_0, 'msgs'), (self.gsm_message_printer_1, 'msgs'))
200 self.msg_connect((self.gsm_decryption_0, 'bursts'), (self.gsm_control_channels_decoder_0_0, 'bursts'))
201 self.msg_connect((self.gsm_receiver_0, 'C0'), (self.gsm_bcch_ccch_demapper_0, 'bursts'))
202 self.msg_connect((self.gsm_receiver_0, 'measurements'), (self.gsm_clock_offset_control_0, 'measurements'))
203 self.msg_connect((self.gsm_receiver_0, 'C0'), (self.gsm_sdcch8_demapper_0, 'bursts'))
204 self.msg_connect((self.gsm_sdcch8_demapper_0, 'bursts'), (self.gsm_decryption_0, 'bursts'))
205 self.connect((self.blocks_rotator_cc_0, 0), (self.gsm_input_0, 0))
206 self.connect((self.blocks_rotator_cc_0, 0), (self.qtgui_freq_sink_x_0, 0))
207 self.connect((self.gsm_input_0, 0), (self.gsm_receiver_0, 0))
208 self.connect((self.rtlsdr_source_0, 0), (self.blocks_rotator_cc_0, 0))
209
210 def closeEvent(self, event):
Piotr Krysik332e0b52016-02-13 18:37:32 +0100211 self.settings = Qt.QSettings("GNU Radio", "grgsm_livemon")
Piotr Krysik35582082015-09-02 21:49:12 +0200212 self.settings.setValue("geometry", self.saveGeometry())
213 event.accept()
214
Piotr Krysik6577ec22016-07-15 13:21:09 +0200215
216 def get_args(self):
217 return self.args
218
219 def set_args(self, args):
220 self.args = args
221
Piotr Krysik35582082015-09-02 21:49:12 +0200222 def get_fc(self):
223 return self.fc
224
225 def set_fc(self, fc):
226 self.fc = fc
227 self.set_fc_slider(self.fc)
228 self.gsm_input_0.set_fc(self.fc)
229
230 def get_gain(self):
231 return self.gain
232
233 def set_gain(self, gain):
234 self.gain = gain
235 self.set_g_slider(self.gain)
236
237 def get_ppm(self):
238 return self.ppm
239
240 def set_ppm(self, ppm):
241 self.ppm = ppm
242 self.set_ppm_slider(self.ppm)
243
244 def get_samp_rate(self):
245 return self.samp_rate
246
247 def set_samp_rate(self, samp_rate):
248 self.samp_rate = samp_rate
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200249 self.gsm_input_0.set_samp_rate_in(self.samp_rate)
Piotr Krysik35582082015-09-02 21:49:12 +0200250 self.qtgui_freq_sink_x_0.set_frequency_range(self.fc_slider, self.samp_rate)
251 self.rtlsdr_source_0.set_sample_rate(self.samp_rate)
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200252 self.blocks_rotator_cc_0.set_phase_inc(-2*pi*self.shiftoff/self.samp_rate)
Piotr Krysik35582082015-09-02 21:49:12 +0200253
254 def get_shiftoff(self):
255 return self.shiftoff
256
257 def set_shiftoff(self, shiftoff):
258 self.shiftoff = shiftoff
Piotr Krysik35582082015-09-02 21:49:12 +0200259 self.rtlsdr_source_0.set_center_freq(self.fc_slider-self.shiftoff, 0)
260 self.rtlsdr_source_0.set_bandwidth(250e3+abs(self.shiftoff), 0)
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200261 self.blocks_rotator_cc_0.set_phase_inc(-2*pi*self.shiftoff/self.samp_rate)
262
263 def get_osr(self):
264 return self.osr
265
266 def set_osr(self, osr):
267 self.osr = osr
Piotr Krysik35582082015-09-02 21:49:12 +0200268
269 def get_ppm_slider(self):
270 return self.ppm_slider
271
272 def set_ppm_slider(self, ppm_slider):
273 self.ppm_slider = ppm_slider
274 self.rtlsdr_source_0.set_freq_corr(self.ppm_slider, 0)
275
276 def get_g_slider(self):
277 return self.g_slider
278
279 def set_g_slider(self, g_slider):
280 self.g_slider = g_slider
281 self.rtlsdr_source_0.set_gain(self.g_slider, 0)
282
283 def get_fc_slider(self):
284 return self.fc_slider
285
286 def set_fc_slider(self, fc_slider):
287 self.fc_slider = fc_slider
288 self.qtgui_freq_sink_x_0.set_frequency_range(self.fc_slider, self.samp_rate)
289 self.rtlsdr_source_0.set_center_freq(self.fc_slider-self.shiftoff, 0)
290
291
Piotr Krysik6577ec22016-07-15 13:21:09 +0200292def argument_parser():
Piotr Krysik35582082015-09-02 21:49:12 +0200293 parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200294 parser.add_option(
295 "", "--args", dest="args", type="string", default="",
296 help="Set Device Arguments [default=%default]")
297 parser.add_option(
298 "-f", "--fc", dest="fc", type="eng_float", default=eng_notation.num_to_str(939.4e6),
Piotr Krysik35582082015-09-02 21:49:12 +0200299 help="Set fc [default=%default]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200300 parser.add_option(
301 "-g", "--gain", dest="gain", type="eng_float", default=eng_notation.num_to_str(30),
Piotr Krysik35582082015-09-02 21:49:12 +0200302 help="Set gain [default=%default]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200303 parser.add_option(
304 "-p", "--ppm", dest="ppm", type="intx", default=0,
Piotr Krysik35582082015-09-02 21:49:12 +0200305 help="Set ppm [default=%default]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200306 parser.add_option(
307 "-s", "--samp-rate", dest="samp_rate", type="eng_float", default=eng_notation.num_to_str(2000000.052982),
Piotr Krysik35582082015-09-02 21:49:12 +0200308 help="Set samp_rate [default=%default]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200309 parser.add_option(
310 "-o", "--shiftoff", dest="shiftoff", type="eng_float", default=eng_notation.num_to_str(400e3),
Piotr Krysik35582082015-09-02 21:49:12 +0200311 help="Set shiftoff [default=%default]")
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200312 parser.add_option(
313 "", "--osr", dest="osr", type="intx", default=4,
314 help="Set OSR [default=%default]")
Piotr Krysik6577ec22016-07-15 13:21:09 +0200315 return parser
316
317
318def main(top_block_cls=grgsm_livemon, options=None):
319 if options is None:
320 options, _ = argument_parser().parse_args()
321
322 from distutils.version import StrictVersion
323 if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"):
324 style = gr.prefs().get_string('qtgui', 'style', 'raster')
325 Qt.QApplication.setGraphicsSystem(style)
Piotr Krysik35582082015-09-02 21:49:12 +0200326 qapp = Qt.QApplication(sys.argv)
Piotr Krysik6577ec22016-07-15 13:21:09 +0200327
Piotr Krysikfe538eb2016-07-18 18:14:49 +0200328 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 +0200329 tb.start()
330 tb.show()
331
332 def quitting():
333 tb.stop()
334 tb.wait()
335 qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting)
336 qapp.exec_()
Piotr Krysik6577ec22016-07-15 13:21:09 +0200337
338
339if __name__ == '__main__':
340 main()