blob: d57c979579981cd8e0e48a54e042185eefd66f76 [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
55 self.phy_freq_offset_hz = argv.freq_offset
56 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,
Vadim Yanitskiy473b35b2018-08-10 00:20:03 +070066 self.bind_addr, self.remote_addr,
67 self.base_port)
Piotr Krysik902f4eb2017-09-19 08:04:33 +020068
Piotr Krysik1cc264f2018-09-06 19:57:57 +020069 # Optional frequency offset
70 if self.phy_freq_offset_hz is not None:
71 self.radio.freq_offset_hz = self.phy_freq_offset_hz
72
Piotr Krysik902f4eb2017-09-19 08:04:33 +020073 # Power measurement emulation
74 # Noise: -120 .. -105
75 # BTS: -75 .. -50
Vadim Yanitskiyba7ad292017-10-17 07:21:59 +070076 self.pm = fake_pm(-120, -105, -75, -50)
Piotr Krysik902f4eb2017-09-19 08:04:33 +020077
78 # Init TRX CTRL interface
Vadim Yanitskiy473b35b2018-08-10 00:20:03 +070079 self.server = ctrl_if_bb(
80 self.remote_addr, self.base_port + 101,
81 self.bind_addr, self.base_port + 1,
Piotr Krysik902f4eb2017-09-19 08:04:33 +020082 self.radio, self.pm)
83
84 print("[i] Init complete")
85
86 # Enter main loop
87 while True:
88 self.server.loop()
89
90 def shutdown(self):
91 print("[i] Shutting down...")
Piotr Krysik902f4eb2017-09-19 08:04:33 +020092 self.radio.shutdown()
93
Piotr Krysik902f4eb2017-09-19 08:04:33 +020094 def sig_handler(self, signum, frame):
95 print("Signal %d received" % signum)
96 if signum is signal.SIGINT:
97 self.shutdown()
98 sys.exit(0)
99
Piotr Krysik7379e342018-09-07 18:36:13 +0700100def eng_float(value):
101 try:
102 return eng_notation.str_to_num(value)
103 except:
104 raise ArgumentTypeError("invalid engineering notation "
105 "value: {0}".format(value))
106
107def parse_argv():
108 parser = ArgumentParser(prog = "grgsm_trx")
109
110 # TRX interface specific
111 parser.add_argument("-i", "--remote-addr",
112 dest = "remote_addr", type = str, default = "127.0.0.1",
113 help = "Set remote address (default %(default)s)")
114 parser.add_argument("-b", "--bind-addr",
115 dest = "bind_addr", type = str, default = "0.0.0.0",
116 help = "Set bind address (default %(default)s)")
117 parser.add_argument("-p", "--base_port",
118 dest = "base_port", type = int, default = 6700,
119 help = "Set base port number (default %(default)s)")
120
121 # PHY specific
122 parser.add_argument("-a", "--args",
123 dest = "args", type = str, default = "",
124 help = "Set device arguments")
125 parser.add_argument("-s", "--sample-rate",
126 dest = "sample_rate", type = eng_float,
127 default = radio_if.SAMPLE_RATE,
128 help = "Set samp_rate (default %(default)s)")
129 parser.add_argument("-g", "--rx-gain",
130 dest = "rx_gain", type = float, default = 30,
131 help = "Set RX gain (default %(default)s)")
132 parser.add_argument("-G", "--tx-gain",
133 dest = "tx_gain", type = float, default = 10,
134 help = "Set TX gain (default %(default)s)")
135 parser.add_argument("--rx-antenna",
136 dest = "rx_antenna", type = str, default = "RX2",
137 help = "Set RX antenna (default %(default)s)")
138 parser.add_argument("--tx-antenna",
139 dest = "tx_antenna", type = str, default = "TX/RX",
140 help = "Set TX antenna (default %(default)s)")
141 parser.add_argument("--freq-offset",
142 dest = "freq_offset", type = eng_float, default = 0,
143 help = "Shift baseband freq. (e.g. -500M)")
144 parser.add_argument("--ppm",
145 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()