blob: f698205ac60c6f25f7ec4fca9660ac512fae9ce3 [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
Piotr Krysik81ba56f2018-09-20 14:49:27 +020056 self.sdr_source = \
57 osmosdr.source(args="numchan=1" + device_args )
58 self.sdr_source.set_sample_rate(samp_rate)
59 self.sdr_source.set_center_freq(freq, 0)
60 self.sdr_source.set_freq_corr(freq_corr, 0)
61 self.sdr_source.set_dc_offset_mode(2, 0)
62 self.sdr_source.set_iq_balance_mode(2, 0)
63 self.sdr_source.set_gain_mode(True, 0)
64 self.sdr_source.set_gain(gain, 0)
65 self.sdr_source.set_if_gain(if_gain, 0)
66 self.sdr_source.set_bb_gain(bb_gain, 0)
67 self.sdr_source.set_antenna("", 0)
68 if bandwidth != 0:
69 self.sdr_source.set_bandwidth(bandwidth, 0)
Roman Khassraf529e2152015-08-22 19:52:41 +020070
Piotr Krysik81ba56f2018-09-20 14:49:27 +020071 ##################################################
72 # The rest of processing blocks
73 ##################################################
Roman Khassraf529e2152015-08-22 19:52:41 +020074
Piotr Krysik81ba56f2018-09-20 14:49:27 +020075 if rec_length != float('Inf'):
76 self.head = \
77 blocks.head(gr.sizeof_gr_complex, int(samp_rate*rec_length))
Roman Khassraf529e2152015-08-22 19:52:41 +020078
Piotr Krysik81ba56f2018-09-20 14:49:27 +020079 self.file_sink = blocks.file_sink(gr.sizeof_gr_complex*1, \
80 output_filename, False)
81 self.file_sink.set_unbuffered(False)
Roman Khassraf529e2152015-08-22 19:52:41 +020082
83 ##################################################
84 # Connections
85 ##################################################
86
Piotr Krysik81ba56f2018-09-20 14:49:27 +020087 if rec_length != float('Inf'): #if recording length is not infinite
88 #connect head block after the source
89 self.connect((self.sdr_source, 0), (self.head, 0))
90 self.connect((self.head, 0), (self.file_sink, 0))
Piotr Krysik351d2172015-09-20 13:53:06 +020091 else:
Piotr Krysik81ba56f2018-09-20 14:49:27 +020092 self.connect((self.sdr_source, 0), (self.file_sink, 0))
Piotr Krysik351d2172015-09-20 13:53:06 +020093
Roman Khassraf529e2152015-08-22 19:52:41 +020094if __name__ == '__main__':
Roman Khassraf529e2152015-08-22 19:52:41 +020095
Piotr Krysik81ba56f2018-09-20 14:49:27 +020096 parser = OptionParser(option_class=eng_option, usage="%prog [options] output_filename",
Roman Khassraf529e2152015-08-22 19:52:41 +020097 description="RTL-SDR capturing app of gr-gsm.")
Roman Khassraf529e2152015-08-22 19:52:41 +020098
Piotr Krysik81ba56f2018-09-20 14:49:27 +020099 parser.add_option("-f", "--freq", dest="freq", type="eng_float",
Roman Khassraf529e2152015-08-22 19:52:41 +0200100 help="Set frequency [default=%default]")
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200101
102 parser.add_option("-a", "--arfcn", dest="arfcn", type="intx",
103 help="Set ARFCN instead of frequency (for PCS1900 add"
104 "0x8000 (2**15) to the ARFCN number)")
105
106 parser.add_option("-g", "--gain", dest="gain", type="eng_float",
Roman Khassraf529e2152015-08-22 19:52:41 +0200107 default=eng_notation.num_to_str(30),
108 help="Set gain [default=%default]")
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200109
110 parser.add_option("-s", "--samp-rate", dest="samp_rate", type="eng_float",
Piotr Krysik96485402016-07-21 16:06:03 +0200111 default=eng_notation.num_to_str(1000000),
Roman Khassraf529e2152015-08-22 19:52:41 +0200112 help="Set samp_rate [default=%default]")
Piotr Krysik7185b662016-02-14 20:24:54 +0100113
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200114 parser.add_option("-T", "--rec-length", dest="rec_length", type="float",
115 default='Inf', help="Set length of recording in seconds "
116 "[default=infinity]")
Piotr Krysik351d2172015-09-20 13:53:06 +0200117
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200118 parser.add_option("-p", "--freq-corr", dest="freq_corr", type="eng_float",
119 default="0", help="Set frequency correction in"
120 " ppm [default=%default]")
121
122 osmogroup = OptionGroup(parser, 'Additional osmosdr source options',
123 "Options specific to a subset of SDR receivers "
124 "supported by osmosdr source.")
125
126 osmogroup.add_option("-w", "--bandwidth", dest="bandwidth", type="eng_float",
127 default="0", help="Set bandwidth [default=samp_rate]")
128
129 osmogroup.add_option("", "--bb-gain", dest="bb_gain", type="eng_float",
130 default=eng_notation.num_to_str(20),
131 help="Set baseband gain [default=%default]")
132
133 osmogroup.add_option("", "--if-gain", dest="if_gain", type="eng_float",
134 default=eng_notation.num_to_str(20),
135 help="Set intermediate freque gain [default=%default]")
136
137 osmogroup.add_option("", "--ant", dest="antenna", type="string",
138 default="", help="Set antenna "
139 "[default=%default]")
140
141 osmogroup.add_option("", "--args", dest="device_args", type="string",
142 default="", help="Set device arguments "
143 "[default=%default]")
144
145 parser.add_option_group(osmogroup)
Piotr Krysik351d2172015-09-20 13:53:06 +0200146
Roman Khassraf529e2152015-08-22 19:52:41 +0200147 (options, args) = parser.parse_args()
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200148
149 if not args:
150 parser.error("Please provide an output file name to save the captured data\n")
151
152 output_filename = args[0]
153
154 if (options.freq is None and options.arfcn is None) or \
155 (options.freq is not None and options.arfcn is not None):
156 parser.error("You have to provide either a frequency or"
157 "an ARFCN (but not both).\n")
158
Roman Khassraf529e2152015-08-22 19:52:41 +0200159 arfcn = 0
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200160 freq = 0
Roman Khassraf529e2152015-08-22 19:52:41 +0200161 if options.arfcn:
Piotr Krysika80567f2017-09-11 10:01:12 +0200162 if not grgsm.arfcn.is_valid_arfcn(options.arfcn):
163 parser.error("ARFCN is not valid\n")
164 else:
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200165 freq = grgsm.arfcn.arfcn2downlink(options.arfcn)
166 elif options.freq:
167 freq = options.freq
168
169 tb = grgsm_capture(freq=freq,
170 gain=options.gain,
171 freq_corr=options.freq_corr,
172 samp_rate=options.samp_rate,
173 output_filename=output_filename,
174 rec_length=options.rec_length,
175 bandwidth=options.bandwidth,
176 bb_gain=options.bb_gain,
177 if_gain=options.if_gain,
178 antenna=options.antenna,
179 device_args=options.device_args)
180
Roman Khassraf7eda4802015-08-24 20:00:48 +0200181 def signal_handler(signal, frame):
182 tb.stop()
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200183 tb.wait()
Roman Khassraf7eda4802015-08-24 20:00:48 +0200184 sys.exit(0)
Piotr Krysik81ba56f2018-09-20 14:49:27 +0200185
Roman Khassraf7eda4802015-08-24 20:00:48 +0200186 signal.signal(signal.SIGINT, signal_handler)
Roman Khassraf529e2152015-08-22 19:52:41 +0200187
188 tb.start()
Roman Khassraf7eda4802015-08-24 20:00:48 +0200189 tb.wait()