Piotr Krysik | 902f4eb | 2017-09-19 08:04:33 +0200 | [diff] [blame] | 1 | #!/usr/bin/env python2 |
| 2 | # -*- coding: utf-8 -*- |
| 3 | |
| 4 | # GR-GSM based transceiver |
| 5 | # |
Vadim Yanitskiy | 3e6bfe7 | 2019-01-19 09:02:12 +0700 | [diff] [blame] | 6 | # (C) 2016-2019 by Vadim Yanitskiy <axilirator@gmail.com> |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 7 | # (C) 2017-2018 by Piotr Krysik <ptrkrysik@gmail.com> |
Piotr Krysik | 902f4eb | 2017-09-19 08:04:33 +0200 | [diff] [blame] | 8 | # |
| 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 | |
| 25 | import signal |
Piotr Krysik | 902f4eb | 2017-09-19 08:04:33 +0200 | [diff] [blame] | 26 | import sys |
| 27 | |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 28 | from argparse import ArgumentParser |
| 29 | from argparse import ArgumentTypeError |
Vadim Yanitskiy | 3f9abbd | 2018-08-10 05:29:23 +0700 | [diff] [blame] | 30 | from gnuradio import eng_notation |
| 31 | |
Vadim Yanitskiy | 6ee957f | 2019-01-19 11:55:01 +0700 | [diff] [blame] | 32 | from grgsm.trx import RadioInterfaceUHD |
Vadim Yanitskiy | 44d8c1e | 2018-12-20 09:49:56 +0700 | [diff] [blame] | 33 | from grgsm.trx import RadioInterface |
Vadim Yanitskiy | 2cbc3b5 | 2019-01-19 10:22:59 +0700 | [diff] [blame] | 34 | from grgsm.trx import Transceiver |
Piotr Krysik | 902f4eb | 2017-09-19 08:04:33 +0200 | [diff] [blame] | 35 | |
| 36 | COPYRIGHT = \ |
Vadim Yanitskiy | 2165584 | 2018-08-10 00:20:03 +0700 | [diff] [blame] | 37 | "Copyright (C) 2016-2018 by Vadim Yanitskiy <axilirator@gmail.com>\n" \ |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 38 | "Copyright (C) 2017-2018 by Piotr Krysik <ptrkrysik@gmail.com>\n" \ |
Piotr Krysik | 902f4eb | 2017-09-19 08:04:33 +0200 | [diff] [blame] | 39 | "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 Krysik | ba6fd0e | 2018-09-06 19:57:57 +0200 | [diff] [blame] | 44 | class Application: |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 45 | 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 Krysik | db65883 | 2018-09-13 15:42:55 +0200 | [diff] [blame] | 55 | self.phy_freq_offset = argv.freq_offset |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 56 | self.phy_ppm = argv.ppm |
Piotr Krysik | 902f4eb | 2017-09-19 08:04:33 +0200 | [diff] [blame] | 57 | |
| 58 | # Set up signal handlers |
| 59 | signal.signal(signal.SIGINT, self.sig_handler) |
| 60 | |
Piotr Krysik | 902f4eb | 2017-09-19 08:04:33 +0200 | [diff] [blame] | 61 | # Init Radio interface |
Vadim Yanitskiy | 6ee957f | 2019-01-19 11:55:01 +0700 | [diff] [blame] | 62 | self.radio = RadioInterfaceUHD(self.phy_args, self.phy_sample_rate, |
Vadim Yanitskiy | 790b6f0 | 2017-10-17 11:47:36 +0700 | [diff] [blame] | 63 | self.phy_rx_gain, self.phy_tx_gain, self.phy_ppm, |
Piotr Krysik | ba6fd0e | 2018-09-06 19:57:57 +0200 | [diff] [blame] | 64 | self.phy_rx_antenna, self.phy_tx_antenna, |
Piotr Krysik | db65883 | 2018-09-13 15:42:55 +0200 | [diff] [blame] | 65 | self.phy_freq_offset, self.bind_addr, |
Piotr Krysik | 11583ad | 2018-09-13 14:41:06 +0200 | [diff] [blame] | 66 | self.remote_addr, self.base_port) |
Piotr Krysik | 902f4eb | 2017-09-19 08:04:33 +0200 | [diff] [blame] | 67 | |
Vadim Yanitskiy | 2cbc3b5 | 2019-01-19 10:22:59 +0700 | [diff] [blame] | 68 | # Init Transceiver |
| 69 | self.trx = Transceiver(self.bind_addr, |
| 70 | self.remote_addr, self.base_port, |
| 71 | radio_if = self.radio) |
Piotr Krysik | 902f4eb | 2017-09-19 08:04:33 +0200 | [diff] [blame] | 72 | |
| 73 | print("[i] Init complete") |
| 74 | |
Vadim Yanitskiy | 3e6bfe7 | 2019-01-19 09:02:12 +0700 | [diff] [blame] | 75 | def run(self): |
Piotr Krysik | 902f4eb | 2017-09-19 08:04:33 +0200 | [diff] [blame] | 76 | # Enter main loop |
| 77 | while True: |
Vadim Yanitskiy | 2cbc3b5 | 2019-01-19 10:22:59 +0700 | [diff] [blame] | 78 | self.trx.ctrl_if.loop() |
Piotr Krysik | 902f4eb | 2017-09-19 08:04:33 +0200 | [diff] [blame] | 79 | |
| 80 | def shutdown(self): |
| 81 | print("[i] Shutting down...") |
Piotr Krysik | 902f4eb | 2017-09-19 08:04:33 +0200 | [diff] [blame] | 82 | self.radio.shutdown() |
| 83 | |
Piotr Krysik | 902f4eb | 2017-09-19 08:04:33 +0200 | [diff] [blame] | 84 | def sig_handler(self, signum, frame): |
| 85 | print("Signal %d received" % signum) |
| 86 | if signum is signal.SIGINT: |
| 87 | self.shutdown() |
| 88 | sys.exit(0) |
| 89 | |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 90 | def eng_float(value): |
| 91 | try: |
| 92 | return eng_notation.str_to_num(value) |
| 93 | except: |
| 94 | raise ArgumentTypeError("invalid engineering notation " |
| 95 | "value: {0}".format(value)) |
| 96 | |
| 97 | def parse_argv(): |
| 98 | parser = ArgumentParser(prog = "grgsm_trx") |
| 99 | |
| 100 | # TRX interface specific |
Vadim Yanitskiy | ef93382 | 2018-09-21 14:52:53 +0700 | [diff] [blame] | 101 | trx_group = parser.add_argument_group("TRX interface") |
| 102 | trx_group.add_argument("-i", "--remote-addr", |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 103 | dest = "remote_addr", type = str, default = "127.0.0.1", |
| 104 | help = "Set remote address (default %(default)s)") |
Vadim Yanitskiy | ef93382 | 2018-09-21 14:52:53 +0700 | [diff] [blame] | 105 | trx_group.add_argument("-b", "--bind-addr", |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 106 | dest = "bind_addr", type = str, default = "0.0.0.0", |
| 107 | help = "Set bind address (default %(default)s)") |
Vadim Yanitskiy | ef93382 | 2018-09-21 14:52:53 +0700 | [diff] [blame] | 108 | trx_group.add_argument("-p", "--base_port", |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 109 | dest = "base_port", type = int, default = 6700, |
| 110 | help = "Set base port number (default %(default)s)") |
| 111 | |
| 112 | # PHY specific |
Vadim Yanitskiy | ef93382 | 2018-09-21 14:52:53 +0700 | [diff] [blame] | 113 | phy_group = parser.add_argument_group("PHY parameters") |
| 114 | phy_group.add_argument("-a", "--args", |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 115 | dest = "args", type = str, default = "", |
| 116 | help = "Set device arguments") |
Vadim Yanitskiy | ef93382 | 2018-09-21 14:52:53 +0700 | [diff] [blame] | 117 | phy_group.add_argument("-s", "--sample-rate", |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 118 | dest = "sample_rate", type = eng_float, |
Vadim Yanitskiy | 44d8c1e | 2018-12-20 09:49:56 +0700 | [diff] [blame] | 119 | default = RadioInterface.SAMPLE_RATE, |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 120 | help = "Set samp_rate (default %(default)s)") |
Vadim Yanitskiy | ef93382 | 2018-09-21 14:52:53 +0700 | [diff] [blame] | 121 | phy_group.add_argument("-g", "--rx-gain", |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 122 | dest = "rx_gain", type = float, default = 30, |
| 123 | help = "Set RX gain (default %(default)s)") |
Vadim Yanitskiy | ef93382 | 2018-09-21 14:52:53 +0700 | [diff] [blame] | 124 | phy_group.add_argument("-G", "--tx-gain", |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 125 | dest = "tx_gain", type = float, default = 10, |
| 126 | help = "Set TX gain (default %(default)s)") |
Vadim Yanitskiy | ef93382 | 2018-09-21 14:52:53 +0700 | [diff] [blame] | 127 | phy_group.add_argument("--rx-antenna", |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 128 | dest = "rx_antenna", type = str, default = "RX2", |
| 129 | help = "Set RX antenna (default %(default)s)") |
Vadim Yanitskiy | ef93382 | 2018-09-21 14:52:53 +0700 | [diff] [blame] | 130 | phy_group.add_argument("--tx-antenna", |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 131 | dest = "tx_antenna", type = str, default = "TX/RX", |
| 132 | help = "Set TX antenna (default %(default)s)") |
Vadim Yanitskiy | ef93382 | 2018-09-21 14:52:53 +0700 | [diff] [blame] | 133 | phy_group.add_argument("--freq-offset", |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 134 | dest = "freq_offset", type = eng_float, default = 0, |
| 135 | help = "Shift baseband freq. (e.g. -500M)") |
Vadim Yanitskiy | ef93382 | 2018-09-21 14:52:53 +0700 | [diff] [blame] | 136 | phy_group.add_argument("--ppm", |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 137 | dest = "ppm", type = float, default = 0, |
| 138 | help = "Set frequency correction (default %(default)s)") |
| 139 | |
| 140 | return parser.parse_args() |
| 141 | |
Piotr Krysik | fcb64a8 | 2018-09-05 21:36:34 +0200 | [diff] [blame] | 142 | if __name__ == '__main__': |
Piotr Krysik | 262bda1 | 2018-09-07 18:36:13 +0700 | [diff] [blame] | 143 | print(COPYRIGHT) |
| 144 | argv = parse_argv() |
| 145 | app = Application(argv) |
Piotr Krysik | ba6fd0e | 2018-09-06 19:57:57 +0200 | [diff] [blame] | 146 | app.run() |