blob: f3886ba85807b9c779e07ee41de2b8fbd1550253 [file] [log] [blame]
Roman Khassraf529e2152015-08-22 19:52:41 +02001#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# @file
Piotr Krysika6268a52017-08-23 16:02:19 +02004# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
Piotr Krysik81ba56f2018-09-20 14:49:27 +02005# (C) 2019 by Piotr Krysik <ptrkrysik@gmail.com>
Roman Khassraf529e2152015-08-22 19:52:41 +02006# @section LICENSE
7#
8# Gr-gsm is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 3, or (at your option)
11# any later version.
12#
13# Gr-gsm is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with gr-gsm; see the file COPYING. If not, write to
20# the Free Software Foundation, Inc., 51 Franklin Street,
21# Boston, MA 02110-1301, USA.
22#
23#
24
Roman Khassraf529e2152015-08-22 19:52:41 +020025from gnuradio import blocks
26from gnuradio import eng_notation
27from gnuradio import gr
Roman Khassraf529e2152015-08-22 19:52:41 +020028from gnuradio.eng_option import eng_option
29from gnuradio.filter import firdes
Piotr Krysik81ba56f2018-09-20 14:49:27 +020030from optparse import OptionParser, OptionGroup
Roman Khassraf529e2152015-08-22 19:52:41 +020031import osmosdr
Piotr Krysik81ba56f2018-09-20 14:49:27 +020032import time
33import grgsm
Roman Khassraf7eda4802015-08-24 20:00:48 +020034import signal
35import sys
Roman Khassraf529e2152015-08-22 19:52:41 +020036
Piotr Krysik3e192c42016-02-13 07:31:51 +010037class grgsm_capture(gr.top_block):
Piotr Krysik81ba56f2018-09-20 14:49:27 +020038 def __init__(self,
39 freq,
40 gain=30,
41 samp_rate=1e6,
42 rec_length=float('Inf'),
43 freq_corr=0,
44 output_filename=None,
45 bandwidth=0,
46 bb_gain=20,
47 if_gain=20,
48 antenna="",
49 device_args=""):
Piotr Krysik3e192c42016-02-13 07:31:51 +010050 gr.top_block.__init__(self, "Gr-gsm Capture")
Piotr Krysik81ba56f2018-09-20 14:49:27 +020051
Roman Khassraf529e2152015-08-22 19:52:41 +020052 ##################################################
Piotr Krysik81ba56f2018-09-20 14:49:27 +020053 # Setting up RF source
Roman Khassraf529e2152015-08-22 19:52:41 +020054 ##################################################
55
Vasil Velichkov54580d12019-04-17 18:28:46 +030056 self.sdr_source = osmosdr.source(args="numchan=" + str(1) + " " +
57 str(grgsm.device.get_default_args(device_args)))
Vasil Velichkov61e42c82019-04-15 22:10:18 +030058
Piotr Krysik81ba56f2018-09-20 14:49:27 +020059 self.sdr_source.set_sample_rate(samp_rate)
60 self.sdr_source.set_center_freq(freq, 0)
61 self.sdr_source.set_freq_corr(freq_corr, 0)
62 self.sdr_source.set_dc_offset_mode(2, 0)
63 self.sdr_source.set_iq_balance_mode(2, 0)
64 self.sdr_source.set_gain_mode(True, 0)
65 self.sdr_source.set_gain(gain, 0)
66 self.sdr_source.set_if_gain(if_gain, 0)
67 self.sdr_source.set_bb_gain(bb_gain, 0)
68 self.sdr_source.set_antenna("", 0)
69 if bandwidth != 0:
70 self.sdr_source.set_bandwidth(bandwidth, 0)
Roman Khassraf529e2152015-08-22 19:52:41 +020071
Piotr Krysik81ba56f2018-09-20 14:49:27 +020072 ##################################################
73 # The rest of processing blocks
74 ##################################################
Roman Khassraf529e2152015-08-22 19:52:41 +020075
Piotr Krysik81ba56f2018-09-20 14:49:27 +020076 if rec_length != float('Inf'):
77 self.head = \
78 blocks.head(gr.sizeof_gr_complex, int(samp_rate*rec_length))
Roman Khassraf529e2152015-08-22 19:52:41 +020079
Piotr Krysik81ba56f2018-09-20 14:49:27 +020080 self.file_sink = blocks.file_sink(gr.sizeof_gr_complex*1, \
81 output_filename, False)
82 self.file_sink.set_unbuffered(False)
Roman Khassraf529e2152015-08-22 19:52:41 +020083
84 ##################################################
85 # Connections
86 ##################################################
87
Piotr Krysik81ba56f2018-09-20 14:49:27 +020088 if rec_length != float('Inf'): #if recording length is not infinite
89 #connect head block after the source
90 self.connect((self.sdr_source, 0), (self.head, 0))
91 self.connect((self.head, 0), (self.file_sink, 0))
Piotr Krysik351d2172015-09-20 13:53:06 +020092 else:
Piotr Krysik81ba56f2018-09-20 14:49:27 +020093 self.connect((self.sdr_source, 0), (self.file_sink, 0))
Piotr Krysik351d2172015-09-20 13:53:06 +020094
Roman Khassraf529e2152015-08-22 19:52:41 +020095if __name__ == '__main__':
Roman Khassraf529e2152015-08-22 19:52:41 +020096
Piotr Krysik81ba56f2018-09-20 14:49:27 +020097 parser = OptionParser(option_class=eng_option, usage="%prog [options] output_filename",
Roman Khassraf529e2152015-08-22 19:52:41 +020098 description="RTL-SDR capturing app of gr-gsm.")
Roman Khassraf529e2152015-08-22 19:52:41 +020099
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200100 parser.add_option("-f", "--freq", dest="freq", type="eng_float",
Roman Khassraf529e2152015-08-22 19:52:41 +0200101 help="Set frequency [default=%default]")
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200102
103 parser.add_option("-a", "--arfcn", dest="arfcn", type="intx",
104 help="Set ARFCN instead of frequency (for PCS1900 add"
105 "0x8000 (2**15) to the ARFCN number)")
106
107 parser.add_option("-g", "--gain", dest="gain", type="eng_float",
Roman Khassraf529e2152015-08-22 19:52:41 +0200108 default=eng_notation.num_to_str(30),
109 help="Set gain [default=%default]")
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200110
111 parser.add_option("-s", "--samp-rate", dest="samp_rate", type="eng_float",
Piotr Krysik96485402016-07-21 16:06:03 +0200112 default=eng_notation.num_to_str(1000000),
Roman Khassraf529e2152015-08-22 19:52:41 +0200113 help="Set samp_rate [default=%default]")
Piotr Krysik7185b662016-02-14 20:24:54 +0100114
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200115 parser.add_option("-T", "--rec-length", dest="rec_length", type="float",
116 default='Inf', help="Set length of recording in seconds "
117 "[default=infinity]")
Piotr Krysik351d2172015-09-20 13:53:06 +0200118
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200119 parser.add_option("-p", "--freq-corr", dest="freq_corr", type="eng_float",
120 default="0", help="Set frequency correction in"
121 " ppm [default=%default]")
122
123 osmogroup = OptionGroup(parser, 'Additional osmosdr source options',
124 "Options specific to a subset of SDR receivers "
125 "supported by osmosdr source.")
126
127 osmogroup.add_option("-w", "--bandwidth", dest="bandwidth", type="eng_float",
128 default="0", help="Set bandwidth [default=samp_rate]")
129
130 osmogroup.add_option("", "--bb-gain", dest="bb_gain", type="eng_float",
131 default=eng_notation.num_to_str(20),
132 help="Set baseband gain [default=%default]")
133
134 osmogroup.add_option("", "--if-gain", dest="if_gain", type="eng_float",
135 default=eng_notation.num_to_str(20),
136 help="Set intermediate freque gain [default=%default]")
137
138 osmogroup.add_option("", "--ant", dest="antenna", type="string",
139 default="", help="Set antenna "
140 "[default=%default]")
141
142 osmogroup.add_option("", "--args", dest="device_args", type="string",
143 default="", help="Set device arguments "
Vasil Velichkov54580d12019-04-17 18:28:46 +0300144 "[default=%default]. Use --list-devices the view the available devices")
145
146 osmogroup.add_option("-l", "--list-devices", action="store_true",
147 help="List available SDR devices, use --args to specify hints")
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200148
149 parser.add_option_group(osmogroup)
Piotr Krysik351d2172015-09-20 13:53:06 +0200150
Roman Khassraf529e2152015-08-22 19:52:41 +0200151 (options, args) = parser.parse_args()
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200152
Vasil Velichkov54580d12019-04-17 18:28:46 +0300153 if options.list_devices:
154 grgsm.device.print_devices(options.device_args)
155 sys.exit(0)
156
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200157 if not args:
158 parser.error("Please provide an output file name to save the captured data\n")
159
160 output_filename = args[0]
161
162 if (options.freq is None and options.arfcn is None) or \
163 (options.freq is not None and options.arfcn is not None):
164 parser.error("You have to provide either a frequency or"
165 "an ARFCN (but not both).\n")
166
Roman Khassraf529e2152015-08-22 19:52:41 +0200167 arfcn = 0
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200168 freq = 0
Roman Khassraf529e2152015-08-22 19:52:41 +0200169 if options.arfcn:
Piotr Krysika80567f2017-09-11 10:01:12 +0200170 if not grgsm.arfcn.is_valid_arfcn(options.arfcn):
171 parser.error("ARFCN is not valid\n")
172 else:
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200173 freq = grgsm.arfcn.arfcn2downlink(options.arfcn)
174 elif options.freq:
175 freq = options.freq
176
177 tb = grgsm_capture(freq=freq,
178 gain=options.gain,
179 freq_corr=options.freq_corr,
180 samp_rate=options.samp_rate,
181 output_filename=output_filename,
182 rec_length=options.rec_length,
183 bandwidth=options.bandwidth,
184 bb_gain=options.bb_gain,
185 if_gain=options.if_gain,
186 antenna=options.antenna,
187 device_args=options.device_args)
188
Roman Khassraf7eda4802015-08-24 20:00:48 +0200189 def signal_handler(signal, frame):
190 tb.stop()
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200191 tb.wait()
Roman Khassraf7eda4802015-08-24 20:00:48 +0200192 sys.exit(0)
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200193
Roman Khassraf7eda4802015-08-24 20:00:48 +0200194 signal.signal(signal.SIGINT, signal_handler)
Roman Khassraf529e2152015-08-22 19:52:41 +0200195
196 tb.start()
Roman Khassraf7eda4802015-08-24 20:00:48 +0200197 tb.wait()