blob: 721bc1106c604742c26757ac9b97efd07c4c0b9b [file] [log] [blame]
Petter Reinholdtsen0af55122017-08-28 22:19:11 +02001#!/usr/bin/env python2
2# -*- coding: utf-8 -*-
Piotr Krysik3dfa11b2017-09-06 17:48:38 +02003# @file
4# @author (C) 2017 by 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#
Petter Reinholdtsen0af55122017-08-28 22:19:11 +020023##################################################
24# GNU Radio Python Flow Graph
25# Title: Gr-gsm Livemon
26# 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 Krysik3dfa11b2017-09-06 17:48:38 +020028# Generated: Wed Sep 6 16:27:23 2017
Petter Reinholdtsen0af55122017-08-28 22:19:11 +020029##################################################
30
31from gnuradio import blocks
32from gnuradio import eng_notation
33from gnuradio import gr
34from gnuradio.eng_option import eng_option
35from gnuradio.filter import firdes
Piotr Krysik3dfa11b2017-09-06 17:48:38 +020036from grgsm import arfcn
Petter Reinholdtsen0af55122017-08-28 22:19:11 +020037from math import pi
38from optparse import OptionParser
39import grgsm
40import osmosdr
41import pmt
42import time
43
44
45class grgsm_livemon_headless(gr.top_block):
46
Piotr Krysik3dfa11b2017-09-06 17:48:38 +020047 def __init__(self, args="", collector="localhost", collectorport="4729", gain=30, osr=4, ppm=0, rec_len=1000000, samp_rate=2000000.052982, serverport="4729", shiftoff=400e3, fc=957e6):
Petter Reinholdtsen0af55122017-08-28 22:19:11 +020048 gr.top_block.__init__(self, "Gr-gsm Livemon")
49
50 ##################################################
51 # Parameters
52 ##################################################
53 self.args = args
54 self.collector = collector
55 self.collectorport = collectorport
Petter Reinholdtsen0af55122017-08-28 22:19:11 +020056 self.gain = gain
57 self.osr = osr
58 self.ppm = ppm
Piotr Krysik3dfa11b2017-09-06 17:48:38 +020059 self.rec_len = rec_len
Petter Reinholdtsen0af55122017-08-28 22:19:11 +020060 self.samp_rate = samp_rate
61 self.serverport = serverport
62 self.shiftoff = shiftoff
Piotr Krysik3dfa11b2017-09-06 17:48:38 +020063 self.fc = fc
Petter Reinholdtsen0af55122017-08-28 22:19:11 +020064
65 ##################################################
66 # Blocks
67 ##################################################
68 self.rtlsdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + args )
69 self.rtlsdr_source_0.set_sample_rate(samp_rate)
70 self.rtlsdr_source_0.set_center_freq(fc-shiftoff, 0)
71 self.rtlsdr_source_0.set_freq_corr(ppm, 0)
72 self.rtlsdr_source_0.set_dc_offset_mode(2, 0)
73 self.rtlsdr_source_0.set_iq_balance_mode(2, 0)
74 self.rtlsdr_source_0.set_gain_mode(False, 0)
75 self.rtlsdr_source_0.set_gain(gain, 0)
76 self.rtlsdr_source_0.set_if_gain(20, 0)
77 self.rtlsdr_source_0.set_bb_gain(20, 0)
Piotr Krysik3dfa11b2017-09-06 17:48:38 +020078 self.rtlsdr_source_0.set_antenna("", 0)
Petter Reinholdtsen0af55122017-08-28 22:19:11 +020079 self.rtlsdr_source_0.set_bandwidth(250e3+abs(shiftoff), 0)
80
81 self.gsm_sdcch8_demapper_0 = grgsm.gsm_sdcch8_demapper(
82 timeslot_nr=1,
83 )
Piotr Krysik3dfa11b2017-09-06 17:48:38 +020084 self.gsm_receiver_0 = grgsm.receiver(4, ([arfcn.downlink2arfcn(fc)]), ([]), False)
Petter Reinholdtsen0af55122017-08-28 22:19:11 +020085 self.gsm_message_printer_1 = grgsm.message_printer(pmt.intern(""), False,
86 False, False)
87 self.gsm_input_0 = grgsm.gsm_input(
88 ppm=ppm-int(ppm),
89 osr=4,
90 fc=fc,
91 samp_rate_in=samp_rate,
92 )
93 self.gsm_decryption_0 = grgsm.decryption(([]), 1)
94 self.gsm_control_channels_decoder_0_0 = grgsm.control_channels_decoder()
95 self.gsm_control_channels_decoder_0 = grgsm.control_channels_decoder()
96 self.gsm_clock_offset_control_0 = grgsm.clock_offset_control(fc-shiftoff, samp_rate, osr)
97 self.gsm_bcch_ccch_sdcch4_demapper_0 = grgsm.gsm_bcch_ccch_sdcch4_demapper(
98 timeslot_nr=0,
99 )
100 self.blocks_socket_pdu_0_1 = blocks.socket_pdu("UDP_CLIENT", collector, collectorport, 1500, False)
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200101 self.blocks_socket_pdu_0_0 = blocks.socket_pdu("UDP_SERVER", "127.0.0.1", serverport, 10000, False)
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200102 self.blocks_rotator_cc_0 = blocks.rotator_cc(-2*pi*shiftoff/samp_rate)
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200103 self.blocks_head_0 = blocks.head(gr.sizeof_gr_complex*1, int(rec_len*samp_rate))
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200104
105 ##################################################
106 # Connections
107 ##################################################
108 self.msg_connect((self.blocks_socket_pdu_0_0, 'pdus'), (self.gsm_message_printer_1, 'msgs'))
109 self.msg_connect((self.gsm_bcch_ccch_sdcch4_demapper_0, 'bursts'), (self.gsm_control_channels_decoder_0, 'bursts'))
110 self.msg_connect((self.gsm_clock_offset_control_0, 'ctrl'), (self.gsm_input_0, 'ctrl_in'))
111 self.msg_connect((self.gsm_control_channels_decoder_0, 'msgs'), (self.blocks_socket_pdu_0_1, 'pdus'))
112 self.msg_connect((self.gsm_control_channels_decoder_0_0, 'msgs'), (self.blocks_socket_pdu_0_1, 'pdus'))
113 self.msg_connect((self.gsm_decryption_0, 'bursts'), (self.gsm_control_channels_decoder_0_0, 'bursts'))
114 self.msg_connect((self.gsm_receiver_0, 'C0'), (self.gsm_bcch_ccch_sdcch4_demapper_0, 'bursts'))
115 self.msg_connect((self.gsm_receiver_0, 'measurements'), (self.gsm_clock_offset_control_0, 'measurements'))
116 self.msg_connect((self.gsm_receiver_0, 'C0'), (self.gsm_sdcch8_demapper_0, 'bursts'))
117 self.msg_connect((self.gsm_sdcch8_demapper_0, 'bursts'), (self.gsm_decryption_0, 'bursts'))
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200118 self.connect((self.blocks_head_0, 0), (self.blocks_rotator_cc_0, 0))
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200119 self.connect((self.blocks_rotator_cc_0, 0), (self.gsm_input_0, 0))
120 self.connect((self.gsm_input_0, 0), (self.gsm_receiver_0, 0))
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200121 self.connect((self.rtlsdr_source_0, 0), (self.blocks_head_0, 0))
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200122
123 def get_args(self):
124 return self.args
125
126 def set_args(self, args):
127 self.args = args
128
129 def get_collector(self):
130 return self.collector
131
132 def set_collector(self, collector):
133 self.collector = collector
134
135 def get_collectorport(self):
136 return self.collectorport
137
138 def set_collectorport(self, collectorport):
139 self.collectorport = collectorport
140
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200141 def get_gain(self):
142 return self.gain
143
144 def set_gain(self, gain):
145 self.gain = gain
146 self.rtlsdr_source_0.set_gain(self.gain, 0)
147
148 def get_osr(self):
149 return self.osr
150
151 def set_osr(self, osr):
152 self.osr = osr
153
154 def get_ppm(self):
155 return self.ppm
156
157 def set_ppm(self, ppm):
158 self.ppm = ppm
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200159 self.gsm_input_0.set_ppm(self.ppm-int(self.ppm))
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200160 self.rtlsdr_source_0.set_freq_corr(self.ppm, 0)
161
162 def get_rec_len(self):
163 return self.rec_len
164
165 def set_rec_len(self, rec_len):
166 self.rec_len = rec_len
167 self.blocks_head_0.set_length(int(self.rec_len*self.samp_rate))
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200168
169 def get_samp_rate(self):
170 return self.samp_rate
171
172 def set_samp_rate(self, samp_rate):
173 self.samp_rate = samp_rate
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200174 self.blocks_head_0.set_length(int(self.rec_len*self.samp_rate))
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200175 self.blocks_rotator_cc_0.set_phase_inc(-2*pi*self.shiftoff/self.samp_rate)
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200176 self.gsm_input_0.set_samp_rate_in(self.samp_rate)
177 self.rtlsdr_source_0.set_sample_rate(self.samp_rate)
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200178
179 def get_serverport(self):
180 return self.serverport
181
182 def set_serverport(self, serverport):
183 self.serverport = serverport
184
185 def get_shiftoff(self):
186 return self.shiftoff
187
188 def set_shiftoff(self, shiftoff):
189 self.shiftoff = shiftoff
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200190 self.blocks_rotator_cc_0.set_phase_inc(-2*pi*self.shiftoff/self.samp_rate)
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200191 self.rtlsdr_source_0.set_center_freq(self.fc-self.shiftoff, 0)
192 self.rtlsdr_source_0.set_bandwidth(250e3+abs(self.shiftoff), 0)
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200193
194 def get_fc(self):
195 return self.fc
196
197 def set_fc(self, fc):
198 self.fc = fc
199 self.gsm_input_0.set_fc(self.fc)
200 self.rtlsdr_source_0.set_center_freq(self.fc-self.shiftoff, 0)
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200201
202
203def argument_parser():
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200204 parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200205 parser.add_option(
206 "", "--args", dest="args", type="string", default="",
207 help="Set Device Arguments [default=%default]")
208 parser.add_option(
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200209 "", "--collector", dest="collector", type="string", default="localhost",
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200210 help="Set IP or DNS name of collector point [default=%default]")
211 parser.add_option(
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200212 "", "--collectorport", dest="collectorport", type="string", default="4729",
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200213 help="Set UDP port number of collector [default=%default]")
214 parser.add_option(
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200215 "-g", "--gain", dest="gain", type="eng_float", default=eng_notation.num_to_str(30),
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200216 help="Set RF Gain [default=%default]")
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200217 parser.add_option(
218 "", "--osr", dest="osr", type="intx", default=4,
219 help="Set OverSampling Ratio [default=%default]")
220 parser.add_option(
221 "-p", "--ppm", dest="ppm", type="eng_float", default=eng_notation.num_to_str(0),
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200222 help="Set Clock frequency offset in ppms (1/1e6 parts) [default=%default]")
223 parser.add_option(
224 "-T", "--rec-len", dest="rec_len", type="eng_float", default=eng_notation.num_to_str(1000000),
225 help="Set Recording length in seconds [default=%default]")
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200226 parser.add_option(
227 "-s", "--samp-rate", dest="samp_rate", type="eng_float", default=eng_notation.num_to_str(2000000.052982),
228 help="Set samp_rate [default=%default]")
229 parser.add_option(
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200230 "", "--serverport", dest="serverport", type="string", default="4729",
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200231 help="Set UDP server listening port [default=%default]")
232 parser.add_option(
233 "-o", "--shiftoff", dest="shiftoff", type="eng_float", default=eng_notation.num_to_str(400e3),
234 help="Set Frequency Shiftoff [default=%default]")
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200235 parser.add_option(
236 "-f", "--fc", dest="fc", type="eng_float", default=eng_notation.num_to_str(957e6),
237 help="Set GSM channel's central frequency [default=%default]")
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200238 return parser
239
240
241def main(top_block_cls=grgsm_livemon_headless, options=None):
242 if options is None:
243 options, _ = argument_parser().parse_args()
244
Piotr Krysik3dfa11b2017-09-06 17:48:38 +0200245 tb = top_block_cls(args=options.args, collector=options.collector, collectorport=options.collectorport, gain=options.gain, osr=options.osr, ppm=options.ppm, rec_len=options.rec_len, samp_rate=options.samp_rate, serverport=options.serverport, shiftoff=options.shiftoff, fc=options.fc)
Petter Reinholdtsen0af55122017-08-28 22:19:11 +0200246 tb.start()
247 tb.wait()
248
249
250if __name__ == '__main__':
251 main()