blob: b53d12ac6f15ee02011a7ccd4391d4f0cca1b5f0 [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 Yanitskiy21655842018-08-10 00:20:03 +07006# (C) 2016-2018 by Vadim Yanitskiy <axilirator@gmail.com>
Piotr Krysik262bda12018-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 Krysik262bda12018-09-07 18:36:13 +070028from argparse import ArgumentParser
29from argparse import ArgumentTypeError
Vadim Yanitskiy3f9abbd2018-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 Yanitskiy21655842018-08-10 00:20:03 +070037 "Copyright (C) 2016-2018 by Vadim Yanitskiy <axilirator@gmail.com>\n" \
Piotr Krysik262bda12018-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 Krysikba6fd0e2018-09-06 19:57:57 +020044class Application:
Piotr Krysik262bda12018-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 Krysikba6fd0e2018-09-06 19:57:57 +020065 self.phy_rx_antenna, self.phy_tx_antenna,
Piotr Krysik11583ad2018-09-13 14:41:06 +020066 self.phy_freq_offset_hz, self.bind_addr,
67 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 Yanitskiy21655842018-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 Krysik262bda12018-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
107 parser.add_argument("-i", "--remote-addr",
108 dest = "remote_addr", type = str, default = "127.0.0.1",
109 help = "Set remote address (default %(default)s)")
110 parser.add_argument("-b", "--bind-addr",
111 dest = "bind_addr", type = str, default = "0.0.0.0",
112 help = "Set bind address (default %(default)s)")
113 parser.add_argument("-p", "--base_port",
114 dest = "base_port", type = int, default = 6700,
115 help = "Set base port number (default %(default)s)")
116
117 # PHY specific
118 parser.add_argument("-a", "--args",
119 dest = "args", type = str, default = "",
120 help = "Set device arguments")
121 parser.add_argument("-s", "--sample-rate",
122 dest = "sample_rate", type = eng_float,
123 default = radio_if.SAMPLE_RATE,
124 help = "Set samp_rate (default %(default)s)")
125 parser.add_argument("-g", "--rx-gain",
126 dest = "rx_gain", type = float, default = 30,
127 help = "Set RX gain (default %(default)s)")
128 parser.add_argument("-G", "--tx-gain",
129 dest = "tx_gain", type = float, default = 10,
130 help = "Set TX gain (default %(default)s)")
131 parser.add_argument("--rx-antenna",
132 dest = "rx_antenna", type = str, default = "RX2",
133 help = "Set RX antenna (default %(default)s)")
134 parser.add_argument("--tx-antenna",
135 dest = "tx_antenna", type = str, default = "TX/RX",
136 help = "Set TX antenna (default %(default)s)")
137 parser.add_argument("--freq-offset",
138 dest = "freq_offset", type = eng_float, default = 0,
139 help = "Shift baseband freq. (e.g. -500M)")
140 parser.add_argument("--ppm",
141 dest = "ppm", type = float, default = 0,
142 help = "Set frequency correction (default %(default)s)")
143
144 return parser.parse_args()
145
Piotr Krysikfcb64a82018-09-05 21:36:34 +0200146if __name__ == '__main__':
Piotr Krysik262bda12018-09-07 18:36:13 +0700147 print(COPYRIGHT)
148 argv = parse_argv()
149 app = Application(argv)
Piotr Krysikba6fd0e2018-09-06 19:57:57 +0200150 app.run()