blob: 6b3565d950cd0049e7a1ff38d472f93bbeae6153 [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 Yanitskiy473b35b2018-08-10 00:20:03 +07006# (C) 2016-2018 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 Yanitskiyba7ad292017-10-17 07:21:59 +070032from grgsm.trx import ctrl_if_bb
33from grgsm.trx import radio_if
34from grgsm.trx import fake_pm
Piotr Krysik902f4eb2017-09-19 08:04:33 +020035
36COPYRIGHT = \
Vadim Yanitskiy473b35b2018-08-10 00:20:03 +070037 "Copyright (C) 2016-2018 by Vadim Yanitskiy <axilirator@gmail.com>\n" \
Piotr Krysik7379e342018-09-07 18:36:13 +070038 "Copyright (C) 2017-2018 by Piotr Krysik <ptrkrysik@gmail.com>\n" \
Piotr Krysik902f4eb2017-09-19 08:04:33 +020039 "License GPLv2+: GNU GPL version 2 or later " \
40 "<http://gnu.org/licenses/gpl.html>\n" \
41 "This is free software: you are free to change and redistribute it.\n" \
42 "There is NO WARRANTY, to the extent permitted by law.\n"
43
Piotr Krysik1cc264f2018-09-06 19:57:57 +020044class Application:
Piotr Krysik7379e342018-09-07 18:36:13 +070045 def __init__(self, argv):
46 self.remote_addr = argv.remote_addr
47 self.bind_addr = argv.bind_addr
48 self.base_port = argv.base_port
49 self.phy_args = argv.args
50 self.phy_sample_rate = argv.sample_rate
51 self.phy_rx_gain = argv.rx_gain
52 self.phy_tx_gain = argv.tx_gain
53 self.phy_rx_antenna = argv.rx_antenna
54 self.phy_tx_antenna = argv.tx_antenna
Piotr Krysikb8632ff2018-09-13 15:42:55 +020055 self.phy_freq_offset = argv.freq_offset
Piotr Krysik7379e342018-09-07 18:36:13 +070056 self.phy_ppm = argv.ppm
Piotr Krysik902f4eb2017-09-19 08:04:33 +020057
58 # Set up signal handlers
59 signal.signal(signal.SIGINT, self.sig_handler)
60
61 def run(self):
62 # Init Radio interface
Vadim Yanitskiy5d68aa52017-10-17 11:14:48 +070063 self.radio = radio_if(self.phy_args, self.phy_sample_rate,
Vadim Yanitskiy790b6f02017-10-17 11:47:36 +070064 self.phy_rx_gain, self.phy_tx_gain, self.phy_ppm,
Piotr Krysik1cc264f2018-09-06 19:57:57 +020065 self.phy_rx_antenna, self.phy_tx_antenna,
Piotr Krysikb8632ff2018-09-13 15:42:55 +020066 self.phy_freq_offset, self.bind_addr,
Piotr Krysik06317672018-09-13 14:41:06 +020067 self.remote_addr, self.base_port)
Piotr Krysik902f4eb2017-09-19 08:04:33 +020068
69 # Power measurement emulation
70 # Noise: -120 .. -105
71 # BTS: -75 .. -50
Vadim Yanitskiyba7ad292017-10-17 07:21:59 +070072 self.pm = fake_pm(-120, -105, -75, -50)
Piotr Krysik902f4eb2017-09-19 08:04:33 +020073
74 # Init TRX CTRL interface
Vadim Yanitskiy473b35b2018-08-10 00:20:03 +070075 self.server = ctrl_if_bb(
76 self.remote_addr, self.base_port + 101,
77 self.bind_addr, self.base_port + 1,
Piotr Krysik902f4eb2017-09-19 08:04:33 +020078 self.radio, self.pm)
79
80 print("[i] Init complete")
81
82 # Enter main loop
83 while True:
84 self.server.loop()
85
86 def shutdown(self):
87 print("[i] Shutting down...")
Piotr Krysik902f4eb2017-09-19 08:04:33 +020088 self.radio.shutdown()
89
Piotr Krysik902f4eb2017-09-19 08:04:33 +020090 def sig_handler(self, signum, frame):
91 print("Signal %d received" % signum)
92 if signum is signal.SIGINT:
93 self.shutdown()
94 sys.exit(0)
95
Piotr Krysik7379e342018-09-07 18:36:13 +070096def eng_float(value):
97 try:
98 return eng_notation.str_to_num(value)
99 except:
100 raise ArgumentTypeError("invalid engineering notation "
101 "value: {0}".format(value))
102
103def parse_argv():
104 parser = ArgumentParser(prog = "grgsm_trx")
105
106 # TRX interface specific
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700107 trx_group = parser.add_argument_group("TRX interface")
108 trx_group.add_argument("-i", "--remote-addr",
Piotr Krysik7379e342018-09-07 18:36:13 +0700109 dest = "remote_addr", type = str, default = "127.0.0.1",
110 help = "Set remote address (default %(default)s)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700111 trx_group.add_argument("-b", "--bind-addr",
Piotr Krysik7379e342018-09-07 18:36:13 +0700112 dest = "bind_addr", type = str, default = "0.0.0.0",
113 help = "Set bind address (default %(default)s)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700114 trx_group.add_argument("-p", "--base_port",
Piotr Krysik7379e342018-09-07 18:36:13 +0700115 dest = "base_port", type = int, default = 6700,
116 help = "Set base port number (default %(default)s)")
117
118 # PHY specific
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700119 phy_group = parser.add_argument_group("PHY parameters")
120 phy_group.add_argument("-a", "--args",
Piotr Krysik7379e342018-09-07 18:36:13 +0700121 dest = "args", type = str, default = "",
122 help = "Set device arguments")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700123 phy_group.add_argument("-s", "--sample-rate",
Piotr Krysik7379e342018-09-07 18:36:13 +0700124 dest = "sample_rate", type = eng_float,
125 default = radio_if.SAMPLE_RATE,
126 help = "Set samp_rate (default %(default)s)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700127 phy_group.add_argument("-g", "--rx-gain",
Piotr Krysik7379e342018-09-07 18:36:13 +0700128 dest = "rx_gain", type = float, default = 30,
129 help = "Set RX gain (default %(default)s)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700130 phy_group.add_argument("-G", "--tx-gain",
Piotr Krysik7379e342018-09-07 18:36:13 +0700131 dest = "tx_gain", type = float, default = 10,
132 help = "Set TX gain (default %(default)s)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700133 phy_group.add_argument("--rx-antenna",
Piotr Krysik7379e342018-09-07 18:36:13 +0700134 dest = "rx_antenna", type = str, default = "RX2",
135 help = "Set RX antenna (default %(default)s)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700136 phy_group.add_argument("--tx-antenna",
Piotr Krysik7379e342018-09-07 18:36:13 +0700137 dest = "tx_antenna", type = str, default = "TX/RX",
138 help = "Set TX antenna (default %(default)s)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700139 phy_group.add_argument("--freq-offset",
Piotr Krysik7379e342018-09-07 18:36:13 +0700140 dest = "freq_offset", type = eng_float, default = 0,
141 help = "Shift baseband freq. (e.g. -500M)")
Vadim Yanitskiyed03e412018-09-21 14:52:53 +0700142 phy_group.add_argument("--ppm",
Piotr Krysik7379e342018-09-07 18:36:13 +0700143 dest = "ppm", type = float, default = 0,
144 help = "Set frequency correction (default %(default)s)")
145
146 return parser.parse_args()
147
Piotr Krysikc62a3d92018-09-05 21:36:34 +0200148if __name__ == '__main__':
Piotr Krysik7379e342018-09-07 18:36:13 +0700149 print(COPYRIGHT)
150 argv = parse_argv()
151 app = Application(argv)
Piotr Krysik1cc264f2018-09-06 19:57:57 +0200152 app.run()