blob: 081544a82b2523ef94aef782fd8fbd283ca383a7 [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 Krysike11b1d32018-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 Krysike11b1d32018-09-20 14:49:27 +020030from optparse import OptionParser, OptionGroup
Roman Khassraf529e2152015-08-22 19:52:41 +020031import osmosdr
Piotr Krysike11b1d32018-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 Krysike11b1d32018-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 Krysike11b1d32018-09-20 14:49:27 +020051
Roman Khassraf529e2152015-08-22 19:52:41 +020052 ##################################################
Piotr Krysike11b1d32018-09-20 14:49:27 +020053 # Setting up RF source
Roman Khassraf529e2152015-08-22 19:52:41 +020054 ##################################################
55
Piotr Krysike11b1d32018-09-20 14:49:27 +020056 self.sdr_source = \
Vasil Velichkovb615cef2019-04-15 22:10:18 +030057 osmosdr.source(args="numchan=" + str(1) + " " + device_args)
58
Piotr Krysike11b1d32018-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 Krysike11b1d32018-09-20 14:49:27 +020072 ##################################################
73 # The rest of processing blocks
74 ##################################################
Roman Khassraf529e2152015-08-22 19:52:41 +020075
Piotr Krysike11b1d32018-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 Krysike11b1d32018-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 Krysike11b1d32018-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 Krysike11b1d32018-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 Krysike11b1d32018-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 Krysike11b1d32018-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 Krysike11b1d32018-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 Krysike11b1d32018-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 Krysike11b1d32018-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 Krysike11b1d32018-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 "
144 "[default=%default]")
145
146 parser.add_option_group(osmogroup)
Piotr Krysik351d2172015-09-20 13:53:06 +0200147
Roman Khassraf529e2152015-08-22 19:52:41 +0200148 (options, args) = parser.parse_args()
Piotr Krysike11b1d32018-09-20 14:49:27 +0200149
150 if not args:
151 parser.error("Please provide an output file name to save the captured data\n")
152
153 output_filename = args[0]
154
155 if (options.freq is None and options.arfcn is None) or \
156 (options.freq is not None and options.arfcn is not None):
157 parser.error("You have to provide either a frequency or"
158 "an ARFCN (but not both).\n")
159
Roman Khassraf529e2152015-08-22 19:52:41 +0200160 arfcn = 0
Piotr Krysike11b1d32018-09-20 14:49:27 +0200161 freq = 0
Roman Khassraf529e2152015-08-22 19:52:41 +0200162 if options.arfcn:
Piotr Krysika80567f2017-09-11 10:01:12 +0200163 if not grgsm.arfcn.is_valid_arfcn(options.arfcn):
164 parser.error("ARFCN is not valid\n")
165 else:
Piotr Krysike11b1d32018-09-20 14:49:27 +0200166 freq = grgsm.arfcn.arfcn2downlink(options.arfcn)
167 elif options.freq:
168 freq = options.freq
169
170 tb = grgsm_capture(freq=freq,
171 gain=options.gain,
172 freq_corr=options.freq_corr,
173 samp_rate=options.samp_rate,
174 output_filename=output_filename,
175 rec_length=options.rec_length,
176 bandwidth=options.bandwidth,
177 bb_gain=options.bb_gain,
178 if_gain=options.if_gain,
179 antenna=options.antenna,
180 device_args=options.device_args)
181
Roman Khassraf7eda4802015-08-24 20:00:48 +0200182 def signal_handler(signal, frame):
183 tb.stop()
Piotr Krysike11b1d32018-09-20 14:49:27 +0200184 tb.wait()
Roman Khassraf7eda4802015-08-24 20:00:48 +0200185 sys.exit(0)
Piotr Krysike11b1d32018-09-20 14:49:27 +0200186
Roman Khassraf7eda4802015-08-24 20:00:48 +0200187 signal.signal(signal.SIGINT, signal_handler)
Roman Khassraf529e2152015-08-22 19:52:41 +0200188
189 tb.start()
Roman Khassraf7eda4802015-08-24 20:00:48 +0200190 tb.wait()