blob: 7da9e06bbe531d3b8ea7314c79eb615f0667bfed [file] [log] [blame]
Piotr Krysik902f4eb2017-09-19 08:04:33 +02001#!/usr/bin/env python2
2# -*- coding: utf-8 -*-
3
4# GR-GSM based transceiver
5#
Vadim Yanitskiy435d7552019-01-19 09:02:12 +07006# (C) 2016-2019 by Vadim Yanitskiy <axilirator@gmail.com>
Piotr Krysik7379e342018-09-07 18:36:13 +07007# (C) 2017-2018 by Piotr Krysik <ptrkrysik@gmail.com>
Piotr Krysik902f4eb2017-09-19 08:04:33 +02008#
9# All Rights Reserved
10#
11# This program is free software; you can redistribute it and/or modify
12# it under the terms of the GNU General Public License as published by
13# the Free Software Foundation; either version 2 of the License, or
14# (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License along
22# with this program; if not, write to the Free Software Foundation, Inc.,
23# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
25import signal
Piotr Krysik902f4eb2017-09-19 08:04:33 +020026import sys
27
Piotr Krysik7379e342018-09-07 18:36:13 +070028from argparse import ArgumentParser
29from argparse import ArgumentTypeError
Vadim Yanitskiy97dc84e2018-08-10 05:29:23 +070030from gnuradio import eng_notation
31
Vadim Yanitskiyf237f1a2018-12-20 09:49:56 +070032from grgsm.trx import RadioInterface
Vadim Yanitskiy180a0372019-01-19 10:22:59 +070033from grgsm.trx import Transceiver
Piotr Krysik902f4eb2017-09-19 08:04:33 +020034
35COPYRIGHT = \
Vadim Yanitskiy473b35b2018-08-10 00:20:03 +070036 "Copyright (C) 2016-2018 by Vadim Yanitskiy <axilirator@gmail.com>\n" \
Piotr Krysik7379e342018-09-07 18:36:13 +070037 "Copyright (C) 2017-2018 by Piotr Krysik <ptrkrysik@gmail.com>\n" \
Piotr Krysik902f4eb2017-09-19 08:04:33 +020038 "License GPLv2+: GNU GPL version 2 or later " \
39 "<http://gnu.org/licenses/gpl.html>\n" \
40 "This is free software: you are free to change and redistribute it.\n" \
41 "There is NO WARRANTY, to the extent permitted by law.\n"
42
Piotr Krysik1cc264f2018-09-06 19:57:57 +020043class Application:
Piotr Krysik7379e342018-09-07 18:36:13 +070044 def __init__(self, argv):
45 self.remote_addr = argv.remote_addr
46 self.bind_addr = argv.bind_addr
47 self.base_port = argv.base_port
48 self.phy_args = argv.args
49 self.phy_sample_rate = argv.sample_rate
50 self.phy_rx_gain = argv.rx_gain
51 self.phy_tx_gain = argv.tx_gain
52 self.phy_rx_antenna = argv.rx_antenna
53 self.phy_tx_antenna = argv.tx_antenna
Piotr Krysikb8632ff2018-09-13 15:42:55 +020054 self.phy_freq_offset = argv.freq_offset
Piotr Krysik7379e342018-09-07 18:36:13 +070055 self.phy_ppm = argv.ppm
Piotr Krysik902f4eb2017-09-19 08:04:33 +020056
57 # Set up signal handlers
58 signal.signal(signal.SIGINT, self.sig_handler)
59
Vadim Yanitskiyca49a3e2019-01-19 12:16:17 +070060 if argv.driver == "uhd":
61 from grgsm.trx.radio_if_uhd import RadioInterfaceUHD as Radio
62 else:
63 raise ValueError("Unknown RadioInterface driver '%s'" % argv.driver)
64
Piotr Krysik902f4eb2017-09-19 08:04:33 +020065 # Init Radio interface
Vadim Yanitskiyca49a3e2019-01-19 12:16:17 +070066 self.radio = Radio(self.phy_args, self.phy_sample_rate,
Vadim Yanitskiy790b6f02017-10-17 11:47:36 +070067 self.phy_rx_gain, self.phy_tx_gain, self.phy_ppm,
Piotr Krysik1cc264f2018-09-06 19:57:57 +020068 self.phy_rx_antenna, self.phy_tx_antenna,
Piotr Krysikb8632ff2018-09-13 15:42:55 +020069 self.phy_freq_offset, self.bind_addr,
Piotr Krysik06317672018-09-13 14:41:06 +020070 self.remote_addr, self.base_port)
Piotr Krysik902f4eb2017-09-19 08:04:33 +020071
Vadim Yanitskiy180a0372019-01-19 10:22:59 +070072 # Init Transceiver
73 self.trx = Transceiver(self.bind_addr,
74 self.remote_addr, self.base_port,
75 radio_if = self.radio)
Piotr Krysik902f4eb2017-09-19 08:04:33 +020076
77 print("[i] Init complete")
78
Vadim Yanitskiy435d7552019-01-19 09:02:12 +070079 def run(self):
Piotr Krysik902f4eb2017-09-19 08:04:33 +020080 # Enter main loop
81 while True:
Vadim Yanitskiy180a0372019-01-19 10:22:59 +070082 self.trx.ctrl_if.loop()
Piotr Krysik902f4eb2017-09-19 08:04:33 +020083
84 def shutdown(self):
85 print("[i] Shutting down...")
Piotr Krysik902f4eb2017-09-19 08:04:33 +020086 self.radio.shutdown()
87
Piotr Krysik902f4eb2017-09-19 08:04:33 +020088 def sig_handler(self, signum, frame):
89 print("Signal %d received" % signum)
90 if signum is signal.SIGINT:
91 self.shutdown()
92 sys.exit(0)
93
Piotr Krysik7379e342018-09-07 18:36:13 +070094def eng_float(value):
95 try:
96 return eng_notation.str_to_num(value)
97 except:
98 raise ArgumentTypeError("invalid engineering notation "
99 "value: {0}".format(value))
100
101def parse_argv():
102 parser = ArgumentParser(prog = "grgsm_trx")
103
104 # TRX interface specific
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700105 trx_group = parser.add_argument_group("TRX interface")
106 trx_group.add_argument("-i", "--remote-addr",
Piotr Krysik7379e342018-09-07 18:36:13 +0700107 dest = "remote_addr", type = str, default = "127.0.0.1",
108 help = "Set remote address (default %(default)s)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700109 trx_group.add_argument("-b", "--bind-addr",
Piotr Krysik7379e342018-09-07 18:36:13 +0700110 dest = "bind_addr", type = str, default = "0.0.0.0",
111 help = "Set bind address (default %(default)s)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700112 trx_group.add_argument("-p", "--base_port",
Piotr Krysik7379e342018-09-07 18:36:13 +0700113 dest = "base_port", type = int, default = 6700,
114 help = "Set base port number (default %(default)s)")
115
116 # PHY specific
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700117 phy_group = parser.add_argument_group("PHY parameters")
Vadim Yanitskiyca49a3e2019-01-19 12:16:17 +0700118 phy_group.add_argument("--driver",
119 dest = "driver", type = str, default = "uhd",
120 choices = ["uhd"],
121 help = "Set device driver (default %(default)s)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700122 phy_group.add_argument("-a", "--args",
Piotr Krysik7379e342018-09-07 18:36:13 +0700123 dest = "args", type = str, default = "",
124 help = "Set device arguments")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700125 phy_group.add_argument("-s", "--sample-rate",
Piotr Krysik7379e342018-09-07 18:36:13 +0700126 dest = "sample_rate", type = eng_float,
Vadim Yanitskiyf237f1a2018-12-20 09:49:56 +0700127 default = RadioInterface.SAMPLE_RATE,
Piotr Krysik7379e342018-09-07 18:36:13 +0700128 help = "Set samp_rate (default %(default)s)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700129 phy_group.add_argument("-g", "--rx-gain",
Piotr Krysik7379e342018-09-07 18:36:13 +0700130 dest = "rx_gain", type = float, default = 30,
131 help = "Set RX gain (default %(default)s)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700132 phy_group.add_argument("-G", "--tx-gain",
Piotr Krysik7379e342018-09-07 18:36:13 +0700133 dest = "tx_gain", type = float, default = 10,
134 help = "Set TX gain (default %(default)s)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700135 phy_group.add_argument("--rx-antenna",
Piotr Krysik7379e342018-09-07 18:36:13 +0700136 dest = "rx_antenna", type = str, default = "RX2",
137 help = "Set RX antenna (default %(default)s)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700138 phy_group.add_argument("--tx-antenna",
Piotr Krysik7379e342018-09-07 18:36:13 +0700139 dest = "tx_antenna", type = str, default = "TX/RX",
140 help = "Set TX antenna (default %(default)s)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700141 phy_group.add_argument("--freq-offset",
Piotr Krysik7379e342018-09-07 18:36:13 +0700142 dest = "freq_offset", type = eng_float, default = 0,
143 help = "Shift baseband freq. (e.g. -500M)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700144 phy_group.add_argument("--ppm",
Piotr Krysik7379e342018-09-07 18:36:13 +0700145 dest = "ppm", type = float, default = 0,
146 help = "Set frequency correction (default %(default)s)")
147
148 return parser.parse_args()
149
Piotr Krysikc62a3d92018-09-05 21:36:34 +0200150if __name__ == '__main__':
Piotr Krysik7379e342018-09-07 18:36:13 +0700151 print(COPYRIGHT)
152 argv = parse_argv()
153 app = Application(argv)
Piotr Krysik1cc264f2018-09-06 19:57:57 +0200154 app.run()