From 89fc14ba44723cfbd88c2499ec8ab96ad993c5c4 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 16 Jun 2017 21:00:29 +0700 Subject: Implement transceiver interface This change introduces a new block 'TRX Interface', which is aimed to provide an interface for external applications, such as Osmocom MS side stack implementation - OsmocomBB. Currently one allows to exchange raw GSM bursts between GR-GSM and other applications. Moreover, there is a new 'trx.py' application, which implements a simple follow graph, where all demodulated bursts are being sent to external application via UDP link provided by 'TRX Interface'. OsmoTRX (Osmocom's fork of OpenBTS transceiver) like control interface is used to initialize, configure, start and stop the application. Messages on this interface are human readable ASCII strings, which contain a command and some related parameters. --- apps/trx/ctrl_if.py | 157 ++++++++++++++++++++++++ apps/trx/radio_if.py | 184 +++++++++++++++++++++++++++++ apps/trx/trx.py | 150 +++++++++++++++++++++++ grc/CMakeLists.txt | 1 + grc/trx_interface/CMakeLists.txt | 22 ++++ grc/trx_interface/gsm_trx.xml | 68 +++++++++++ include/grgsm/CMakeLists.txt | 1 + include/grgsm/trx_interface/CMakeLists.txt | 25 ++++ include/grgsm/trx_interface/trx.h | 59 +++++++++ lib/CMakeLists.txt | 2 + lib/trx_interface/trx_impl.cc | 154 ++++++++++++++++++++++++ lib/trx_interface/trx_impl.h | 54 +++++++++ lib/trx_interface/udp_socket.cc | 117 ++++++++++++++++++ lib/trx_interface/udp_socket.h | 65 ++++++++++ swig/grgsm_swig.i | 3 + 15 files changed, 1062 insertions(+) create mode 100644 apps/trx/ctrl_if.py create mode 100644 apps/trx/radio_if.py create mode 100755 apps/trx/trx.py create mode 100644 grc/trx_interface/CMakeLists.txt create mode 100644 grc/trx_interface/gsm_trx.xml create mode 100644 include/grgsm/trx_interface/CMakeLists.txt create mode 100644 include/grgsm/trx_interface/trx.h create mode 100644 lib/trx_interface/trx_impl.cc create mode 100644 lib/trx_interface/trx_impl.h create mode 100644 lib/trx_interface/udp_socket.cc create mode 100644 lib/trx_interface/udp_socket.h diff --git a/apps/trx/ctrl_if.py b/apps/trx/ctrl_if.py new file mode 100644 index 0000000..43fc185 --- /dev/null +++ b/apps/trx/ctrl_if.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# GR-GSM based transceiver +# Transceiver UDP interface +# +# (C) 2016-2017 by Vadim Yanitskiy +# +# All Rights Reserved +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import socket +import select + +class UDPServer: + def __init__(self, remote_addr, remote_port, bind_port): + self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self.sock.bind(('0.0.0.0', bind_port)) + self.sock.setblocking(0) + + # Save remote info + self.remote_addr = remote_addr + self.remote_port = remote_port + + def loop(self): + r_event, w_event, x_event = select.select([self.sock], [], []) + + # Check for incoming data + if self.sock in r_event: + data, addr = self.sock.recvfrom(128) + self.handle_rx(data) + + def shutdown(self): + self.sock.close(); + + def send(self, data): + self.sock.sendto(data, (self.remote_addr, self.remote_port)) + + def handle_rx(self, data): + raise NotImplementedError + +class CTRLInterface(UDPServer): + def __init__(self, remote_addr, remote_port, bind_port, radio_if): + print("[i] Init TRX CTRL interface") + UDPServer.__init__(self, remote_addr, remote_port, bind_port) + self.tb = radio_if + + def shutdown(self): + print("[i] Shutdown TRX CTRL interface") + UDPServer.shutdown(self) + + def handle_rx(self, data): + if self.verify_req(data): + request = self.prepare_req(data) + self.parse_cmd(request) + else: + print("[!] Wrong data on CTRL interface") + + def verify_req(self, data): + # Verify command signature + return data.startswith("CMD") + + def prepare_req(self, data): + # Strip signature, paddings and \0 + request = data[4:].strip().strip("\0") + # Split into a command and arguments + request = request.split(" ") + # Now we have something like ["TXTUNE", "941600"] + return request + + def verify_cmd(self, request, cmd, argc): + # Check if requested command matches + if request[0] != cmd: + return False + + # And has enough arguments + if len(request) - 1 != argc: + return False + + # Check if all arguments are numeric + for v in request[1:]: + if not v.isdigit(): + return False + + return True + + def parse_cmd(self, request): + response_code = "0" + + # Power control + if self.verify_cmd(request, "POWERON", 0): + print("[i] Recv POWERON cmd") + if not self.tb.trx_started: + if self.tb.check_available(): + print("[i] Starting transceiver...") + self.tb.trx_started = True + self.tb.start() + else: + print("[!] Transceiver isn't ready to start") + response_code = "-1" + else: + print("[!] Transceiver already started!") + response_code = "-1" + elif self.verify_cmd(request, "POWEROFF", 0): + print("[i] Recv POWEROFF cmd") + print("[i] Stopping transceiver...") + self.tb.trx_started = False + # TODO: flush all buffers between blocks + self.tb.stop() + elif self.verify_cmd(request, "SETRXGAIN", 1): + print("[i] Recv SETRXGAIN cmd") + # TODO: check gain value + gain = int(request[1]) + self.tb.set_gain(gain) + + # Tuning Control + elif self.verify_cmd(request, "RXTUNE", 1): + print("[i] Recv RXTUNE cmd") + # TODO: check freq range + freq = int(request[1]) * 1000 + self.tb.set_fc(freq) + elif self.verify_cmd(request, "TXTUNE", 1): + print("[i] Recv TXTUNE cmd") + # TODO: is not implemented yet + + # Misc + elif self.verify_cmd(request, "ECHO", 0): + print("[i] Recv ECHO cmd") + + # Wrong / unknown command + else: + print("[!] Wrong request on CTRL interface") + response_code = "-1" + + # Anyway, we need to respond + self.send_response(request, response_code) + + def send_response(self, request, response_code): + # Include status code, for example ["TXTUNE", "0", "941600"] + request.insert(1, response_code) + # Add the response signature, and join back to string + response = "RSP " + " ".join(request) + "\0" + # Now we have something like "RSP TXTUNE 0 941600" + self.send(response) diff --git a/apps/trx/radio_if.py b/apps/trx/radio_if.py new file mode 100644 index 0000000..41eb3e8 --- /dev/null +++ b/apps/trx/radio_if.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# GR-GSM based transceiver +# Follow graph implementation +# +# (C) 2016-2017 by Vadim Yanitskiy +# +# All Rights Reserved +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import pmt +import time +import grgsm +import osmosdr + +from math import pi + +from gnuradio.eng_option import eng_option +from gnuradio import eng_notation +from gnuradio.filter import firdes +from gnuradio import blocks +from gnuradio import gr + +class RadioInterface(gr.top_block): + # PHY specific variables + samp_rate = 2000000 + shiftoff = 400e3 + subdev_spec = "" # TODO: use it + device_args = "" + fc = 941.6e6 # TODO: set ARFCN to 0? + gain = 30 + ppm = 0 + + # Application state flags + trx_started = False + fc_set = False + + def __init__(self, phy_args, phy_subdev_spec, + phy_sample_rate, phy_gain, phy_ppm, + trx_remote_addr, trx_base_port): + print("[i] Init Radio interface") + + # TRX block specific variables + self.trx_remote_addr = trx_remote_addr + self.trx_base_port = trx_base_port + + # PHY specific variables + self.subdev_spec = phy_subdev_spec + self.samp_rate = phy_sample_rate + self.device_args = phy_args + self.gain = phy_gain + self.ppm = phy_ppm + + gr.top_block.__init__(self, "GR-GSM TRX") + shift_fc = self.fc - self.shiftoff + + ################################################## + # PHY Definition + ################################################## + self.phy = osmosdr.source( + args = "numchan=%d %s" % (1, self.device_args)) + + self.phy.set_bandwidth(250e3 + abs(self.shiftoff), 0) + self.phy.set_center_freq(shift_fc, 0) + self.phy.set_sample_rate(self.samp_rate) + self.phy.set_freq_corr(self.ppm, 0) + self.phy.set_iq_balance_mode(2, 0) + self.phy.set_dc_offset_mode(2, 0) + self.phy.set_gain_mode(False, 0) + self.phy.set_gain(self.gain, 0) + self.phy.set_if_gain(20, 0) + self.phy.set_bb_gain(20, 0) + self.phy.set_antenna("", 0) + + ################################################## + # GR-GSM Magic + ################################################## + self.blocks_rotator = blocks.rotator_cc( + -2 * pi * self.shiftoff / self.samp_rate) + + self.gsm_input = grgsm.gsm_input( + ppm = self.ppm, osr = 4, fc = self.fc, + samp_rate_in = self.samp_rate) + + self.gsm_receiver = grgsm.receiver(4, ([0]), ([])) + + self.gsm_clck_ctrl = grgsm.clock_offset_control( + shift_fc, self.samp_rate, osr = 4) + + # TODO: implement configurable TS filter + self.gsm_ts_filter = grgsm.burst_timeslot_filter(0) + + self.gsm_trx_if = grgsm.trx(self.trx_remote_addr, + str(self.trx_base_port)) + + ################################################## + # Connections + ################################################## + self.connect((self.phy, 0), (self.blocks_rotator, 0)) + self.connect((self.blocks_rotator, 0), (self.gsm_input, 0)) + self.connect((self.gsm_input, 0), (self.gsm_receiver, 0)) + + self.msg_connect((self.gsm_receiver, 'measurements'), + (self.gsm_clck_ctrl, 'measurements')) + + self.msg_connect((self.gsm_clck_ctrl, 'ctrl'), + (self.gsm_input, 'ctrl_in')) + + self.msg_connect((self.gsm_receiver, 'C0'), + (self.gsm_ts_filter, 'in')) + + self.msg_connect((self.gsm_ts_filter, 'out'), + (self.gsm_trx_if, 'bursts')) + + def check_available(self): + return self.fc_set + + def shutdown(self): + print("[i] Shutdown Radio interface") + self.stop() + self.wait() + + def get_args(self): + return self.args + + def set_args(self, args): + self.args = args + + def get_fc(self): + return self.fc + + def set_fc(self, fc): + self.phy.set_center_freq(fc - self.shiftoff, 0) + self.gsm_input.set_fc(fc) + self.fc_set = True + self.fc = fc + + def get_gain(self): + return self.gain + + def set_gain(self, gain): + self.phy.set_gain(gain, 0) + self.gain = gain + + def get_ppm(self): + return self.ppm + + def set_ppm(self, ppm): + self.rtlsdr_source_0.set_freq_corr(ppm, 0) + self.ppm = ppm + + def get_samp_rate(self): + return self.samp_rate + + def set_samp_rate(self, samp_rate): + self.blocks_rotator.set_phase_inc( + -2 * pi * self.shiftoff / samp_rate) + self.gsm_input.set_samp_rate_in(samp_rate) + self.phy.set_sample_rate(samp_rate) + self.samp_rate = samp_rate + + def get_shiftoff(self): + return self.shiftoff + + def set_shiftoff(self, shiftoff): + self.blocks_rotator.set_phase_inc( + -2 * pi * shiftoff / self.samp_rate) + self.phy.set_bandwidth(250e3 + abs(shiftoff), 0) + self.phy.set_center_freq(self.fc - shiftoff, 0) + self.shiftoff = shiftoff diff --git a/apps/trx/trx.py b/apps/trx/trx.py new file mode 100755 index 0000000..25f76cf --- /dev/null +++ b/apps/trx/trx.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# GR-GSM based transceiver +# +# (C) 2016-2017 by Vadim Yanitskiy +# +# All Rights Reserved +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import signal +import getopt +import sys + +from ctrl_if import CTRLInterface +from radio_if import RadioInterface + +COPYRIGHT = \ + "Copyright (C) 2016-2017 by Vadim Yanitskiy \n" \ + "License GPLv2+: GNU GPL version 2 or later " \ + "\n" \ + "This is free software: you are free to change and redistribute it.\n" \ + "There is NO WARRANTY, to the extent permitted by law.\n" + +class Application: + # Application variables + remote_addr = "127.0.0.1" + base_port = 5700 + + # PHY specific + phy_sample_rate = 2000000 + phy_subdev_spec = False + phy_gain = 30 + phy_args = "" + phy_ppm = 0 + + def __init__(self): + self.print_copyright() + self.parse_argv() + + # Set up signal handlers + signal.signal(signal.SIGINT, self.sig_handler) + + def run(self): + # Init Radio interface + self.radio = RadioInterface(self.phy_args, self.phy_subdev_spec, + self.phy_sample_rate, self.phy_gain, self.phy_ppm, + self.remote_addr, self.base_port) + + # Init TRX CTRL interface + self.server = CTRLInterface(self.remote_addr, + self.base_port + 101, self.base_port + 1, self.radio) + + print("[i] Init complete") + + # Enter main loop + while True: + self.server.loop() + + def shutdown(self): + print("[i] Shutting down...") + self.server.shutdown() + self.radio.shutdown() + + def print_copyright(self): + print(COPYRIGHT) + + def print_help(self): + s = " Usage: " + sys.argv[0] + " [options]\n\n" \ + " Some help...\n" \ + " -h --help this text\n\n" + + # TRX specific + s += " TRX interface specific\n" \ + " -s --remote-addr Set remote address (default 127.0.0.1)\n" \ + " -p --base-port Set base port number (default 5700)\n\n" + + # PHY specific + s += " Radio interface specific\n" \ + " -a --device-args Set device arguments\n" \ + " -s --sample-rate Set PHY sample rate (default 2000000)\n" \ + " -S --subdev-spec Set PHY sub-device specification\n" \ + " -g --gain Set PHY gain (default 30)\n" \ + " --ppm Set PHY frequency correction (default 0)\n" + + print(s) + + def parse_argv(self): + try: + opts, args = getopt.getopt(sys.argv[1:], + "a:p:i:s:S:g:h", + ["help", "remote-addr=", "base-port=", "device-args=", + "gain=", "subdev-spec=", "sample-rate=", "ppm="]) + except getopt.GetoptError as err: + # Print(help and exit) + self.print_help() + print("[!] " + str(err)) + sys.exit(2) + + for o, v in opts: + if o in ("-h", "--help"): + self.print_help() + sys.exit(2) + + # TRX specific + elif o in ("-i", "--remote-addr"): + self.remote_addr = v + elif o in ("-p", "--base-port"): + if int(v) >= 0 and int(v) <= 65535: + self.base_port = int(v) + else: + print("[!] The port number should be in range [0-65536]") + sys.exit(2) + + # PHY specific + elif o in ("-a", "--device-args"): + self.phy_args = v + elif o in ("-g", "--gain"): + self.phy_gain = int(v) + elif o in ("-S", "--subdev-spec"): + self.phy_subdev_spec = v + elif o in ("-s", "--sample-rate"): + self.phy_sample_rate = int(v) + elif o in ("--ppm"): + self.phy_ppm = int(v) + + def sig_handler(self, signum, frame): + print("Signal %d received" % signum) + if signum is signal.SIGINT: + self.shutdown() + sys.exit(0) + +def main(): + Application().run() + +if __name__ == '__main__': + main() diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 2b94539..045d6a5 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -23,6 +23,7 @@ add_subdirectory(demapping) add_subdirectory(receiver) add_subdirectory(flow_control) add_subdirectory(misc_utils) +add_subdirectory(trx_interface) install(FILES gsm_block_tree.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/trx_interface/CMakeLists.txt b/grc/trx_interface/CMakeLists.txt new file mode 100644 index 0000000..752b7a7 --- /dev/null +++ b/grc/trx_interface/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +install(FILES + gsm_trx.xml DESTINATION share/gnuradio/grc/blocks +) diff --git a/grc/trx_interface/gsm_trx.xml b/grc/trx_interface/gsm_trx.xml new file mode 100644 index 0000000..cf882ef --- /dev/null +++ b/grc/trx_interface/gsm_trx.xml @@ -0,0 +1,68 @@ + + + TRX interface + grgsm_trx_interface + import grgsm + grgsm.trx($remote_addr, $base_port) + + + base_port + base_port + 5700 + string + + + + remote_addr + remote_addr + 127.0.0.1 + string + + + + bursts + message + + + + OsmoTRX like UDP interface for external applications. + + There are three UDP sockets: CLCK, CTRL and DATA. + Give a base port B (5700 by default), the SCH clock + interface is at port P=B. The TRX-side control interface + is on port P=B+100+1 and the data interface is on an odd + numbered port P=B+100+2. + + Indications on the SCH Clock Interface (CLCK) + The SCH clock interface is output only (from the radio). + CLOCK gives the current value of the BTS clock to + be used by external applications. The indications are + sent whenever a transmission packet arrives that is too + late or too early. + + Commands on Control Interface (CTRL) + The control interface uses a command-response protocol. + Commands are NULL-terminated ASCII strings. Each command + has a corresponding response. This interface isn't handled + by this particular block, and should be implemented outside. + + Messages on the Data Interface + Messages on the data interface carry one radio burst per + UDP message. + + Received Data Burst: + 1 byte timeslot index + 4 bytes GSM frame number, big endian + 1 byte RSSI in -dBm + 2 bytes correlator timing offset in 1/256 symbol steps, + 2's-comp, big endian + 148 bytes soft symbol estimates, 0 -> definite "0", + 255 -> definite "1" + + Transmit Data Burst: + 1 byte timeslot index + 4 bytes GSM frame number, big endian + 1 byte transmit level wrt ARFCN max, -dB (attenuation) + 148 bytes output symbol values, 0 & 1 + + diff --git a/include/grgsm/CMakeLists.txt b/include/grgsm/CMakeLists.txt index dc9b191..beca954 100644 --- a/include/grgsm/CMakeLists.txt +++ b/include/grgsm/CMakeLists.txt @@ -33,3 +33,4 @@ add_subdirectory(receiver) add_subdirectory(misc_utils) add_subdirectory(qa_utils) add_subdirectory(flow_control) +add_subdirectory(trx_interface) diff --git a/include/grgsm/trx_interface/CMakeLists.txt b/include/grgsm/trx_interface/CMakeLists.txt new file mode 100644 index 0000000..8d35ef7 --- /dev/null +++ b/include/grgsm/trx_interface/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# Install public header files +######################################################################## +install(FILES + trx.h DESTINATION include/grgsm/trx_interface +) diff --git a/include/grgsm/trx_interface/trx.h b/include/grgsm/trx_interface/trx.h new file mode 100644 index 0000000..7821389 --- /dev/null +++ b/include/grgsm/trx_interface/trx.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* @file + * @author Vadim Yanitskiy + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef INCLUDED_GRGSM_TRX_H +#define INCLUDED_GRGSM_TRX_H + +#include +#include + +namespace gr { + namespace grgsm { + + /*! + * \brief <+description of block+> + * \ingroup grgsm + * + */ + class GRGSM_API trx : virtual public gr::block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of grgsm::trx. + * + * To avoid accidental use of raw pointers, grgsm::trx's + * constructor is in a private implementation + * class. grgsm::trx::make is the public interface for + * creating new instances. + */ + static sptr make( + const std::string &remote_addr, + const std::string &base_port); + }; + + } // namespace grgsm +} // namespace gr + +#endif /* INCLUDED_GRGSM_TRX_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 680c41f..5d3f461 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -69,6 +69,8 @@ list(APPEND grgsm_sources qa_utils/message_source_impl.cc qa_utils/message_sink_impl.cc decryption/decryption_impl.cc + trx_interface/udp_socket.cc + trx_interface/trx_impl.cc ) diff --git a/lib/trx_interface/trx_impl.cc b/lib/trx_interface/trx_impl.cc new file mode 100644 index 0000000..9b9c484 --- /dev/null +++ b/lib/trx_interface/trx_impl.cc @@ -0,0 +1,154 @@ +/* -*- c++ -*- */ +/* @file + * @author Vadim Yanitskiy + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "udp_socket.h" +#include "trx_impl.h" + +namespace gr { + namespace grgsm { + + trx::sptr + trx::make( + const std::string &remote_addr, + const std::string &base_port) + { + int base_port_int = boost::lexical_cast (base_port); + + return gnuradio::get_initial_sptr + (new trx_impl(remote_addr, base_port_int)); + } + + /* + * The private constructor + */ + trx_impl::trx_impl(const std::string &remote_addr, int base_port) + : gr::block("trx", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)) + { + message_port_register_in(pmt::mp("bursts")); + set_msg_handler(pmt::mp("bursts"), + boost::bind(&trx_impl::handle_dl_burst, this, _1)); + + // Prepare port numbers + std::string clck_src_port = boost::lexical_cast (base_port + 0); + std::string clck_dst_port = boost::lexical_cast (base_port + 100); + std::string data_src_port = boost::lexical_cast (base_port + 2); + std::string data_dst_port = boost::lexical_cast (base_port + 102); + + // Init DATA interface + d_data_sock = new udp_socket(remote_addr, data_src_port, data_dst_port); + d_clck_sock = new udp_socket(remote_addr, clck_src_port, clck_dst_port); + } + + /* + * Our virtual destructor. + */ + trx_impl::~trx_impl() + { + // Release all UDP sockets and free memory + delete d_data_sock; + delete d_clck_sock; + } + + /* + * Create an UDP payload with clock indication + */ + void + trx_impl::clck_ind_send(uint32_t frame_nr) + { + char buf[20]; + size_t n; + + n = snprintf(buf, 20, "IND CLOCK %u", frame_nr); + d_clck_sock->udp_send((uint8_t *) buf, n + 1); + } + + /* + * Create an UDP payload with burst bits + * and some channel data. + */ + void + trx_impl::burst_pack(pmt::pmt_t msg, uint8_t *buf) + { + pmt::pmt_t header_plus_burst = pmt::cdr(msg); + + // Extract GSMTAP header from message + gsmtap_hdr *header = (gsmtap_hdr *) + pmt::blob_data(header_plus_burst); + + // Pack timeslot index + buf[0] = header->timeslot; + + // Extract frame number + uint32_t frame_nr = be32toh(header->frame_number); + + // HACK: send clock indications every 51-th frame + if (frame_nr % 51 == 0) + clck_ind_send(frame_nr); + + // Pack frame number + buf[1] = (frame_nr >> 24) & 0xff; + buf[2] = (frame_nr >> 16) & 0xff; + buf[3] = (frame_nr >> 8) & 0xff; + buf[4] = (frame_nr >> 0) & 0xff; + + // Pack RSSI (-dBm) + buf[5] = -(uint8_t) header->signal_dbm; + + // Pack correlator timing offset (TOA) + // FIXME: where to find this value? + buf[6] = 0; + buf[7] = 0; + + // Extract bits {0..1} from message + // Despite GR-GSM uses int8_t, they are not real sbits {-127..127} + uint8_t *burst = (uint8_t *) + (pmt::blob_data(header_plus_burst)) + sizeof(gsmtap_hdr); + + // Convert to transceiver interface specific bits {255..0} + for (int i = 0; i < 148; i++) + buf[8 + i] = burst[i] ? 255 : 0; + } + + void + trx_impl::handle_dl_burst(pmt::pmt_t msg) + { + // 8 bytes of header + 148 bytes of burst + uint8_t buf[156]; + + // Compose a new UDP payload with burst + burst_pack(msg, buf); + + // Send a burst + d_data_sock->udp_send(buf, 156); + } + + } /* namespace grgsm */ +} /* namespace gr */ diff --git a/lib/trx_interface/trx_impl.h b/lib/trx_interface/trx_impl.h new file mode 100644 index 0000000..41a4788 --- /dev/null +++ b/lib/trx_interface/trx_impl.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* @file + * @author Vadim Yanitskiy + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef INCLUDED_GRGSM_TRX_IMPL_H +#define INCLUDED_GRGSM_TRX_IMPL_H + +#include + +#include +#include + +namespace gr { + namespace grgsm { + + class trx_impl : public trx + { + private: + udp_socket *d_data_sock; + udp_socket *d_clck_sock; + + void clck_ind_send(uint32_t frame_nr); + void burst_pack(pmt::pmt_t msg, uint8_t *buf); + + public: + trx_impl(const std::string &remote_addr, int base_port); + ~trx_impl(); + + void handle_dl_burst(pmt::pmt_t msg); + }; + + } // namespace grgsm +} // namespace gr + +#endif /* INCLUDED_GRGSM_TRX_IMPL_H */ + diff --git a/lib/trx_interface/udp_socket.cc b/lib/trx_interface/udp_socket.cc new file mode 100644 index 0000000..4bbf206 --- /dev/null +++ b/lib/trx_interface/udp_socket.cc @@ -0,0 +1,117 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include +#include "udp_socket.h" + +using boost::asio::ip::udp; + +namespace gr { + namespace grgsm { + + udp_socket::udp_socket( + const std::string &remote_addr, + const std::string &src_port, + const std::string &dst_port) + { + // Resolve remote host address + udp::resolver resolver(d_io_service); + + udp::resolver::query rx_query( + udp::v4(), remote_addr, src_port, + boost::asio::ip::resolver_query_base::passive); + udp::resolver::query tx_query( + udp::v4(), remote_addr, dst_port, + boost::asio::ip::resolver_query_base::passive); + + d_udp_endpoint_rx = *resolver.resolve(rx_query); + d_udp_endpoint_tx = *resolver.resolve(tx_query); + + // Create a socket + d_udp_socket.reset(new udp::socket(d_io_service, d_udp_endpoint_rx)); + + // Setup read handler + d_udp_socket->async_receive_from( + boost::asio::buffer(d_rxbuf), d_udp_endpoint_rx, + boost::bind(&udp_socket::handle_udp_read, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + + // Start server + d_thread = gr::thread::thread( + boost::bind(&udp_socket::run_io_service, this)); + } + + udp_socket::~udp_socket() + { + // Stop server + d_io_service.stop(); + d_thread.interrupt(); + d_thread.join(); + } + + void + udp_socket::run_io_service(void) + { + d_io_service.run(); + } + + void + udp_socket::udp_send(uint8_t *data, size_t len) + { + d_udp_socket->send_to( + boost::asio::buffer(data, len), + d_udp_endpoint_tx); + } + + void + udp_socket::handle_udp_read( + const boost::system::error_code& error, + size_t bytes_transferred) + { + if (error) + return; + + pmt::pmt_t vector = pmt::init_u8vector(bytes_transferred, + (const uint8_t *) &d_rxbuf[0]); + pmt::pmt_t pdu = pmt::cons(pmt::PMT_NIL, vector); + + // TODO: call handler here + + d_udp_socket->async_receive_from( + boost::asio::buffer(d_rxbuf), d_udp_endpoint_rx, + boost::bind(&udp_socket::handle_udp_read, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + + } /* namespace blocks */ +}/* namespace gr */ diff --git a/lib/trx_interface/udp_socket.h b/lib/trx_interface/udp_socket.h new file mode 100644 index 0000000..2f424c9 --- /dev/null +++ b/lib/trx_interface/udp_socket.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GRGSM_TRX_UDP_SOCKET_H +#define INCLUDED_GRGSM_TRX_UDP_SOCKET_H + +#include + +#include +#include +#include + +namespace gr { + namespace grgsm { + + class udp_socket + { + private: + boost::asio::io_service d_io_service; + std::vector d_rxbuf; + gr::thread::thread d_thread; + bool d_started; + bool d_finished; + + boost::asio::ip::udp::endpoint d_udp_endpoint_rx; + boost::asio::ip::udp::endpoint d_udp_endpoint_tx; + boost::shared_ptr d_udp_socket; + + void handle_udp_read(const boost::system::error_code& error, + size_t bytes_transferred); + void run_io_service(void); + + public: + udp_socket( + const std::string &remote_addr, + const std::string &src_port, + const std::string &dst_port); + ~udp_socket(); + + void udp_send(uint8_t *data, size_t len); + }; + + } /* namespace blocks */ +} /* namespace gr */ + +#endif /* INCLUDED_GRGSM_TRX_UDP_SOCKET_H */ diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i index 68911ae..6013cb1 100644 --- a/swig/grgsm_swig.i +++ b/swig/grgsm_swig.i @@ -41,6 +41,7 @@ #include "grgsm/misc_utils/message_file_source.h" #include "grgsm/misc_utils/msg_to_tag.h" #include "grgsm/misc_utils/controlled_fractional_resampler_cc.h" +#include "grgsm/trx_interface/trx.h" %} %include "grgsm/receiver/receiver.h" @@ -117,3 +118,5 @@ GR_SWIG_BLOCK_MAGIC2(gsm, burst_source); GR_SWIG_BLOCK_MAGIC2(gsm, message_source); %include "grgsm/qa_utils/message_sink.h" GR_SWIG_BLOCK_MAGIC2(gsm, message_sink); +%include "grgsm/trx_interface/trx.h" +GR_SWIG_BLOCK_MAGIC2(grgsm, trx); -- cgit v1.2.3 From c36c49889c0c72a68c8845f0a8371137862f229e Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sun, 16 Jul 2017 23:16:54 +0700 Subject: trx_interface: append two unused bytes at the end of messages Despite the last two bytes at the end of messages on DATA interface are not used, let's keep the protocol compatibility and fill them by 0x00. --- lib/trx_interface/trx_impl.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/trx_interface/trx_impl.cc b/lib/trx_interface/trx_impl.cc index 9b9c484..abcd45e 100644 --- a/lib/trx_interface/trx_impl.cc +++ b/lib/trx_interface/trx_impl.cc @@ -135,19 +135,25 @@ namespace gr { // Convert to transceiver interface specific bits {255..0} for (int i = 0; i < 148; i++) buf[8 + i] = burst[i] ? 255 : 0; + + // Fill two unused bytes + buf[156] = 0x00; + buf[157] = 0x00; } void trx_impl::handle_dl_burst(pmt::pmt_t msg) { // 8 bytes of header + 148 bytes of burst - uint8_t buf[156]; + // + two unused, but required bytes + // otherwise bursts would be rejected + uint8_t buf[158]; // Compose a new UDP payload with burst burst_pack(msg, buf); // Send a burst - d_data_sock->udp_send(buf, 156); + d_data_sock->udp_send(buf, 158); } } /* namespace grgsm */ -- cgit v1.2.3 From 99be625855320ff8ddebd4c30601a45325d22562 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sun, 16 Jul 2017 23:26:34 +0700 Subject: trx_interface: follow common block naming style --- grc/trx_interface/gsm_trx.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grc/trx_interface/gsm_trx.xml b/grc/trx_interface/gsm_trx.xml index cf882ef..71c88ef 100644 --- a/grc/trx_interface/gsm_trx.xml +++ b/grc/trx_interface/gsm_trx.xml @@ -1,6 +1,6 @@ - TRX interface + TRX Interface grgsm_trx_interface import grgsm grgsm.trx($remote_addr, $base_port) -- cgit v1.2.3 From 948f70463f45241bf931e7dbb6107c478d58ca54 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sun, 16 Jul 2017 23:29:59 +0700 Subject: trx_interface: follow GR-GSM app naming style --- apps/trx/grgsm_trx.py | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++ apps/trx/trx.py | 150 -------------------------------------------------- 2 files changed, 150 insertions(+), 150 deletions(-) create mode 100755 apps/trx/grgsm_trx.py delete mode 100755 apps/trx/trx.py diff --git a/apps/trx/grgsm_trx.py b/apps/trx/grgsm_trx.py new file mode 100755 index 0000000..25f76cf --- /dev/null +++ b/apps/trx/grgsm_trx.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# GR-GSM based transceiver +# +# (C) 2016-2017 by Vadim Yanitskiy +# +# All Rights Reserved +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import signal +import getopt +import sys + +from ctrl_if import CTRLInterface +from radio_if import RadioInterface + +COPYRIGHT = \ + "Copyright (C) 2016-2017 by Vadim Yanitskiy \n" \ + "License GPLv2+: GNU GPL version 2 or later " \ + "\n" \ + "This is free software: you are free to change and redistribute it.\n" \ + "There is NO WARRANTY, to the extent permitted by law.\n" + +class Application: + # Application variables + remote_addr = "127.0.0.1" + base_port = 5700 + + # PHY specific + phy_sample_rate = 2000000 + phy_subdev_spec = False + phy_gain = 30 + phy_args = "" + phy_ppm = 0 + + def __init__(self): + self.print_copyright() + self.parse_argv() + + # Set up signal handlers + signal.signal(signal.SIGINT, self.sig_handler) + + def run(self): + # Init Radio interface + self.radio = RadioInterface(self.phy_args, self.phy_subdev_spec, + self.phy_sample_rate, self.phy_gain, self.phy_ppm, + self.remote_addr, self.base_port) + + # Init TRX CTRL interface + self.server = CTRLInterface(self.remote_addr, + self.base_port + 101, self.base_port + 1, self.radio) + + print("[i] Init complete") + + # Enter main loop + while True: + self.server.loop() + + def shutdown(self): + print("[i] Shutting down...") + self.server.shutdown() + self.radio.shutdown() + + def print_copyright(self): + print(COPYRIGHT) + + def print_help(self): + s = " Usage: " + sys.argv[0] + " [options]\n\n" \ + " Some help...\n" \ + " -h --help this text\n\n" + + # TRX specific + s += " TRX interface specific\n" \ + " -s --remote-addr Set remote address (default 127.0.0.1)\n" \ + " -p --base-port Set base port number (default 5700)\n\n" + + # PHY specific + s += " Radio interface specific\n" \ + " -a --device-args Set device arguments\n" \ + " -s --sample-rate Set PHY sample rate (default 2000000)\n" \ + " -S --subdev-spec Set PHY sub-device specification\n" \ + " -g --gain Set PHY gain (default 30)\n" \ + " --ppm Set PHY frequency correction (default 0)\n" + + print(s) + + def parse_argv(self): + try: + opts, args = getopt.getopt(sys.argv[1:], + "a:p:i:s:S:g:h", + ["help", "remote-addr=", "base-port=", "device-args=", + "gain=", "subdev-spec=", "sample-rate=", "ppm="]) + except getopt.GetoptError as err: + # Print(help and exit) + self.print_help() + print("[!] " + str(err)) + sys.exit(2) + + for o, v in opts: + if o in ("-h", "--help"): + self.print_help() + sys.exit(2) + + # TRX specific + elif o in ("-i", "--remote-addr"): + self.remote_addr = v + elif o in ("-p", "--base-port"): + if int(v) >= 0 and int(v) <= 65535: + self.base_port = int(v) + else: + print("[!] The port number should be in range [0-65536]") + sys.exit(2) + + # PHY specific + elif o in ("-a", "--device-args"): + self.phy_args = v + elif o in ("-g", "--gain"): + self.phy_gain = int(v) + elif o in ("-S", "--subdev-spec"): + self.phy_subdev_spec = v + elif o in ("-s", "--sample-rate"): + self.phy_sample_rate = int(v) + elif o in ("--ppm"): + self.phy_ppm = int(v) + + def sig_handler(self, signum, frame): + print("Signal %d received" % signum) + if signum is signal.SIGINT: + self.shutdown() + sys.exit(0) + +def main(): + Application().run() + +if __name__ == '__main__': + main() diff --git a/apps/trx/trx.py b/apps/trx/trx.py deleted file mode 100755 index 25f76cf..0000000 --- a/apps/trx/trx.py +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf-8 -*- - -# GR-GSM based transceiver -# -# (C) 2016-2017 by Vadim Yanitskiy -# -# All Rights Reserved -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -import signal -import getopt -import sys - -from ctrl_if import CTRLInterface -from radio_if import RadioInterface - -COPYRIGHT = \ - "Copyright (C) 2016-2017 by Vadim Yanitskiy \n" \ - "License GPLv2+: GNU GPL version 2 or later " \ - "\n" \ - "This is free software: you are free to change and redistribute it.\n" \ - "There is NO WARRANTY, to the extent permitted by law.\n" - -class Application: - # Application variables - remote_addr = "127.0.0.1" - base_port = 5700 - - # PHY specific - phy_sample_rate = 2000000 - phy_subdev_spec = False - phy_gain = 30 - phy_args = "" - phy_ppm = 0 - - def __init__(self): - self.print_copyright() - self.parse_argv() - - # Set up signal handlers - signal.signal(signal.SIGINT, self.sig_handler) - - def run(self): - # Init Radio interface - self.radio = RadioInterface(self.phy_args, self.phy_subdev_spec, - self.phy_sample_rate, self.phy_gain, self.phy_ppm, - self.remote_addr, self.base_port) - - # Init TRX CTRL interface - self.server = CTRLInterface(self.remote_addr, - self.base_port + 101, self.base_port + 1, self.radio) - - print("[i] Init complete") - - # Enter main loop - while True: - self.server.loop() - - def shutdown(self): - print("[i] Shutting down...") - self.server.shutdown() - self.radio.shutdown() - - def print_copyright(self): - print(COPYRIGHT) - - def print_help(self): - s = " Usage: " + sys.argv[0] + " [options]\n\n" \ - " Some help...\n" \ - " -h --help this text\n\n" - - # TRX specific - s += " TRX interface specific\n" \ - " -s --remote-addr Set remote address (default 127.0.0.1)\n" \ - " -p --base-port Set base port number (default 5700)\n\n" - - # PHY specific - s += " Radio interface specific\n" \ - " -a --device-args Set device arguments\n" \ - " -s --sample-rate Set PHY sample rate (default 2000000)\n" \ - " -S --subdev-spec Set PHY sub-device specification\n" \ - " -g --gain Set PHY gain (default 30)\n" \ - " --ppm Set PHY frequency correction (default 0)\n" - - print(s) - - def parse_argv(self): - try: - opts, args = getopt.getopt(sys.argv[1:], - "a:p:i:s:S:g:h", - ["help", "remote-addr=", "base-port=", "device-args=", - "gain=", "subdev-spec=", "sample-rate=", "ppm="]) - except getopt.GetoptError as err: - # Print(help and exit) - self.print_help() - print("[!] " + str(err)) - sys.exit(2) - - for o, v in opts: - if o in ("-h", "--help"): - self.print_help() - sys.exit(2) - - # TRX specific - elif o in ("-i", "--remote-addr"): - self.remote_addr = v - elif o in ("-p", "--base-port"): - if int(v) >= 0 and int(v) <= 65535: - self.base_port = int(v) - else: - print("[!] The port number should be in range [0-65536]") - sys.exit(2) - - # PHY specific - elif o in ("-a", "--device-args"): - self.phy_args = v - elif o in ("-g", "--gain"): - self.phy_gain = int(v) - elif o in ("-S", "--subdev-spec"): - self.phy_subdev_spec = v - elif o in ("-s", "--sample-rate"): - self.phy_sample_rate = int(v) - elif o in ("--ppm"): - self.phy_ppm = int(v) - - def sig_handler(self, signum, frame): - print("Signal %d received" % signum) - if signum is signal.SIGINT: - self.shutdown() - sys.exit(0) - -def main(): - Application().run() - -if __name__ == '__main__': - main() -- cgit v1.2.3 From ac3a527c9897c71ae463c6af58829a6232dda2e5 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 19 Jul 2017 03:05:07 +0700 Subject: trx_interface: implement incoming data handler This change implements a receive path for UL bursts, namely the OsmoTRX style header conversation to GSMTAP. --- grc/trx_interface/gsm_trx.xml | 5 +++ lib/trx_interface/trx_impl.cc | 69 +++++++++++++++++++++++++++++++++++++++-- lib/trx_interface/trx_impl.h | 1 + lib/trx_interface/udp_socket.cc | 14 +++++---- lib/trx_interface/udp_socket.h | 6 +++- 5 files changed, 85 insertions(+), 10 deletions(-) diff --git a/grc/trx_interface/gsm_trx.xml b/grc/trx_interface/gsm_trx.xml index 71c88ef..f73b5fd 100644 --- a/grc/trx_interface/gsm_trx.xml +++ b/grc/trx_interface/gsm_trx.xml @@ -24,6 +24,11 @@ message + + bursts + message + + OsmoTRX like UDP interface for external applications. diff --git a/lib/trx_interface/trx_impl.cc b/lib/trx_interface/trx_impl.cc index abcd45e..48ef51a 100644 --- a/lib/trx_interface/trx_impl.cc +++ b/lib/trx_interface/trx_impl.cc @@ -30,6 +30,9 @@ #include "udp_socket.h" #include "trx_impl.h" +#define BURST_SIZE 148 +#define DATA_IF_MTU 160 + namespace gr { namespace grgsm { @@ -53,6 +56,9 @@ namespace gr { gr::io_signature::make(0, 0, 0)) { message_port_register_in(pmt::mp("bursts")); + message_port_register_out(pmt::mp("bursts")); + + // Bind a port handler set_msg_handler(pmt::mp("bursts"), boost::bind(&trx_impl::handle_dl_burst, this, _1)); @@ -62,9 +68,15 @@ namespace gr { std::string data_src_port = boost::lexical_cast (base_port + 2); std::string data_dst_port = boost::lexical_cast (base_port + 102); - // Init DATA interface - d_data_sock = new udp_socket(remote_addr, data_src_port, data_dst_port); - d_clck_sock = new udp_socket(remote_addr, clck_src_port, clck_dst_port); + // Init DATA & CLCK interfaces + d_data_sock = new udp_socket(remote_addr, + data_src_port, data_dst_port, DATA_IF_MTU); + d_clck_sock = new udp_socket(remote_addr, + clck_src_port, clck_dst_port, DATA_IF_MTU); + + // Bind DATA interface handler + d_data_sock->udp_rx_handler = boost::bind( + &trx_impl::handle_ul_burst, this, _1, _2); } /* @@ -156,5 +168,56 @@ namespace gr { d_data_sock->udp_send(buf, 158); } + void + trx_impl::handle_ul_burst(uint8_t *payload, size_t len) + { + // Check length according to the protocol + if (len != 154) + return; + + /* Make sure TS index is correct */ + if (payload[0] >= 8) + return; + + /* Unpack and check frame number */ + uint32_t fn = (payload[1] << 24) + | (payload[2] << 16) + | (payload[3] << 8) + | payload[4]; + + if (fn >= 2715648) + return; + + // Prepare a buffer for GSMTAP header and burst + uint8_t buf[sizeof(gsmtap_hdr) + BURST_SIZE]; + + // Set up pointer to GSMTAP header structure + struct gsmtap_hdr *header = (struct gsmtap_hdr *) buf; + memset(header, 0x00, sizeof(struct gsmtap_hdr)); + + // Fill in basic info + header->version = GSMTAP_VERSION; + header->hdr_len = sizeof(gsmtap_hdr) / 4; + header->type = GSMTAP_TYPE_UM_BURST; + + // Set timeslot index and frame number + header->timeslot = payload[0]; + header->frame_number = htobe32(fn); + + // HACK: use GSMTAP_BURST_NORMAL for now + // FIXME: We will need to distinguish between RACN and NORMAL + header->sub_type = GSMTAP_BURST_NORMAL; + + // Copy burst bits (0 & 1) for source message + memcpy(buf + sizeof(gsmtap_hdr), payload + 6, BURST_SIZE); + + // Create a pmt blob + pmt::pmt_t blob = pmt::make_blob(buf, sizeof(gsmtap_hdr) + BURST_SIZE); + pmt::pmt_t msg = pmt::cons(pmt::PMT_NIL, blob); + + /* Send a message to the output */ + message_port_pub(pmt::mp("bursts"), msg); + } + } /* namespace grgsm */ } /* namespace gr */ diff --git a/lib/trx_interface/trx_impl.h b/lib/trx_interface/trx_impl.h index 41a4788..29545b1 100644 --- a/lib/trx_interface/trx_impl.h +++ b/lib/trx_interface/trx_impl.h @@ -45,6 +45,7 @@ namespace gr { ~trx_impl(); void handle_dl_burst(pmt::pmt_t msg); + void handle_ul_burst(uint8_t *payload, size_t len); }; } // namespace grgsm diff --git a/lib/trx_interface/udp_socket.cc b/lib/trx_interface/udp_socket.cc index 4bbf206..be4bb66 100644 --- a/lib/trx_interface/udp_socket.cc +++ b/lib/trx_interface/udp_socket.cc @@ -40,8 +40,12 @@ namespace gr { udp_socket::udp_socket( const std::string &remote_addr, const std::string &src_port, - const std::string &dst_port) + const std::string &dst_port, + size_t mtu) { + // Resize receive buffer according to MTU value + d_rxbuf.resize(mtu); + // Resolve remote host address udp::resolver resolver(d_io_service); @@ -100,11 +104,9 @@ namespace gr { if (error) return; - pmt::pmt_t vector = pmt::init_u8vector(bytes_transferred, - (const uint8_t *) &d_rxbuf[0]); - pmt::pmt_t pdu = pmt::cons(pmt::PMT_NIL, vector); - - // TODO: call handler here + // Call incoming data handler + if (udp_rx_handler != NULL) + udp_rx_handler((uint8_t *) &d_rxbuf[0], bytes_transferred); d_udp_socket->async_receive_from( boost::asio::buffer(d_rxbuf), d_udp_endpoint_rx, diff --git a/lib/trx_interface/udp_socket.h b/lib/trx_interface/udp_socket.h index 2f424c9..5bcc42b 100644 --- a/lib/trx_interface/udp_socket.h +++ b/lib/trx_interface/udp_socket.h @@ -25,8 +25,10 @@ #include +#include #include #include +#include #include namespace gr { @@ -53,10 +55,12 @@ namespace gr { udp_socket( const std::string &remote_addr, const std::string &src_port, - const std::string &dst_port); + const std::string &dst_port, + size_t mtu); ~udp_socket(); void udp_send(uint8_t *data, size_t len); + boost::function udp_rx_handler; }; } /* namespace blocks */ -- cgit v1.2.3 From 780816d12a88780a41c0d6c74b4f7f2a6c3497eb Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 19 Jul 2017 03:06:17 +0700 Subject: trx_interface: make both source and sink ports optional --- grc/trx_interface/gsm_trx.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/grc/trx_interface/gsm_trx.xml b/grc/trx_interface/gsm_trx.xml index f73b5fd..cbe268c 100644 --- a/grc/trx_interface/gsm_trx.xml +++ b/grc/trx_interface/gsm_trx.xml @@ -22,11 +22,13 @@ bursts message + 1 bursts message + 1 -- cgit v1.2.3 From 1d6b628c5a3760e28d92546de7b04e27f63e9b8d Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 19 Jul 2017 14:23:21 +0700 Subject: trx_interface: set proper burst type in GSMTAP header If received burst is a RACH burst, one should contain the RACH synchronization sequence (GSM 05.02 Chapter 5.2.7) and long guard period filled by 0x00. --- lib/trx_interface/trx_impl.cc | 34 +++++++++++++++++++++++++++++++--- lib/trx_interface/trx_impl.h | 1 + 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/lib/trx_interface/trx_impl.cc b/lib/trx_interface/trx_impl.cc index 48ef51a..8847278 100644 --- a/lib/trx_interface/trx_impl.cc +++ b/lib/trx_interface/trx_impl.cc @@ -33,6 +33,16 @@ #define BURST_SIZE 148 #define DATA_IF_MTU 160 +/** + * 41-bit RACH synchronization sequence + * GSM 05.02 Chapter 5.2.7 Access burst (AB) + */ +static uint8_t rach_synch_seq[] = { + 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, + 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, +}; + namespace gr { namespace grgsm { @@ -89,6 +99,24 @@ namespace gr { delete d_clck_sock; } + /* + * Check if burst is a RACH burst + */ + bool trx_impl::detect_rach(uint8_t *burst) + { + // Compare synchronization sequence + for (int i = 0; i < 41; i++) + if (burst[i + 8] != rach_synch_seq[i]) + return false; + + // Make sure TB and GP are filled by 0x00 + for (int i = 0; i < 63; i++) + if (burst[i + 85] != 0x00) + return false; + + return true; + } + /* * Create an UDP payload with clock indication */ @@ -204,9 +232,9 @@ namespace gr { header->timeslot = payload[0]; header->frame_number = htobe32(fn); - // HACK: use GSMTAP_BURST_NORMAL for now - // FIXME: We will need to distinguish between RACN and NORMAL - header->sub_type = GSMTAP_BURST_NORMAL; + // Check if one is a RACH burst + header->sub_type = detect_rach(payload + 6) ? + GSMTAP_BURST_ACCESS : GSMTAP_BURST_NORMAL; // Copy burst bits (0 & 1) for source message memcpy(buf + sizeof(gsmtap_hdr), payload + 6, BURST_SIZE); diff --git a/lib/trx_interface/trx_impl.h b/lib/trx_interface/trx_impl.h index 29545b1..65b4d97 100644 --- a/lib/trx_interface/trx_impl.h +++ b/lib/trx_interface/trx_impl.h @@ -37,6 +37,7 @@ namespace gr { udp_socket *d_data_sock; udp_socket *d_clck_sock; + bool detect_rach(uint8_t *burst); void clck_ind_send(uint32_t frame_nr); void burst_pack(pmt::pmt_t msg, uint8_t *buf); -- cgit v1.2.3 From 7427bafd509f73e0c6352edde3f8617ca8f5250d Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 19 Jul 2017 14:43:48 +0700 Subject: apps/trx: separate UDP socket implementation --- apps/trx/ctrl_if.py | 33 ++++--------------------------- apps/trx/udp_link.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 29 deletions(-) create mode 100644 apps/trx/udp_link.py diff --git a/apps/trx/ctrl_if.py b/apps/trx/ctrl_if.py index 43fc185..58960c5 100644 --- a/apps/trx/ctrl_if.py +++ b/apps/trx/ctrl_if.py @@ -25,42 +25,17 @@ import socket import select -class UDPServer: - def __init__(self, remote_addr, remote_port, bind_port): - self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - self.sock.bind(('0.0.0.0', bind_port)) - self.sock.setblocking(0) +from udp_link import UDPLink - # Save remote info - self.remote_addr = remote_addr - self.remote_port = remote_port - - def loop(self): - r_event, w_event, x_event = select.select([self.sock], [], []) - - # Check for incoming data - if self.sock in r_event: - data, addr = self.sock.recvfrom(128) - self.handle_rx(data) - - def shutdown(self): - self.sock.close(); - - def send(self, data): - self.sock.sendto(data, (self.remote_addr, self.remote_port)) - - def handle_rx(self, data): - raise NotImplementedError - -class CTRLInterface(UDPServer): +class CTRLInterface(UDPLink): def __init__(self, remote_addr, remote_port, bind_port, radio_if): print("[i] Init TRX CTRL interface") - UDPServer.__init__(self, remote_addr, remote_port, bind_port) + UDPLink.__init__(self, remote_addr, remote_port, bind_port) self.tb = radio_if def shutdown(self): print("[i] Shutdown TRX CTRL interface") - UDPServer.shutdown(self) + UDPLink.shutdown(self) def handle_rx(self, data): if self.verify_req(data): diff --git a/apps/trx/udp_link.py b/apps/trx/udp_link.py new file mode 100644 index 0000000..0d90ec9 --- /dev/null +++ b/apps/trx/udp_link.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# GR-GSM based transceiver +# UDP link implementation +# +# (C) 2017 by Vadim Yanitskiy +# +# All Rights Reserved +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import socket +import select + +class UDPLink: + def __init__(self, remote_addr, remote_port, bind_port): + self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self.sock.bind(('0.0.0.0', bind_port)) + self.sock.setblocking(0) + + # Save remote info + self.remote_addr = remote_addr + self.remote_port = remote_port + + def loop(self): + r_event, w_event, x_event = select.select([self.sock], [], []) + + # Check for incoming data + if self.sock in r_event: + data, addr = self.sock.recvfrom(128) + self.handle_rx(data.decode()) + + def shutdown(self): + self.sock.close(); + + def send(self, data): + if type(data) not in [bytearray, bytes]: + data = data.encode() + + self.sock.sendto(data, (self.remote_addr, self.remote_port)) + + def handle_rx(self, data): + raise NotImplementedError -- cgit v1.2.3 From 4b5c299dc02101650a39df232a48e25f4d822e7a Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 19 Jul 2017 14:54:14 +0700 Subject: apps/trx: get rid of meaningless main function --- apps/trx/grgsm_trx.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/trx/grgsm_trx.py b/apps/trx/grgsm_trx.py index 25f76cf..7a1ece3 100755 --- a/apps/trx/grgsm_trx.py +++ b/apps/trx/grgsm_trx.py @@ -143,8 +143,6 @@ class Application: self.shutdown() sys.exit(0) -def main(): - Application().run() - if __name__ == '__main__': - main() + app = Application() + app.run() -- cgit v1.2.3 From f3eccbf44460865641e64efb1b5c8bd99e8ded1c Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 19 Jul 2017 15:17:37 +0700 Subject: apps/trx: separate CTRLInterface implementation --- apps/trx/ctrl_if.py | 82 ++++++++------------------------------ apps/trx/ctrl_if_bb.py | 104 +++++++++++++++++++++++++++++++++++++++++++++++++ apps/trx/grgsm_trx.py | 4 +- 3 files changed, 122 insertions(+), 68 deletions(-) create mode 100644 apps/trx/ctrl_if_bb.py diff --git a/apps/trx/ctrl_if.py b/apps/trx/ctrl_if.py index 58960c5..0129d7f 100644 --- a/apps/trx/ctrl_if.py +++ b/apps/trx/ctrl_if.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- # GR-GSM based transceiver -# Transceiver UDP interface +# CTRL interface implementation # # (C) 2016-2017 by Vadim Yanitskiy # @@ -22,25 +22,18 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -import socket -import select - from udp_link import UDPLink class CTRLInterface(UDPLink): - def __init__(self, remote_addr, remote_port, bind_port, radio_if): - print("[i] Init TRX CTRL interface") - UDPLink.__init__(self, remote_addr, remote_port, bind_port) - self.tb = radio_if - - def shutdown(self): - print("[i] Shutdown TRX CTRL interface") - UDPLink.shutdown(self) - def handle_rx(self, data): if self.verify_req(data): request = self.prepare_req(data) - self.parse_cmd(request) + rc = self.parse_cmd(request) + + if type(rc) is tuple: + self.send_response(request, rc[0], rc[1]) + else: + self.send_response(request, rc) else: print("[!] Wrong data on CTRL interface") @@ -72,61 +65,18 @@ class CTRLInterface(UDPLink): return True - def parse_cmd(self, request): - response_code = "0" - - # Power control - if self.verify_cmd(request, "POWERON", 0): - print("[i] Recv POWERON cmd") - if not self.tb.trx_started: - if self.tb.check_available(): - print("[i] Starting transceiver...") - self.tb.trx_started = True - self.tb.start() - else: - print("[!] Transceiver isn't ready to start") - response_code = "-1" - else: - print("[!] Transceiver already started!") - response_code = "-1" - elif self.verify_cmd(request, "POWEROFF", 0): - print("[i] Recv POWEROFF cmd") - print("[i] Stopping transceiver...") - self.tb.trx_started = False - # TODO: flush all buffers between blocks - self.tb.stop() - elif self.verify_cmd(request, "SETRXGAIN", 1): - print("[i] Recv SETRXGAIN cmd") - # TODO: check gain value - gain = int(request[1]) - self.tb.set_gain(gain) - - # Tuning Control - elif self.verify_cmd(request, "RXTUNE", 1): - print("[i] Recv RXTUNE cmd") - # TODO: check freq range - freq = int(request[1]) * 1000 - self.tb.set_fc(freq) - elif self.verify_cmd(request, "TXTUNE", 1): - print("[i] Recv TXTUNE cmd") - # TODO: is not implemented yet - - # Misc - elif self.verify_cmd(request, "ECHO", 0): - print("[i] Recv ECHO cmd") - - # Wrong / unknown command - else: - print("[!] Wrong request on CTRL interface") - response_code = "-1" + def send_response(self, request, response_code, params = None): + # Include status code, for example ["TXTUNE", "0", "941600"] + request.insert(1, str(response_code)) - # Anyway, we need to respond - self.send_response(request, response_code) + # Optionally append command specific parameters + if params is not None: + request += params - def send_response(self, request, response_code): - # Include status code, for example ["TXTUNE", "0", "941600"] - request.insert(1, response_code) # Add the response signature, and join back to string response = "RSP " + " ".join(request) + "\0" # Now we have something like "RSP TXTUNE 0 941600" self.send(response) + + def parse_cmd(self, request): + raise NotImplementedError diff --git a/apps/trx/ctrl_if_bb.py b/apps/trx/ctrl_if_bb.py new file mode 100644 index 0000000..8f7b57a --- /dev/null +++ b/apps/trx/ctrl_if_bb.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# GR-GSM based transceiver +# CTRL interface for OsmocomBB +# +# (C) 2016-2017 by Vadim Yanitskiy +# +# All Rights Reserved +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +from ctrl_if import CTRLInterface + +class CTRLInterfaceBB(CTRLInterface): + def __init__(self, remote_addr, remote_port, bind_port, tb): + print("[i] Init CTRL interface") + CTRLInterface.__init__(self, remote_addr, remote_port, bind_port) + + # Set link to the follow graph (top block) + self.tb = tb + + def shutdown(self): + print("[i] Shutdown CTRL interface") + CTRLInterface.shutdown(self) + + def parse_cmd(self, request): + # Power control + if self.verify_cmd(request, "POWERON", 0): + print("[i] Recv POWERON CMD") + + # Ensure transceiver isn't working + if self.tb.trx_started: + print("[!] Transceiver already started") + return -1 + + # Ensure transceiver is ready to start + if not self.tb.check_available(): + print("[!] Transceiver isn't ready to start") + return -1 + + print("[i] Starting transceiver...") + self.tb.trx_started = True + self.tb.start() + + return 0 + + elif self.verify_cmd(request, "POWEROFF", 0): + print("[i] Recv POWEROFF cmd") + + # TODO: flush all buffers between blocks + if self.tb.trx_started: + print("[i] Stopping transceiver...") + self.tb.trx_started = False + self.tb.stop() + + return 0 + + elif self.verify_cmd(request, "SETRXGAIN", 1): + print("[i] Recv SETRXGAIN cmd") + + # TODO: check gain value + gain = int(request[1]) + self.tb.set_gain(gain) + + return 0 + + # Tuning Control + elif self.verify_cmd(request, "RXTUNE", 1): + print("[i] Recv RXTUNE cmd") + + # TODO: check freq range + freq = int(request[1]) * 1000 + self.tb.set_fc(freq) + + return 0 + + elif self.verify_cmd(request, "TXTUNE", 1): + print("[i] Recv TXTUNE cmd") + + # TODO: is not implemented yet + return 0 + + # Misc + elif self.verify_cmd(request, "ECHO", 0): + print("[i] Recv ECHO cmd") + return 0 + + # Wrong / unknown command + else: + print("[!] Wrong request on CTRL interface") + return -1 diff --git a/apps/trx/grgsm_trx.py b/apps/trx/grgsm_trx.py index 7a1ece3..dbc1c9f 100755 --- a/apps/trx/grgsm_trx.py +++ b/apps/trx/grgsm_trx.py @@ -25,7 +25,7 @@ import signal import getopt import sys -from ctrl_if import CTRLInterface +from ctrl_if_bb import CTRLInterfaceBB from radio_if import RadioInterface COPYRIGHT = \ @@ -61,7 +61,7 @@ class Application: self.remote_addr, self.base_port) # Init TRX CTRL interface - self.server = CTRLInterface(self.remote_addr, + self.server = CTRLInterfaceBB(self.remote_addr, self.base_port + 101, self.base_port + 1, self.radio) print("[i] Init complete") -- cgit v1.2.3 From dd0b06a5fcfeaf3f064472f743235a5036d1c762 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 19 Jul 2017 15:22:41 +0700 Subject: apps/trx: wait until transceiver actually stop --- apps/trx/ctrl_if_bb.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/trx/ctrl_if_bb.py b/apps/trx/ctrl_if_bb.py index 8f7b57a..90d6740 100644 --- a/apps/trx/ctrl_if_bb.py +++ b/apps/trx/ctrl_if_bb.py @@ -65,6 +65,7 @@ class CTRLInterfaceBB(CTRLInterface): print("[i] Stopping transceiver...") self.tb.trx_started = False self.tb.stop() + self.tb.wait() return 0 -- cgit v1.2.3 From 5f393a41bb60a0b005be8823298e41d29190d05e Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 19 Jul 2017 15:24:03 +0700 Subject: apps/trx/radio_if.py: drop unused imports --- apps/trx/radio_if.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/trx/radio_if.py b/apps/trx/radio_if.py index 41eb3e8..9029f85 100644 --- a/apps/trx/radio_if.py +++ b/apps/trx/radio_if.py @@ -29,9 +29,6 @@ import osmosdr from math import pi -from gnuradio.eng_option import eng_option -from gnuradio import eng_notation -from gnuradio.filter import firdes from gnuradio import blocks from gnuradio import gr -- cgit v1.2.3 From 5b7c60af7a2e910e11ce03884ee54081c911ff26 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 19 Jul 2017 17:30:44 +0700 Subject: trx_interface: implement built-in timeslot filter There is a dedicated block named 'Burst Timeslot Filter', which could be used, but one doesn't expose the API to change the timeslot index 'on fly'. This change implements built-in timeslot filter in 'TRX Interface' block, which will be used until the proper block expose API. --- include/grgsm/trx_interface/trx.h | 4 ++++ lib/trx_interface/trx_impl.cc | 22 ++++++++++++++++++++++ lib/trx_interface/trx_impl.h | 5 +++++ 3 files changed, 31 insertions(+) diff --git a/include/grgsm/trx_interface/trx.h b/include/grgsm/trx_interface/trx.h index 7821389..997ef62 100644 --- a/include/grgsm/trx_interface/trx.h +++ b/include/grgsm/trx_interface/trx.h @@ -50,6 +50,10 @@ namespace gr { static sptr make( const std::string &remote_addr, const std::string &base_port); + + /* Expose internal timeslot filter API */ + virtual void ts_filter_set_tn(int tn) = 0; + virtual int ts_filter_get_tn(void) = 0; }; } // namespace grgsm diff --git a/lib/trx_interface/trx_impl.cc b/lib/trx_interface/trx_impl.cc index 8847278..2068da3 100644 --- a/lib/trx_interface/trx_impl.cc +++ b/lib/trx_interface/trx_impl.cc @@ -87,6 +87,9 @@ namespace gr { // Bind DATA interface handler d_data_sock->udp_rx_handler = boost::bind( &trx_impl::handle_ul_burst, this, _1, _2); + + // Init timeslot filter + d_ts_filter_tn = -1; } /* @@ -99,6 +102,21 @@ namespace gr { delete d_clck_sock; } + /* + * Timeslot filter API (getter and setter) + */ + void + trx_impl::ts_filter_set_tn(int tn) + { + d_ts_filter_tn = (tn >= 0 && tn <= 7) ? tn : -1; + } + + int + trx_impl::ts_filter_get_tn(void) + { + return d_ts_filter_tn; + } + /* * Check if burst is a RACH burst */ @@ -192,6 +210,10 @@ namespace gr { // Compose a new UDP payload with burst burst_pack(msg, buf); + // Timeslot filter + if (d_ts_filter_tn != -1 && buf[0] != d_ts_filter_tn) + return; + // Send a burst d_data_sock->udp_send(buf, 158); } diff --git a/lib/trx_interface/trx_impl.h b/lib/trx_interface/trx_impl.h index 65b4d97..19e4848 100644 --- a/lib/trx_interface/trx_impl.h +++ b/lib/trx_interface/trx_impl.h @@ -36,6 +36,7 @@ namespace gr { private: udp_socket *d_data_sock; udp_socket *d_clck_sock; + int d_ts_filter_tn; bool detect_rach(uint8_t *burst); void clck_ind_send(uint32_t frame_nr); @@ -45,6 +46,10 @@ namespace gr { trx_impl(const std::string &remote_addr, int base_port); ~trx_impl(); + /* Timeslot filter API */ + void ts_filter_set_tn(int tn); + int ts_filter_get_tn(void); + void handle_dl_burst(pmt::pmt_t msg); void handle_ul_burst(uint8_t *payload, size_t len); }; -- cgit v1.2.3 From 45d9f2235261fa5ad48f908d4ed216e59d8e9836 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 19 Jul 2017 17:35:56 +0700 Subject: apps/trx: handle SETSLOT command Currently, this command is used only to (re)configure built-in timeslot filter of 'TRX Interface' block. Channel configuration number, provided as the second parameter of command, is ignored. --- apps/trx/ctrl_if_bb.py | 22 ++++++++++++++++++++++ apps/trx/radio_if.py | 6 ------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/apps/trx/ctrl_if_bb.py b/apps/trx/ctrl_if_bb.py index 90d6740..1705cf1 100644 --- a/apps/trx/ctrl_if_bb.py +++ b/apps/trx/ctrl_if_bb.py @@ -94,6 +94,28 @@ class CTRLInterfaceBB(CTRLInterface): # TODO: is not implemented yet return 0 + # Timeslot management + elif self.verify_cmd(request, "SETSLOT", 2): + print("[i] Recv SETSLOT cmd") + + # Obtain TS index + tn = int(request[1]) + if tn not in range(0, 8): + print("[!] TS index should be in range: 0..7") + return -1 + + # Ignore timeslot type for now + # Value 0 means 'drop all' + config = -1 if int(request[2]) == 0 else tn + + print("[i] Configure timeslot filter to: %s" + % ("drop all" if config == -1 else "TS %d" % tn)) + + # HACK: configure built-in timeslot filter + self.tb.gsm_trx_if.ts_filter_set_tn(config) + + return 0 + # Misc elif self.verify_cmd(request, "ECHO", 0): print("[i] Recv ECHO cmd") diff --git a/apps/trx/radio_if.py b/apps/trx/radio_if.py index 9029f85..c162f69 100644 --- a/apps/trx/radio_if.py +++ b/apps/trx/radio_if.py @@ -98,9 +98,6 @@ class RadioInterface(gr.top_block): self.gsm_clck_ctrl = grgsm.clock_offset_control( shift_fc, self.samp_rate, osr = 4) - # TODO: implement configurable TS filter - self.gsm_ts_filter = grgsm.burst_timeslot_filter(0) - self.gsm_trx_if = grgsm.trx(self.trx_remote_addr, str(self.trx_base_port)) @@ -118,9 +115,6 @@ class RadioInterface(gr.top_block): (self.gsm_input, 'ctrl_in')) self.msg_connect((self.gsm_receiver, 'C0'), - (self.gsm_ts_filter, 'in')) - - self.msg_connect((self.gsm_ts_filter, 'out'), (self.gsm_trx_if, 'bursts')) def check_available(self): -- cgit v1.2.3 From 76e4b334535223a07c0a8d93186a046b7d9818cb Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 19 Jul 2017 17:51:24 +0700 Subject: apps/trx: handle MEASURE command As the actual power measurement isn't implemented yet, we will emulate this process sending random power levels from specified range. --- apps/trx/ctrl_if_bb.py | 17 +++++++++++++++- apps/trx/fake_pm.py | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ apps/trx/grgsm_trx.py | 9 ++++++++- 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 apps/trx/fake_pm.py diff --git a/apps/trx/ctrl_if_bb.py b/apps/trx/ctrl_if_bb.py index 1705cf1..b0d54f9 100644 --- a/apps/trx/ctrl_if_bb.py +++ b/apps/trx/ctrl_if_bb.py @@ -25,12 +25,14 @@ from ctrl_if import CTRLInterface class CTRLInterfaceBB(CTRLInterface): - def __init__(self, remote_addr, remote_port, bind_port, tb): + def __init__(self, remote_addr, remote_port, bind_port, tb, pm): print("[i] Init CTRL interface") CTRLInterface.__init__(self, remote_addr, remote_port, bind_port) # Set link to the follow graph (top block) self.tb = tb + # Power measurement + self.pm = pm def shutdown(self): print("[i] Shutdown CTRL interface") @@ -116,6 +118,19 @@ class CTRLInterfaceBB(CTRLInterface): return 0 + # Power measurement + elif self.verify_cmd(request, "MEASURE", 1): + print("[i] Recv MEASURE cmd") + + # TODO: check freq range + meas_freq = int(request[1]) * 1000 + + # HACK: send fake low power values + # until actual power measurement is implemented + meas_dbm = str(self.pm.measure(meas_freq)) + + return (0, [meas_dbm]) + # Misc elif self.verify_cmd(request, "ECHO", 0): print("[i] Recv ECHO cmd") diff --git a/apps/trx/fake_pm.py b/apps/trx/fake_pm.py new file mode 100644 index 0000000..1d76916 --- /dev/null +++ b/apps/trx/fake_pm.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# Virtual Um-interface (fake transceiver) +# Power measurement emulation for BB +# +# (C) 2017 by Vadim Yanitskiy +# +# All Rights Reserved +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +from random import randint + +class FakePM: + # Freq. list for good power level + bts_list = [] + + def __init__(self, noise_min, noise_max, bts_min, bts_max): + # Save power level ranges + self.noise_min = noise_min + self.noise_max = noise_max + self.bts_min = bts_min + self.bts_max = bts_max + + def measure(self, bts): + if bts in self.bts_list: + return randint(self.bts_min, self.bts_max) + else: + return randint(self.noise_min, self.noise_max) + + def update_bts_list(self, new_list): + self.bts_list = new_list + + def add_bts_list(self, add_list): + self.bts_list += add_list + + def del_bts_list(self, del_list): + for item in del_list: + if item in self.bts_list: + self.bts_list.remove(item) diff --git a/apps/trx/grgsm_trx.py b/apps/trx/grgsm_trx.py index dbc1c9f..fbc9350 100755 --- a/apps/trx/grgsm_trx.py +++ b/apps/trx/grgsm_trx.py @@ -27,6 +27,7 @@ import sys from ctrl_if_bb import CTRLInterfaceBB from radio_if import RadioInterface +from fake_pm import FakePM COPYRIGHT = \ "Copyright (C) 2016-2017 by Vadim Yanitskiy \n" \ @@ -60,9 +61,15 @@ class Application: self.phy_sample_rate, self.phy_gain, self.phy_ppm, self.remote_addr, self.base_port) + # Power measurement emulation + # Noise: -120 .. -105 + # BTS: -75 .. -50 + self.pm = FakePM(-120, -105, -75, -50) + # Init TRX CTRL interface self.server = CTRLInterfaceBB(self.remote_addr, - self.base_port + 101, self.base_port + 1, self.radio) + self.base_port + 101, self.base_port + 1, + self.radio, self.pm) print("[i] Init complete") -- cgit v1.2.3 From 2164b9be57887fa483f55ac9ca1fdf3f9d0909a7 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 13 Sep 2017 09:33:27 +0200 Subject: Added new block for tagging bursts messages with txtime --- grc/transmitter/CMakeLists.txt | 22 +++++++++++++ grc/transmitter/gsm_txtime_bursts_tagger.xml | 42 +++++++++++++++++++++++++ python/qa_txtime_bursts_tagger.py | 43 +++++++++++++++++++++++++ python/transmitter/txtime_bursts_tagger.py | 47 ++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+) create mode 100644 grc/transmitter/CMakeLists.txt create mode 100644 grc/transmitter/gsm_txtime_bursts_tagger.xml create mode 100755 python/qa_txtime_bursts_tagger.py create mode 100644 python/transmitter/txtime_bursts_tagger.py diff --git a/grc/transmitter/CMakeLists.txt b/grc/transmitter/CMakeLists.txt new file mode 100644 index 0000000..e4f5c0b --- /dev/null +++ b/grc/transmitter/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +install(FILES + gsm_txtime_bursts_tagger.xml DESTINATION share/gnuradio/grc/blocks +) diff --git a/grc/transmitter/gsm_txtime_bursts_tagger.xml b/grc/transmitter/gsm_txtime_bursts_tagger.xml new file mode 100644 index 0000000..6e72e03 --- /dev/null +++ b/grc/transmitter/gsm_txtime_bursts_tagger.xml @@ -0,0 +1,42 @@ + + + txtime_bursts_tagger + gsm_txtime_bursts_tagger + GSM + import grgsm + grgsm.txtime_bursts_tagger() + + + init_fn + init_fn + 20 + int + part + + + + init_time + init_time + [10 0.1] + none + part + + + + fn_time + message + 1 + + + + bursts + message + 1 + + + + bursts + message + 1 + + diff --git a/python/qa_txtime_bursts_tagger.py b/python/qa_txtime_bursts_tagger.py new file mode 100755 index 0000000..80257fa --- /dev/null +++ b/python/qa_txtime_bursts_tagger.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @file +# @author Piotr Krysik +# @section LICENSE +# +# Gr-gsm is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# Gr-gsm is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with gr-gsm; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# +# + +from gnuradio import gr, gr_unittest +from gnuradio import blocks +from txtime_bursts_tagger import txtime_bursts_tagger + +class qa_txtime_bursts_tagger (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_t (self): + # set up fg + self.tb.run () + # check data + + +if __name__ == '__main__': + gr_unittest.run(qa_txtime_bursts_tagger, "qa_txtime_bursts_tagger.xml") diff --git a/python/transmitter/txtime_bursts_tagger.py b/python/transmitter/txtime_bursts_tagger.py new file mode 100644 index 0000000..ce57e55 --- /dev/null +++ b/python/transmitter/txtime_bursts_tagger.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @file +# @author Piotr Krysik +# @section LICENSE +# +# Gr-gsm is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# Gr-gsm is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with gr-gsm; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# +# + +import numpy +from gnuradio import gr + +class txtime_bursts_tagger(gr.basic_block): + """ + A block that adds txtime metadata to a burst + """ + def __init__(self): + gr.basic_block.__init__(self, + name="txtime_bursts_tagger", + in_sig=[], + out_sig=[]) + self.message_port_register_in(pmt.intern("fn_time")) + self.message_port_register_in(pmt.intern("bursts")) + self.message_port_register_out(pmt.intern("bursts")) + + self.set_msg_handler(pmt.intern("fn_time"), self.set_fn_time_reference) + self.set_msg_handler(pmt.intern("bursts"), self.set_txtime_of_burst) + + def set_fn_time_reference(self, msg): + pass + + def set_txtime_of_burst() + pass -- cgit v1.2.3 From 42d1e19a2a7038d9178c4825ea55172add5a60e0 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 13 Sep 2017 09:33:47 +0200 Subject: Added cmake file for trx_interface --- lib/trx_interface/CMakeLists.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 lib/trx_interface/CMakeLists.txt diff --git a/lib/trx_interface/CMakeLists.txt b/lib/trx_interface/CMakeLists.txt new file mode 100644 index 0000000..12767b9 --- /dev/null +++ b/lib/trx_interface/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +add_sources( + trx_impl.cc + udp_socket.cc +) -- cgit v1.2.3 From 531d978480d337160b797c8d5d2d2407dbb337b5 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 13 Sep 2017 09:35:51 +0200 Subject: Added cmake files for transmitter --- python/CMakeLists.txt | 1 + python/transmitter/CMakeLists.txt | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 python/transmitter/CMakeLists.txt diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 6947d8f..a31ea2f 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -31,6 +31,7 @@ endif() add_subdirectory(misc_utils) add_subdirectory(receiver) add_subdirectory(demapping) +add_subdirectory(transmitter) GR_PYTHON_INSTALL( FILES diff --git a/python/transmitter/CMakeLists.txt b/python/transmitter/CMakeLists.txt new file mode 100644 index 0000000..38a8c39 --- /dev/null +++ b/python/transmitter/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +install(FILES + txtime_bursts_tagger.py DESTINATION ${GR_PYTHON_DIR}/grgsm +) -- cgit v1.2.3 From 3b06bdaa06e48b412e69ddb1834cd9c7353b3a20 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 13 Sep 2017 09:41:20 +0200 Subject: Correcting cmake file from lib directory --- lib/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index c6bba6e..199b63f 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -70,7 +70,6 @@ add_subdirectory(flow_control) add_subdirectory(misc_utils) add_subdirectory(qa_utils) add_subdirectory(receiver) -add_subdirectory(transmitter) add_subdirectory(trx_interface) ######################################################################## -- cgit v1.2.3 From 902f4ebaf0785dd410253e5925770dc9c20b8084 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Tue, 19 Sep 2017 08:04:33 +0200 Subject: Moved trx utilities from apps subdirectory - the grgsm_trx app need to be updated --- apps/CMakeLists.txt | 1 + apps/grgsm_trx | 155 ++++++++++++++++++++++++++++++++++++++++ python/CMakeLists.txt | 1 + python/__init__.py | 7 ++ python/trx/CMakeLists.txt | 27 +++++++ python/trx/ctrl_if.py | 82 ++++++++++++++++++++++ python/trx/ctrl_if_bb.py | 142 +++++++++++++++++++++++++++++++++++++ python/trx/fake_pm.py | 53 ++++++++++++++ python/trx/radio_if.py | 175 ++++++++++++++++++++++++++++++++++++++++++++++ python/trx/udp_link.py | 56 +++++++++++++++ swig/grgsm_swig.i.orig | 151 +++++++++++++++++++++++++++++++++++++++ 11 files changed, 850 insertions(+) create mode 100755 apps/grgsm_trx create mode 100644 python/trx/CMakeLists.txt create mode 100644 python/trx/ctrl_if.py create mode 100644 python/trx/ctrl_if_bb.py create mode 100644 python/trx/fake_pm.py create mode 100644 python/trx/radio_if.py create mode 100644 python/trx/udp_link.py create mode 100644 swig/grgsm_swig.i.orig diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index ec04f1f..855b2ed 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -28,6 +28,7 @@ GR_PYTHON_INSTALL( grgsm_livemon_headless grgsm_scanner grgsm_decode + grgsm_trx DESTINATION bin ) diff --git a/apps/grgsm_trx b/apps/grgsm_trx new file mode 100755 index 0000000..fbc9350 --- /dev/null +++ b/apps/grgsm_trx @@ -0,0 +1,155 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# GR-GSM based transceiver +# +# (C) 2016-2017 by Vadim Yanitskiy +# +# All Rights Reserved +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import signal +import getopt +import sys + +from ctrl_if_bb import CTRLInterfaceBB +from radio_if import RadioInterface +from fake_pm import FakePM + +COPYRIGHT = \ + "Copyright (C) 2016-2017 by Vadim Yanitskiy \n" \ + "License GPLv2+: GNU GPL version 2 or later " \ + "\n" \ + "This is free software: you are free to change and redistribute it.\n" \ + "There is NO WARRANTY, to the extent permitted by law.\n" + +class Application: + # Application variables + remote_addr = "127.0.0.1" + base_port = 5700 + + # PHY specific + phy_sample_rate = 2000000 + phy_subdev_spec = False + phy_gain = 30 + phy_args = "" + phy_ppm = 0 + + def __init__(self): + self.print_copyright() + self.parse_argv() + + # Set up signal handlers + signal.signal(signal.SIGINT, self.sig_handler) + + def run(self): + # Init Radio interface + self.radio = RadioInterface(self.phy_args, self.phy_subdev_spec, + self.phy_sample_rate, self.phy_gain, self.phy_ppm, + self.remote_addr, self.base_port) + + # Power measurement emulation + # Noise: -120 .. -105 + # BTS: -75 .. -50 + self.pm = FakePM(-120, -105, -75, -50) + + # Init TRX CTRL interface + self.server = CTRLInterfaceBB(self.remote_addr, + self.base_port + 101, self.base_port + 1, + self.radio, self.pm) + + print("[i] Init complete") + + # Enter main loop + while True: + self.server.loop() + + def shutdown(self): + print("[i] Shutting down...") + self.server.shutdown() + self.radio.shutdown() + + def print_copyright(self): + print(COPYRIGHT) + + def print_help(self): + s = " Usage: " + sys.argv[0] + " [options]\n\n" \ + " Some help...\n" \ + " -h --help this text\n\n" + + # TRX specific + s += " TRX interface specific\n" \ + " -s --remote-addr Set remote address (default 127.0.0.1)\n" \ + " -p --base-port Set base port number (default 5700)\n\n" + + # PHY specific + s += " Radio interface specific\n" \ + " -a --device-args Set device arguments\n" \ + " -s --sample-rate Set PHY sample rate (default 2000000)\n" \ + " -S --subdev-spec Set PHY sub-device specification\n" \ + " -g --gain Set PHY gain (default 30)\n" \ + " --ppm Set PHY frequency correction (default 0)\n" + + print(s) + + def parse_argv(self): + try: + opts, args = getopt.getopt(sys.argv[1:], + "a:p:i:s:S:g:h", + ["help", "remote-addr=", "base-port=", "device-args=", + "gain=", "subdev-spec=", "sample-rate=", "ppm="]) + except getopt.GetoptError as err: + # Print(help and exit) + self.print_help() + print("[!] " + str(err)) + sys.exit(2) + + for o, v in opts: + if o in ("-h", "--help"): + self.print_help() + sys.exit(2) + + # TRX specific + elif o in ("-i", "--remote-addr"): + self.remote_addr = v + elif o in ("-p", "--base-port"): + if int(v) >= 0 and int(v) <= 65535: + self.base_port = int(v) + else: + print("[!] The port number should be in range [0-65536]") + sys.exit(2) + + # PHY specific + elif o in ("-a", "--device-args"): + self.phy_args = v + elif o in ("-g", "--gain"): + self.phy_gain = int(v) + elif o in ("-S", "--subdev-spec"): + self.phy_subdev_spec = v + elif o in ("-s", "--sample-rate"): + self.phy_sample_rate = int(v) + elif o in ("--ppm"): + self.phy_ppm = int(v) + + def sig_handler(self, signum, frame): + print("Signal %d received" % signum) + if signum is signal.SIGINT: + self.shutdown() + sys.exit(0) + +if __name__ == '__main__': + app = Application() + app.run() diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index c7c7cae..0997931 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -32,6 +32,7 @@ add_subdirectory(misc_utils) add_subdirectory(receiver) add_subdirectory(demapping) add_subdirectory(transmitter) +add_subdirectory(trx) GR_PYTHON_INSTALL( FILES diff --git a/python/__init__.py b/python/__init__.py index 0a9e544..f29e154 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -55,6 +55,13 @@ from gsm_input import gsm_input from gsm_bcch_ccch_demapper import gsm_bcch_ccch_demapper from gsm_bcch_ccch_sdcch4_demapper import gsm_bcch_ccch_sdcch4_demapper from gsm_sdcch8_demapper import gsm_sdcch8_demapper +from fn_time import * +from txtime_bursts_tagger import * +#from ctrl_if import * +#from ctrl_if_bb import * +#from fake_pm import * +#from radio_if import * +#from udp_link import * import arfcn diff --git a/python/trx/CMakeLists.txt b/python/trx/CMakeLists.txt new file mode 100644 index 0000000..a0ad38f --- /dev/null +++ b/python/trx/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +GR_PYTHON_INSTALL( + FILES + ctrl_if_bb.py + ctrl_if.py + fake_pm.py + radio_if.py + udp_link.py DESTINATION ${GR_PYTHON_DIR}/grgsm +) diff --git a/python/trx/ctrl_if.py b/python/trx/ctrl_if.py new file mode 100644 index 0000000..a9050ef --- /dev/null +++ b/python/trx/ctrl_if.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# GR-GSM based transceiver +# CTRL interface implementation +# +# (C) 2016-2017 by Vadim Yanitskiy +# +# All Rights Reserved +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +from grgsm import UDPLink + +class CTRLInterface(UDPLink): + def handle_rx(self, data): + if self.verify_req(data): + request = self.prepare_req(data) + rc = self.parse_cmd(request) + + if type(rc) is tuple: + self.send_response(request, rc[0], rc[1]) + else: + self.send_response(request, rc) + else: + print("[!] Wrong data on CTRL interface") + + def verify_req(self, data): + # Verify command signature + return data.startswith("CMD") + + def prepare_req(self, data): + # Strip signature, paddings and \0 + request = data[4:].strip().strip("\0") + # Split into a command and arguments + request = request.split(" ") + # Now we have something like ["TXTUNE", "941600"] + return request + + def verify_cmd(self, request, cmd, argc): + # Check if requested command matches + if request[0] != cmd: + return False + + # And has enough arguments + if len(request) - 1 != argc: + return False + + # Check if all arguments are numeric + for v in request[1:]: + if not v.isdigit(): + return False + + return True + + def send_response(self, request, response_code, params = None): + # Include status code, for example ["TXTUNE", "0", "941600"] + request.insert(1, str(response_code)) + + # Optionally append command specific parameters + if params is not None: + request += params + + # Add the response signature, and join back to string + response = "RSP " + " ".join(request) + "\0" + # Now we have something like "RSP TXTUNE 0 941600" + self.send(response) + + def parse_cmd(self, request): + raise NotImplementedError diff --git a/python/trx/ctrl_if_bb.py b/python/trx/ctrl_if_bb.py new file mode 100644 index 0000000..b0d54f9 --- /dev/null +++ b/python/trx/ctrl_if_bb.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# GR-GSM based transceiver +# CTRL interface for OsmocomBB +# +# (C) 2016-2017 by Vadim Yanitskiy +# +# All Rights Reserved +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +from ctrl_if import CTRLInterface + +class CTRLInterfaceBB(CTRLInterface): + def __init__(self, remote_addr, remote_port, bind_port, tb, pm): + print("[i] Init CTRL interface") + CTRLInterface.__init__(self, remote_addr, remote_port, bind_port) + + # Set link to the follow graph (top block) + self.tb = tb + # Power measurement + self.pm = pm + + def shutdown(self): + print("[i] Shutdown CTRL interface") + CTRLInterface.shutdown(self) + + def parse_cmd(self, request): + # Power control + if self.verify_cmd(request, "POWERON", 0): + print("[i] Recv POWERON CMD") + + # Ensure transceiver isn't working + if self.tb.trx_started: + print("[!] Transceiver already started") + return -1 + + # Ensure transceiver is ready to start + if not self.tb.check_available(): + print("[!] Transceiver isn't ready to start") + return -1 + + print("[i] Starting transceiver...") + self.tb.trx_started = True + self.tb.start() + + return 0 + + elif self.verify_cmd(request, "POWEROFF", 0): + print("[i] Recv POWEROFF cmd") + + # TODO: flush all buffers between blocks + if self.tb.trx_started: + print("[i] Stopping transceiver...") + self.tb.trx_started = False + self.tb.stop() + self.tb.wait() + + return 0 + + elif self.verify_cmd(request, "SETRXGAIN", 1): + print("[i] Recv SETRXGAIN cmd") + + # TODO: check gain value + gain = int(request[1]) + self.tb.set_gain(gain) + + return 0 + + # Tuning Control + elif self.verify_cmd(request, "RXTUNE", 1): + print("[i] Recv RXTUNE cmd") + + # TODO: check freq range + freq = int(request[1]) * 1000 + self.tb.set_fc(freq) + + return 0 + + elif self.verify_cmd(request, "TXTUNE", 1): + print("[i] Recv TXTUNE cmd") + + # TODO: is not implemented yet + return 0 + + # Timeslot management + elif self.verify_cmd(request, "SETSLOT", 2): + print("[i] Recv SETSLOT cmd") + + # Obtain TS index + tn = int(request[1]) + if tn not in range(0, 8): + print("[!] TS index should be in range: 0..7") + return -1 + + # Ignore timeslot type for now + # Value 0 means 'drop all' + config = -1 if int(request[2]) == 0 else tn + + print("[i] Configure timeslot filter to: %s" + % ("drop all" if config == -1 else "TS %d" % tn)) + + # HACK: configure built-in timeslot filter + self.tb.gsm_trx_if.ts_filter_set_tn(config) + + return 0 + + # Power measurement + elif self.verify_cmd(request, "MEASURE", 1): + print("[i] Recv MEASURE cmd") + + # TODO: check freq range + meas_freq = int(request[1]) * 1000 + + # HACK: send fake low power values + # until actual power measurement is implemented + meas_dbm = str(self.pm.measure(meas_freq)) + + return (0, [meas_dbm]) + + # Misc + elif self.verify_cmd(request, "ECHO", 0): + print("[i] Recv ECHO cmd") + return 0 + + # Wrong / unknown command + else: + print("[!] Wrong request on CTRL interface") + return -1 diff --git a/python/trx/fake_pm.py b/python/trx/fake_pm.py new file mode 100644 index 0000000..1d76916 --- /dev/null +++ b/python/trx/fake_pm.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# Virtual Um-interface (fake transceiver) +# Power measurement emulation for BB +# +# (C) 2017 by Vadim Yanitskiy +# +# All Rights Reserved +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +from random import randint + +class FakePM: + # Freq. list for good power level + bts_list = [] + + def __init__(self, noise_min, noise_max, bts_min, bts_max): + # Save power level ranges + self.noise_min = noise_min + self.noise_max = noise_max + self.bts_min = bts_min + self.bts_max = bts_max + + def measure(self, bts): + if bts in self.bts_list: + return randint(self.bts_min, self.bts_max) + else: + return randint(self.noise_min, self.noise_max) + + def update_bts_list(self, new_list): + self.bts_list = new_list + + def add_bts_list(self, add_list): + self.bts_list += add_list + + def del_bts_list(self, del_list): + for item in del_list: + if item in self.bts_list: + self.bts_list.remove(item) diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py new file mode 100644 index 0000000..c162f69 --- /dev/null +++ b/python/trx/radio_if.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# GR-GSM based transceiver +# Follow graph implementation +# +# (C) 2016-2017 by Vadim Yanitskiy +# +# All Rights Reserved +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import pmt +import time +import grgsm +import osmosdr + +from math import pi + +from gnuradio import blocks +from gnuradio import gr + +class RadioInterface(gr.top_block): + # PHY specific variables + samp_rate = 2000000 + shiftoff = 400e3 + subdev_spec = "" # TODO: use it + device_args = "" + fc = 941.6e6 # TODO: set ARFCN to 0? + gain = 30 + ppm = 0 + + # Application state flags + trx_started = False + fc_set = False + + def __init__(self, phy_args, phy_subdev_spec, + phy_sample_rate, phy_gain, phy_ppm, + trx_remote_addr, trx_base_port): + print("[i] Init Radio interface") + + # TRX block specific variables + self.trx_remote_addr = trx_remote_addr + self.trx_base_port = trx_base_port + + # PHY specific variables + self.subdev_spec = phy_subdev_spec + self.samp_rate = phy_sample_rate + self.device_args = phy_args + self.gain = phy_gain + self.ppm = phy_ppm + + gr.top_block.__init__(self, "GR-GSM TRX") + shift_fc = self.fc - self.shiftoff + + ################################################## + # PHY Definition + ################################################## + self.phy = osmosdr.source( + args = "numchan=%d %s" % (1, self.device_args)) + + self.phy.set_bandwidth(250e3 + abs(self.shiftoff), 0) + self.phy.set_center_freq(shift_fc, 0) + self.phy.set_sample_rate(self.samp_rate) + self.phy.set_freq_corr(self.ppm, 0) + self.phy.set_iq_balance_mode(2, 0) + self.phy.set_dc_offset_mode(2, 0) + self.phy.set_gain_mode(False, 0) + self.phy.set_gain(self.gain, 0) + self.phy.set_if_gain(20, 0) + self.phy.set_bb_gain(20, 0) + self.phy.set_antenna("", 0) + + ################################################## + # GR-GSM Magic + ################################################## + self.blocks_rotator = blocks.rotator_cc( + -2 * pi * self.shiftoff / self.samp_rate) + + self.gsm_input = grgsm.gsm_input( + ppm = self.ppm, osr = 4, fc = self.fc, + samp_rate_in = self.samp_rate) + + self.gsm_receiver = grgsm.receiver(4, ([0]), ([])) + + self.gsm_clck_ctrl = grgsm.clock_offset_control( + shift_fc, self.samp_rate, osr = 4) + + self.gsm_trx_if = grgsm.trx(self.trx_remote_addr, + str(self.trx_base_port)) + + ################################################## + # Connections + ################################################## + self.connect((self.phy, 0), (self.blocks_rotator, 0)) + self.connect((self.blocks_rotator, 0), (self.gsm_input, 0)) + self.connect((self.gsm_input, 0), (self.gsm_receiver, 0)) + + self.msg_connect((self.gsm_receiver, 'measurements'), + (self.gsm_clck_ctrl, 'measurements')) + + self.msg_connect((self.gsm_clck_ctrl, 'ctrl'), + (self.gsm_input, 'ctrl_in')) + + self.msg_connect((self.gsm_receiver, 'C0'), + (self.gsm_trx_if, 'bursts')) + + def check_available(self): + return self.fc_set + + def shutdown(self): + print("[i] Shutdown Radio interface") + self.stop() + self.wait() + + def get_args(self): + return self.args + + def set_args(self, args): + self.args = args + + def get_fc(self): + return self.fc + + def set_fc(self, fc): + self.phy.set_center_freq(fc - self.shiftoff, 0) + self.gsm_input.set_fc(fc) + self.fc_set = True + self.fc = fc + + def get_gain(self): + return self.gain + + def set_gain(self, gain): + self.phy.set_gain(gain, 0) + self.gain = gain + + def get_ppm(self): + return self.ppm + + def set_ppm(self, ppm): + self.rtlsdr_source_0.set_freq_corr(ppm, 0) + self.ppm = ppm + + def get_samp_rate(self): + return self.samp_rate + + def set_samp_rate(self, samp_rate): + self.blocks_rotator.set_phase_inc( + -2 * pi * self.shiftoff / samp_rate) + self.gsm_input.set_samp_rate_in(samp_rate) + self.phy.set_sample_rate(samp_rate) + self.samp_rate = samp_rate + + def get_shiftoff(self): + return self.shiftoff + + def set_shiftoff(self, shiftoff): + self.blocks_rotator.set_phase_inc( + -2 * pi * shiftoff / self.samp_rate) + self.phy.set_bandwidth(250e3 + abs(shiftoff), 0) + self.phy.set_center_freq(self.fc - shiftoff, 0) + self.shiftoff = shiftoff diff --git a/python/trx/udp_link.py b/python/trx/udp_link.py new file mode 100644 index 0000000..0d90ec9 --- /dev/null +++ b/python/trx/udp_link.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# GR-GSM based transceiver +# UDP link implementation +# +# (C) 2017 by Vadim Yanitskiy +# +# All Rights Reserved +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import socket +import select + +class UDPLink: + def __init__(self, remote_addr, remote_port, bind_port): + self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self.sock.bind(('0.0.0.0', bind_port)) + self.sock.setblocking(0) + + # Save remote info + self.remote_addr = remote_addr + self.remote_port = remote_port + + def loop(self): + r_event, w_event, x_event = select.select([self.sock], [], []) + + # Check for incoming data + if self.sock in r_event: + data, addr = self.sock.recvfrom(128) + self.handle_rx(data.decode()) + + def shutdown(self): + self.sock.close(); + + def send(self, data): + if type(data) not in [bytearray, bytes]: + data = data.encode() + + self.sock.sendto(data, (self.remote_addr, self.remote_port)) + + def handle_rx(self, data): + raise NotImplementedError diff --git a/swig/grgsm_swig.i.orig b/swig/grgsm_swig.i.orig new file mode 100644 index 0000000..888f07a --- /dev/null +++ b/swig/grgsm_swig.i.orig @@ -0,0 +1,151 @@ +/* -*- c++ -*- */ +/* + * @file + * @author (C) 2014 by Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#define GRGSM_API + +%include "gnuradio.i" // the common stuff + +//load generated python docstrings +%include "grgsm_swig_doc.i" + +%{ +#include "grgsm/constants.h" +#include "grgsm/receiver/receiver.h" +#include "grgsm/receiver/clock_offset_control.h" +#include "grgsm/receiver/cx_channel_hopper.h" +#include "grgsm/decoding/control_channels_decoder.h" +#include "grgsm/decoding/tch_f_decoder.h" +#include "grgsm/decryption/decryption.h" +#include "grgsm/demapping/universal_ctrl_chans_demapper.h" +#include "grgsm/demapping/tch_f_chans_demapper.h" +#include "grgsm/flow_control/common.h" +#include "grgsm/flow_control/burst_timeslot_splitter.h" +#include "grgsm/flow_control/burst_sdcch_subslot_splitter.h" +#include "grgsm/flow_control/burst_timeslot_filter.h" +#include "grgsm/flow_control/burst_sdcch_subslot_filter.h" +#include "grgsm/flow_control/burst_fnr_filter.h" +#include "grgsm/flow_control/dummy_burst_filter.h" +#include "grgsm/flow_control/uplink_downlink_splitter.h" +#include "grgsm/misc_utils/bursts_printer.h" +#include "grgsm/misc_utils/controlled_rotator_cc.h" +#include "grgsm/misc_utils/extract_system_info.h" +#include "grgsm/misc_utils/extract_immediate_assignment.h" +#include "grgsm/misc_utils/message_printer.h" +#include "grgsm/misc_utils/tmsi_dumper.h" +#include "grgsm/misc_utils/burst_file_sink.h" +#include "grgsm/misc_utils/burst_file_source.h" +#include "grgsm/misc_utils/collect_system_info.h" +#include "grgsm/misc_utils/extract_cmc.h" +#include "grgsm/qa_utils/burst_sink.h" +#include "grgsm/qa_utils/burst_source.h" +#include "grgsm/qa_utils/message_source.h" +#include "grgsm/qa_utils/message_sink.h" +#include "grgsm/misc_utils/message_file_sink.h" +#include "grgsm/misc_utils/message_file_source.h" +#include "grgsm/misc_utils/msg_to_tag.h" +#include "grgsm/misc_utils/controlled_fractional_resampler_cc.h" +#include "grgsm/trx_interface/trx.h" +%} + +%include "constants.i" + +%include "grgsm/receiver/receiver.h" +GR_SWIG_BLOCK_MAGIC2(gsm, receiver); +%include "grgsm/receiver/clock_offset_control.h" +GR_SWIG_BLOCK_MAGIC2(gsm, clock_offset_control); +%include "grgsm/receiver/cx_channel_hopper.h" +GR_SWIG_BLOCK_MAGIC2(gsm, cx_channel_hopper); + +%include "grgsm/decoding/control_channels_decoder.h" +GR_SWIG_BLOCK_MAGIC2(gsm, control_channels_decoder); +%include "grgsm/decoding/tch_f_decoder.h" +GR_SWIG_BLOCK_MAGIC2(gsm, tch_f_decoder); + +%include "grgsm/decryption/decryption.h" +GR_SWIG_BLOCK_MAGIC2(gsm, decryption); + +%include "grgsm/demapping/universal_ctrl_chans_demapper.h" +GR_SWIG_BLOCK_MAGIC2(gsm, universal_ctrl_chans_demapper); +%include "grgsm/demapping/tch_f_chans_demapper.h" +GR_SWIG_BLOCK_MAGIC2(gsm, tch_f_chans_demapper); + +%include "grgsm/flow_control/common.h" +%include "grgsm/flow_control/burst_timeslot_splitter.h" +GR_SWIG_BLOCK_MAGIC2(gsm, burst_timeslot_splitter); +%include "grgsm/flow_control/burst_sdcch_subslot_splitter.h" +GR_SWIG_BLOCK_MAGIC2(gsm, burst_sdcch_subslot_splitter); +%include "grgsm/flow_control/burst_timeslot_filter.h" +GR_SWIG_BLOCK_MAGIC2(gsm, burst_timeslot_filter); +%include "grgsm/flow_control/burst_sdcch_subslot_filter.h" +GR_SWIG_BLOCK_MAGIC2(gsm, burst_sdcch_subslot_filter); +%include "grgsm/flow_control/burst_fnr_filter.h" +GR_SWIG_BLOCK_MAGIC2(gsm, burst_fnr_filter); +%include "grgsm/flow_control/dummy_burst_filter.h" +GR_SWIG_BLOCK_MAGIC2(gsm, dummy_burst_filter); +%include "grgsm/flow_control/uplink_downlink_splitter.h" +GR_SWIG_BLOCK_MAGIC2(grgsm, uplink_downlink_splitter); + + +%include "grgsm/misc_utils/bursts_printer.h" +GR_SWIG_BLOCK_MAGIC2(gsm, bursts_printer); +%include "grgsm/misc_utils/burst_file_sink.h" +GR_SWIG_BLOCK_MAGIC2(gsm, burst_file_sink); +%include "grgsm/misc_utils/burst_file_source.h" +GR_SWIG_BLOCK_MAGIC2(gsm, burst_file_source); +%include "grgsm/misc_utils/collect_system_info.h" +GR_SWIG_BLOCK_MAGIC2(gsm, collect_system_info); +%include "grgsm/misc_utils/extract_system_info.h" +GR_SWIG_BLOCK_MAGIC2(gsm, extract_system_info); +%include "grgsm/misc_utils/extract_immediate_assignment.h" +GR_SWIG_BLOCK_MAGIC2(gsm, extract_immediate_assignment); +%include "grgsm/misc_utils/controlled_rotator_cc.h" +GR_SWIG_BLOCK_MAGIC2(gsm, controlled_rotator_cc); +%include "grgsm/misc_utils/message_printer.h" +GR_SWIG_BLOCK_MAGIC2(gsm, message_printer); +%include "grgsm/misc_utils/tmsi_dumper.h" +GR_SWIG_BLOCK_MAGIC2(gsm, tmsi_dumper); +%include "grgsm/misc_utils/message_file_sink.h" +GR_SWIG_BLOCK_MAGIC2(gsm, message_file_sink); +%include "grgsm/misc_utils/message_file_source.h" +GR_SWIG_BLOCK_MAGIC2(gsm, message_file_source); +%include "grgsm/misc_utils/msg_to_tag.h" +GR_SWIG_BLOCK_MAGIC2(gsm, msg_to_tag); +%include "grgsm/misc_utils/controlled_fractional_resampler_cc.h" +GR_SWIG_BLOCK_MAGIC2(gsm, controlled_fractional_resampler_cc); +%include "grgsm/misc_utils/extract_cmc.h" +GR_SWIG_BLOCK_MAGIC2(gsm, extract_cmc); + + +%include "grgsm/qa_utils/burst_sink.h" +GR_SWIG_BLOCK_MAGIC2(gsm, burst_sink); +%include "grgsm/qa_utils/burst_source.h" +GR_SWIG_BLOCK_MAGIC2(gsm, burst_source); +%include "grgsm/qa_utils/message_source.h" +GR_SWIG_BLOCK_MAGIC2(gsm, message_source); +%include "grgsm/qa_utils/message_sink.h" +GR_SWIG_BLOCK_MAGIC2(gsm, message_sink); +<<<<<<< HEAD +%include "grgsm/trx_interface/trx.h" +GR_SWIG_BLOCK_MAGIC2(grgsm, trx); +======= +>>>>>>> development -- cgit v1.2.3 From 27f003267c044f4d416128fcb5cc40721a9fef77 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Tue, 19 Sep 2017 08:05:28 +0200 Subject: Adding block for tagging bursts --- grc/gsm_block_tree.xml | 4 ++ grc/transmitter/gsm_txtime_bursts_tagger.xml | 20 ++++++-- python/qa_txtime_bursts_tagger.py | 69 ++++++++++++++++++++++++++-- python/transmitter/CMakeLists.txt | 3 +- python/transmitter/txtime_bursts_tagger.py | 46 +++++++++++++++---- 5 files changed, 124 insertions(+), 18 deletions(-) diff --git a/grc/gsm_block_tree.xml b/grc/gsm_block_tree.xml index 85a89c2..0ceec47 100644 --- a/grc/gsm_block_tree.xml +++ b/grc/gsm_block_tree.xml @@ -21,6 +21,10 @@ gsm_clock_offset_control gsm_input + + Transmitter + gsm_txtime_bursts_tagger + Logical channels demapping gsm_universal_ctrl_chans_demapper diff --git a/grc/transmitter/gsm_txtime_bursts_tagger.xml b/grc/transmitter/gsm_txtime_bursts_tagger.xml index 6e72e03..8c3a203 100644 --- a/grc/transmitter/gsm_txtime_bursts_tagger.xml +++ b/grc/transmitter/gsm_txtime_bursts_tagger.xml @@ -2,14 +2,14 @@ txtime_bursts_tagger gsm_txtime_bursts_tagger - GSM import grgsm - grgsm.txtime_bursts_tagger() + grgsm.txtime_bursts_tagger($init_fn, $init_time, $time_hint) + set_time_hint($time_hint) init_fn init_fn - 20 + 0 int part @@ -17,8 +17,16 @@ init_time init_time - [10 0.1] - none + 0 + float + part + + + + time_hint + time_hint + 0 + float part @@ -28,6 +36,8 @@ 1 + + bursts message diff --git a/python/qa_txtime_bursts_tagger.py b/python/qa_txtime_bursts_tagger.py index 80257fa..bdbf1af 100755 --- a/python/qa_txtime_bursts_tagger.py +++ b/python/qa_txtime_bursts_tagger.py @@ -24,6 +24,14 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks from txtime_bursts_tagger import txtime_bursts_tagger +#from transmitter.txtime_bursts_tagger import txtime_bursts_tagger +from pmt import * + +def make_time_hint_msg(time_hint): + return cons( dict_add(make_dict(), intern("time_hint"), from_double(time_hint)),PMT_NIL) + +def make_fn_time_msg(fn_ref, time_ref): + return cons( dict_add(make_dict(), intern("fn_time"), cons(from_uint64(fn_ref), from_double(time_ref))),PMT_NIL) class qa_txtime_bursts_tagger (gr_unittest.TestCase): @@ -34,9 +42,64 @@ class qa_txtime_bursts_tagger (gr_unittest.TestCase): self.tb = None def test_001_t (self): - # set up fg - self.tb.run () - # check data + tb = self.tb + time_ref = 0 + fn_ref = 0 + dut = txtime_bursts_tagger(fn_ref, time_ref) + + framenumbers_input = [1259192, 1076346, 1076242, 235879, 1259218] + timeslots_input = [6, 3, 4, 3, 5] + bursts_input = [ + "0001100001000111100111101111100101000100101011000010011110011101001111101100010100111111100000110100011111101011101100100111110011000100010001010000", + "0001000101000000001001111110000110010110110111110111101000001101001111101100010100111111001110001001110101110001010001000111011010010001011011000000", + "0001001101101101000111001000101011001101001110110001001100111101001111101100010100111111111001001010011010011111010010010101011001001011011100110000", + "0000010010100000001001101010100001011100010001101100111111101101001111101100010100111111101101001110100010101110010110101111100010010000110010110000", + ] + + src = grgsm.burst_source(framenumbers_input, timeslots_input, bursts_input) + sink = grgsm.burst_sink() + + self.tb.msg_connect(src, "out", dut, "bursts") + self.tb.msg_connect(dut, "bursts", sink, "in") + + tb.start() + tb.wait() + print "Dupa" + print sink + + +# msg1 = make_msg(1,"lol1") +# msg2 = make_msg(1,"lol2") +# msg3 = make_msg(2,"lol1") +# msg4 = make_msg(2,"lol1") +# +# port = intern("msgs") + +# tb.msg_connect(g,"msgs",dbg,"store") +# #tb.msg_connect(g,"msgs",dbg,"print_pdu") + +# tb.start() + +# g.to_basic_block()._post(port, msg1) +# g.to_basic_block()._post(port, msg3) +# g.to_basic_block()._post(port, msg2) +# g.to_basic_block()._post(port, msg4) + + + +# while dbg.num_messages() < 4: +# time.sleep(0.1) + +# tb.stop() +# tb.wait() +# print dbg.get_message(0) +# print get_id(dbg.get_message(0)) +# +# self.assertEqual(get_id(dbg.get_message(0)),1) +# self.assertEqual(get_id(dbg.get_message(1)),1) +# self.assertEqual(get_id(dbg.get_message(2)),2) +# self.assertEqual(get_id(dbg.get_message(3)),2) + if __name__ == '__main__': diff --git a/python/transmitter/CMakeLists.txt b/python/transmitter/CMakeLists.txt index 38a8c39..121ac8a 100644 --- a/python/transmitter/CMakeLists.txt +++ b/python/transmitter/CMakeLists.txt @@ -17,6 +17,7 @@ # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. -install(FILES +GR_PYTHON_INSTALL( + FILES txtime_bursts_tagger.py DESTINATION ${GR_PYTHON_DIR}/grgsm ) diff --git a/python/transmitter/txtime_bursts_tagger.py b/python/transmitter/txtime_bursts_tagger.py index ce57e55..41cb53b 100644 --- a/python/transmitter/txtime_bursts_tagger.py +++ b/python/transmitter/txtime_bursts_tagger.py @@ -21,27 +21,55 @@ # # -import numpy from gnuradio import gr +from fn_time import fn_time_delta +import pmt +import numpy class txtime_bursts_tagger(gr.basic_block): """ A block that adds txtime metadata to a burst """ - def __init__(self): + def __init__(self, init_fn=0, init_time=0, time_hint=None): gr.basic_block.__init__(self, name="txtime_bursts_tagger", in_sig=[], out_sig=[]) + self.set_fn_time_reference(init_fn, init_time) + if time_hint is not None: + self.set_time_hint(time_hint) + self.message_port_register_in(pmt.intern("fn_time")) self.message_port_register_in(pmt.intern("bursts")) self.message_port_register_out(pmt.intern("bursts")) - - self.set_msg_handler(pmt.intern("fn_time"), self.set_fn_time_reference) - self.set_msg_handler(pmt.intern("bursts"), self.set_txtime_of_burst) + + self.set_msg_handler(pmt.intern("fn_time"), self.process_fn_time_reference) + self.set_msg_handler(pmt.intern("bursts"), self.process_txtime_of_burst) - def set_fn_time_reference(self, msg): - pass + def process_fn_time_reference(self, msg): + time_hint = pmt.to_python(pmt.dict_ref(pmt.car(msg), (pmt.intern("time_hint"),PMT_NIL))) + fn_time = pmt.to_python(pmt.dict_ref(pmt.car(msg), (pmt.intern("fn_time"),PMT_NIL))) + if time_hint is not None: + self.time_hint = time_hint + elif fn_time is not None: + self.fn_ref = pmt.car(fn_time) + self.time_ref = pmt.cdr(fn_time) + self.time_hint = self.time_ref + + def process_txtime_of_burst(self, msg): + burst_with_header = pmt.to_python(pmt.cdr(msg)) + fn = burst_with_header[11]+burst_with_header[10]*2**8+burst_with_header[9]*2**16+burst_with_header[8]*2**24 + ts_num = burst_with_header[3] + fn_delta, txtime = fn_time_delta(self.fn_ref, self.time_ref, fn, self.time_hint, ts_num) + tags_dict = pmt.dict_add(pmt.make_dict(), pmt.intern("txtime"), pmt.from_double(txtime)) + new_msg = pmt.cons(tags_dict, pmt.cdr(msg)) + self.message_port_pub(pmt.intern("bursts"), new_msg) - def set_txtime_of_burst() - pass + def set_fn_time_reference(self, init_fn, init_time): + self.fn_ref = init_fn + self.time_ref = init_time + self.set_time_hint(init_time) + + def set_time_hint(self, time_hint): + self.time_hint = time_hint + -- cgit v1.2.3 From ebf888070946ee9ac5f1fce8abc1cc989fccc6b0 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Tue, 19 Sep 2017 08:07:14 +0200 Subject: Modification of the burst sink to read bursts with headers - incomplete --- include/grgsm/qa_utils/burst_sink.h | 2 ++ lib/qa_utils/burst_sink_impl.cc | 8 ++++++-- lib/qa_utils/burst_sink_impl.h | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/grgsm/qa_utils/burst_sink.h b/include/grgsm/qa_utils/burst_sink.h index e12d027..774075f 100644 --- a/include/grgsm/qa_utils/burst_sink.h +++ b/include/grgsm/qa_utils/burst_sink.h @@ -25,6 +25,7 @@ #include #include +#include namespace gr { namespace gsm { @@ -52,6 +53,7 @@ namespace gr { virtual std::vector get_framenumbers() = 0; virtual std::vector get_timeslots() = 0; virtual std::vector get_burst_data() = 0; + virtual pmt::pmt_t get_bursts() = 0; }; } // namespace gsm } // namespace gr diff --git a/lib/qa_utils/burst_sink_impl.cc b/lib/qa_utils/burst_sink_impl.cc index 102c5be..bdc2192 100644 --- a/lib/qa_utils/burst_sink_impl.cc +++ b/lib/qa_utils/burst_sink_impl.cc @@ -47,7 +47,8 @@ namespace gr { burst_sink_impl::burst_sink_impl() : gr::block("burst_sink", gr::io_signature::make(0, 0, 0), - gr::io_signature::make(0, 0, 0)) + gr::io_signature::make(0, 0, 0)), + d_bursts(pmt::PMT_NIL) { message_port_register_in(pmt::mp("in")); set_msg_handler(pmt::mp("in"), boost::bind(&burst_sink_impl::process_burst, this, _1)); @@ -105,7 +106,10 @@ namespace gr { { return d_burst_data; } - + pmt::pmt_t burst_sink_impl::get_bursts() + { + return d_bursts; + } } /* namespace gsm */ } /* namespace gr */ diff --git a/lib/qa_utils/burst_sink_impl.h b/lib/qa_utils/burst_sink_impl.h index 1035430..e87422d 100644 --- a/lib/qa_utils/burst_sink_impl.h +++ b/lib/qa_utils/burst_sink_impl.h @@ -35,6 +35,7 @@ namespace gr { std::vector d_framenumbers; std::vector d_timeslots; std::vector d_burst_data; + pmt::pmt_t d_bursts; public: burst_sink_impl(); ~burst_sink_impl(); @@ -42,6 +43,7 @@ namespace gr { virtual std::vector get_framenumbers(); virtual std::vector get_timeslots(); virtual std::vector get_burst_data(); + virtual pmt::pmt_t get_bursts(); }; } // namespace gsm -- cgit v1.2.3 From ff5d81de50c167b1c5f71c13a779b2988326cf67 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 27 Sep 2017 21:56:42 +0200 Subject: Added gmsk modulator block for gsm --- grc/CMakeLists.txt | 1 + grc/gsm_block_tree.xml | 1 + grc/transmitter/CMakeLists.txt | 1 + grc/transmitter/gsm_gmsk_mod.xml | 47 ++++++++++++++++++++++++++ python/__init__.py | 1 + python/transmitter/gsm_gmsk_mod.py | 69 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 120 insertions(+) create mode 100644 grc/transmitter/gsm_gmsk_mod.xml create mode 100644 python/transmitter/gsm_gmsk_mod.py diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 045d6a5..26a91d5 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -24,6 +24,7 @@ add_subdirectory(receiver) add_subdirectory(flow_control) add_subdirectory(misc_utils) add_subdirectory(trx_interface) +add_subdirectory(transmitter) install(FILES gsm_block_tree.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/gsm_block_tree.xml b/grc/gsm_block_tree.xml index 0ceec47..ac3670e 100644 --- a/grc/gsm_block_tree.xml +++ b/grc/gsm_block_tree.xml @@ -24,6 +24,7 @@ Transmitter gsm_txtime_bursts_tagger + gsm_gmsk_mod Logical channels demapping diff --git a/grc/transmitter/CMakeLists.txt b/grc/transmitter/CMakeLists.txt index e4f5c0b..c41f56a 100644 --- a/grc/transmitter/CMakeLists.txt +++ b/grc/transmitter/CMakeLists.txt @@ -18,5 +18,6 @@ # Boston, MA 02110-1301, USA. install(FILES + gsm_gmsk_mod.xml gsm_txtime_bursts_tagger.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/transmitter/gsm_gmsk_mod.xml b/grc/transmitter/gsm_gmsk_mod.xml new file mode 100644 index 0000000..4aad01b --- /dev/null +++ b/grc/transmitter/gsm_gmsk_mod.xml @@ -0,0 +1,47 @@ + + GMSK Modulator for GSM + gsm_gmsk_mod + from grgsm import gsm_gmsk_mod + gsm_gmsk_mod( + BT=$BT, + pulse_duration=$pulse_duration, + sps=$sps, +) + set_BT($BT) + set_pulse_duration($pulse_duration) + set_sps($sps) + + 3 dB Time-Bandwidth Product + BT + 4 + raw + + + Pulse Duration + pulse_duration + 4 + raw + + + Samples/Symbol + sps + 4 + raw + + + in + byte + 1 + 1 + + + out + complex + 1 + 1 + + Piotr Krysik +GMSK Modulator for GSM + + gr-gsm/hier_blocks/transmitter/gsm_gmsk_mod.grc + diff --git a/python/__init__.py b/python/__init__.py index f29e154..9e99e72 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -55,6 +55,7 @@ from gsm_input import gsm_input from gsm_bcch_ccch_demapper import gsm_bcch_ccch_demapper from gsm_bcch_ccch_sdcch4_demapper import gsm_bcch_ccch_sdcch4_demapper from gsm_sdcch8_demapper import gsm_sdcch8_demapper +from gsm_gmsk_mod import gsm_gmsk_mod from fn_time import * from txtime_bursts_tagger import * #from ctrl_if import * diff --git a/python/transmitter/gsm_gmsk_mod.py b/python/transmitter/gsm_gmsk_mod.py new file mode 100644 index 0000000..e8ecc7a --- /dev/null +++ b/python/transmitter/gsm_gmsk_mod.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +################################################## +# GNU Radio Python Flow Graph +# Title: GMSK Modulator for GSM +# Author: Piotr Krysik +# Description: GMSK Modulator for GSM +# Generated: Wed Sep 20 21:12:04 2017 +################################################## + +from gnuradio import blocks +from gnuradio import digital +from gnuradio import gr +from gnuradio.analog import cpm +from gnuradio.filter import firdes +import grgsm + +class gsm_gmsk_mod(grgsm.hier_block): + + def __init__(self, BT=4, pulse_duration=4, sps=4): + gr.hier_block2.__init__( + self, "GMSK Modulator for GSM", + gr.io_signature(1, 1, gr.sizeof_char*1), + gr.io_signature(1, 1, gr.sizeof_gr_complex*1), + ) + + ################################################## + # Parameters + ################################################## + self.BT = BT + self.pulse_duration = pulse_duration + self.sps = sps + + ################################################## + # Blocks + ################################################## + self.digital_gmskmod_bc_0 = digital.gmskmod_bc(sps, pulse_duration, BT) + self.digital_diff_decoder_bb_0 = digital.diff_decoder_bb(2) + self.digital_chunks_to_symbols_xx_0 = digital.chunks_to_symbols_bf(([1,-1]), 1) + self.blocks_tagged_stream_multiply_length_0 = blocks.tagged_stream_multiply_length(gr.sizeof_gr_complex*1, "packet_len", sps) + self.blocks_float_to_char_0 = blocks.float_to_char(1, 1) + + ################################################## + # Connections + ################################################## + self.connect((self.blocks_float_to_char_0, 0), (self.digital_gmskmod_bc_0, 0)) + self.connect((self.blocks_tagged_stream_multiply_length_0, 0), (self, 0)) + self.connect((self.digital_chunks_to_symbols_xx_0, 0), (self.blocks_float_to_char_0, 0)) + self.connect((self.digital_diff_decoder_bb_0, 0), (self.digital_chunks_to_symbols_xx_0, 0)) + self.connect((self.digital_gmskmod_bc_0, 0), (self.blocks_tagged_stream_multiply_length_0, 0)) + self.connect((self, 0), (self.digital_diff_decoder_bb_0, 0)) + + def get_BT(self): + return self.BT + + def set_BT(self, BT): + self.BT = BT + + def get_pulse_duration(self): + return self.pulse_duration + + def set_pulse_duration(self, pulse_duration): + self.pulse_duration = pulse_duration + + def get_sps(self): + return self.sps + + def set_sps(self, sps): + self.sps = sps + self.blocks_tagged_stream_multiply_length_0.set_scalar(self.sps) -- cgit v1.2.3 From c6fad1f9540bd63791c242b726359ff0d503ef55 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 27 Sep 2017 21:57:08 +0200 Subject: GRC file for gsm gmsk mod --- hier_blocks/transmitter/gsm_gmsk_mod.grc | 621 +++++++++++++++++++++++++++++++ 1 file changed, 621 insertions(+) create mode 100644 hier_blocks/transmitter/gsm_gmsk_mod.grc diff --git a/hier_blocks/transmitter/gsm_gmsk_mod.grc b/hier_blocks/transmitter/gsm_gmsk_mod.grc new file mode 100644 index 0000000..4f9041b --- /dev/null +++ b/hier_blocks/transmitter/gsm_gmsk_mod.grc @@ -0,0 +1,621 @@ + + + + Wed Sep 20 07:48:30 2017 + + options + + author + Piotr Krysik + + + window_size + + + + category + Modulators + + + comment + + + + description + GMSK Modulator for GSM + + + _enabled + True + + + _coordinate + (8, 8) + + + _rotation + 0 + + + generate_options + hb + + + hier_block_src_path + .: + + + id + gsm_gmsk_mod + + + max_nouts + 0 + + + qt_qss_theme + + + + realtime_scheduling + + + + run_command + {python} -u {filename} + + + run_options + prompt + + + run + True + + + thread_safe_setters + + + + title + GMSK Modulator for GSM + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (504, 15) + + + _rotation + 0 + + + id + BT + + + label + 3 dB Time-Bandwidth Product + + + short_id + + + + type + eng_float + + + value + 4 + + + + blocks_float_to_char + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (472, 204) + + + _rotation + 0 + + + id + blocks_float_to_char_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + scale + 1 + + + vlen + 1 + + + + blocks_tagged_stream_multiply_length + + alias + + + + comment + + + + affinity + + + + _enabled + 1 + + + _coordinate + (848, 209) + + + _rotation + 0 + + + id + blocks_tagged_stream_multiply_length_0 + + + type + complex + + + c + sps + + + lengthtagname + packet_len + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + vlen + 1 + + + + digital_chunks_to_symbols_xx + + alias + + + + comment + + + + affinity + + + + dimension + 1 + + + _enabled + 1 + + + _coordinate + (296, 197) + + + _rotation + 0 + + + id + digital_chunks_to_symbols_xx_0 + + + in_type + byte + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + num_ports + 1 + + + out_type + float + + + symbol_table + [1,-1] + + + + digital_diff_decoder_bb + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + _coordinate + (120, 204) + + + _rotation + 0 + + + id + digital_diff_decoder_bb_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + modulus + 2 + + + + digital_gmskmod_bc + + bt + BT + + + alias + + + + comment + + + + affinity + + + + _enabled + 1 + + + _coordinate + (616, 190) + + + _rotation + 0 + + + id + digital_gmskmod_bc_0 + + + maxoutbuf + 0 + + + minoutbuf + 0 + + + L + pulse_duration + + + samples_per_symbol + sps + + + + import + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (712, 28) + + + _rotation + 0 + + + id + import_0 + + + import + from gnuradio.analog import cpm + + + + pad_sink + + comment + + + + _enabled + True + + + _coordinate + (1136, 220) + + + _rotation + 0 + + + id + pad_sink_0 + + + type + complex + + + label + out + + + num_streams + 1 + + + optional + True + + + vlen + 1 + + + + pad_source + + comment + + + + _enabled + True + + + _coordinate + (0, 204) + + + _rotation + 0 + + + id + pad_source_0 + + + label + in + + + num_streams + 1 + + + optional + True + + + type + byte + + + vlen + 1 + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (376, 14) + + + _rotation + 0 + + + id + pulse_duration + + + label + Pulse Duration + + + short_id + + + + type + eng_float + + + value + 4 + + + + parameter + + alias + + + + comment + + + + _enabled + True + + + _coordinate + (240, 15) + + + _rotation + 0 + + + id + sps + + + label + Samples/Symbol + + + short_id + + + + type + intx + + + value + 4 + + + + blocks_float_to_char_0 + digital_gmskmod_bc_0 + 0 + 0 + + + blocks_tagged_stream_multiply_length_0 + pad_sink_0 + 0 + 0 + + + digital_chunks_to_symbols_xx_0 + blocks_float_to_char_0 + 0 + 0 + + + digital_diff_decoder_bb_0 + digital_chunks_to_symbols_xx_0 + 0 + 0 + + + digital_gmskmod_bc_0 + blocks_tagged_stream_multiply_length_0 + 0 + 0 + + + pad_source_0 + digital_diff_decoder_bb_0 + 0 + 0 + + -- cgit v1.2.3 From df978693ebe6c97f7127eabdcc3c19a2000c3d03 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 27 Sep 2017 21:58:24 +0200 Subject: Added timestamping of bursts in the gsm receiver --- lib/receiver/CMakeLists.txt | 2 + lib/receiver/receiver_impl.cc | 49 +++++++++--- lib/receiver/receiver_impl.h | 17 ++-- lib/receiver/time_sample_ref.cc | 60 ++++++++++++++ lib/receiver/time_sample_ref.h | 49 ++++++++++++ lib/receiver/time_spec.cc | 170 ++++++++++++++++++++++++++++++++++++++++ lib/receiver/time_spec.h | 147 ++++++++++++++++++++++++++++++++++ 7 files changed, 478 insertions(+), 16 deletions(-) create mode 100644 lib/receiver/time_sample_ref.cc create mode 100644 lib/receiver/time_sample_ref.h create mode 100644 lib/receiver/time_spec.cc create mode 100644 lib/receiver/time_spec.h diff --git a/lib/receiver/CMakeLists.txt b/lib/receiver/CMakeLists.txt index 343d2f8..1c5fd53 100644 --- a/lib/receiver/CMakeLists.txt +++ b/lib/receiver/CMakeLists.txt @@ -23,4 +23,6 @@ add_sources( receiver_config.cc receiver_impl.cc viterbi_detector.cc + time_spec.cc + time_sample_ref.cc ) diff --git a/lib/receiver/receiver_impl.cc b/lib/receiver/receiver_impl.cc index b7c5be2..db7d9dd 100644 --- a/lib/receiver/receiver_impl.cc +++ b/lib/receiver/receiver_impl.cc @@ -74,10 +74,12 @@ namespace gr ) : gr::sync_block("receiver", gr::io_signature::make(1, -1, sizeof(gr_complex)), gr::io_signature::make(0, 0, 0)), + d_rx_time_received(false), + d_time_samp_ref(GSM_SYMBOL_RATE * osr), d_OSR(osr), d_process_uplink(process_uplink), d_chan_imp_length(CHAN_IMP_RESP_LENGTH), - d_counter(0), + d_counter(0), //TODO: use nitems_read instead of d_counter d_fcch_start_pos(0), d_freq_offset_setting(0), d_state(fcch_search), @@ -147,6 +149,7 @@ namespace gr std::vector iii = (std::vector) input_items; #endif + /* Time synchronization loop */ float current_time = @@ -175,7 +178,25 @@ namespace gr d_freq_offset_tag_in_fcch = tag_offset < last_sample_nr; } } - + + /* Obtaining current time with use of rx_time tag provided i.e. by UHD devices */ + /* And storing it in time_sample_ref for sample number to time conversion */ + std::vector rx_time_tags; + + get_tags_in_window(rx_time_tags, 0, 0, noutput_items, pmt::string_to_symbol("rx_time")); + if(!rx_time_tags.empty()){ + d_rx_time_received = true; + tag_t rx_time_tag = *(rx_time_tags.begin()); + + uint64_t rx_time_full_part = to_uint64(tuple_ref(rx_time_tag.value,0)); + double rx_time_frac_part = to_double(tuple_ref(rx_time_tag.value,1)); + + time_spec_t current_rx_time = time_spec_t(rx_time_full_part, rx_time_frac_part); + uint64_t current_start_offset = rx_time_tag.offset; + d_time_samp_ref.update(current_rx_time, current_start_offset); +// std::cout << "Mam rx_time: " << current_rx_time.get_real_secs() << std::endl; + } + /* Main state machine */ switch (d_state) { case fcch_search: @@ -335,7 +356,7 @@ namespace gr /* Compose a message with GSMTAP header and bits */ send_burst(d_burst_nr, output_binary, - GSMTAP_BURST_SCH, input_nr); + GSMTAP_BURST_SCH, input_nr, d_c0_burst_start); /* Attempt to decode SCH burst */ rc = decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc); @@ -381,7 +402,7 @@ namespace gr /* Compose a message with GSMTAP header and bits */ send_burst(d_burst_nr, output_binary, - GSMTAP_BURST_NORMAL, input_nr); + GSMTAP_BURST_NORMAL, input_nr, d_c0_burst_start); break; } @@ -405,13 +426,13 @@ namespace gr /* Compose a message with GSMTAP header and bits */ send_burst(d_burst_nr, output_binary, - GSMTAP_BURST_NORMAL, input_nr); + GSMTAP_BURST_NORMAL, input_nr, normal_burst_start); } else { d_c0_burst_start = dummy_burst_start; /* Compose a message with GSMTAP header and bits */ send_burst(d_burst_nr, dummy_burst, - GSMTAP_BURST_DUMMY, input_nr); + GSMTAP_BURST_DUMMY, input_nr, dummy_burst_start); } break; @@ -463,7 +484,7 @@ namespace gr burst_start, output_binary); /* Compose a message with GSMTAP header and bits */ - send_burst(d_burst_nr, output_binary, GSMTAP_BURST_NORMAL, input_nr); + send_burst(d_burst_nr, output_binary, GSMTAP_BURST_NORMAL, input_nr, burst_start); break; } @@ -980,7 +1001,7 @@ namespace gr void receiver_impl::send_burst(burst_counter burst_nr, const unsigned char * burst_binary, uint8_t burst_type, - unsigned int input_nr) + unsigned int input_nr, unsigned int burst_start) { /* Buffer for GSMTAP header and burst */ uint8_t buf[sizeof(gsmtap_hdr) + BURST_SIZE]; @@ -1019,6 +1040,17 @@ namespace gr tap_header->signal_dbm = static_cast(d_signal_dbm); tap_header->snr_db = 0; /* FIXME: Can we calculate this? */ + pmt::pmt_t pdu_header = pmt::make_dict(); + + /* Add timestamp of the first sample - if available */ + if(d_rx_time_received) { + time_spec_t time_spec_of_first_sample = d_time_samp_ref.offset_to_time(nitems_read(0)+burst_start); + uint64_t full = time_spec_of_first_sample.get_full_secs(); + double frac = time_spec_of_first_sample.get_frac_secs(); + pdu_header = + pmt::dict_add(pdu_header, pmt::mp("fn_time"), pmt::cons(pmt::from_uint64(frame_number), pmt::cons(pmt::from_uint64(full), pmt::from_double(frac)))); + } + /* Copy burst to the buffer */ memcpy(burst, burst_binary, BURST_SIZE); @@ -1093,6 +1125,5 @@ namespace gr { d_state = fcch_search; } - } /* namespace gsm */ } /* namespace gr */ diff --git a/lib/receiver/receiver_impl.h b/lib/receiver/receiver_impl.h index 6831bf1..4972b62 100644 --- a/lib/receiver/receiver_impl.h +++ b/lib/receiver/receiver_impl.h @@ -28,12 +28,15 @@ #include #include #include +#include "time_sample_ref.h" namespace gr { namespace gsm { class receiver_impl : public receiver { private: + bool d_rx_time_received; + time_sample_ref d_time_samp_ref; unsigned int d_c0_burst_start; float d_c0_signal_dbm; @@ -195,7 +198,7 @@ namespace gr { * @param burst_binary - content of the burst * @b_type - type of the burst */ - void send_burst(burst_counter burst_nr, const unsigned char * burst_binary, uint8_t burst_type, unsigned int input_nr); + void send_burst(burst_counter burst_nr, const unsigned char * burst_binary, uint8_t burst_type, unsigned int input_nr, unsigned int burst_start=-1); /** * Configures burst types in different channels @@ -209,13 +212,13 @@ namespace gr { gr_vector_const_void_star &input_items, int noutput_items); public: - receiver_impl(int osr, const std::vector &cell_allocation, const std::vector &tseq_nums, bool process_uplink); - ~receiver_impl(); + receiver_impl(int osr, const std::vector &cell_allocation, const std::vector &tseq_nums, bool process_uplink); + ~receiver_impl(); - int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); - virtual void set_cell_allocation(const std::vector &cell_allocation); - virtual void set_tseq_nums(const std::vector & tseq_nums); - virtual void reset(); + int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + virtual void set_cell_allocation(const std::vector &cell_allocation); + virtual void set_tseq_nums(const std::vector & tseq_nums); + virtual void reset(); }; } // namespace gsm } // namespace gr diff --git a/lib/receiver/time_sample_ref.cc b/lib/receiver/time_sample_ref.cc new file mode 100644 index 0000000..0cf85ed --- /dev/null +++ b/lib/receiver/time_sample_ref.cc @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * @file + * @author (C) 2017 by Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include +#include "time_sample_ref.h" + +namespace gr { + namespace gsm { + time_sample_ref::time_sample_ref(double samp_rate): d_samp_rate(samp_rate) + { + } + + time_sample_ref::~time_sample_ref() + { + } + + void time_sample_ref::update(time_spec_t last_rx_time, uint64_t current_start_offset) + { + d_last_rx_time = last_rx_time; + d_current_start_offset = current_start_offset; + } + + time_spec_t time_sample_ref::offset_to_time(uint64_t offset) + { + uint64_t samples_from_last_rx_time = offset - d_current_start_offset; + time_spec_t time = time_spec_t(static_cast(samples_from_last_rx_time)/d_samp_rate) + d_last_rx_time; + + return time; + } + + uint64_t time_sample_ref::time_to_offset(time_spec_t time) + { + double samples_since_last_rx_time_tag = (time-d_last_rx_time).get_real_secs()*d_samp_rate; +// double fractional_part = round(samples_since_last_rx_time_tag) - samples_since_last_rx_time_tag; + uint64_t offset = static_cast(round(samples_since_last_rx_time_tag)) + d_current_start_offset; + + return offset; + } + } // namespace gsm +} // namespace gr + diff --git a/lib/receiver/time_sample_ref.h b/lib/receiver/time_sample_ref.h new file mode 100644 index 0000000..1fecb81 --- /dev/null +++ b/lib/receiver/time_sample_ref.h @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * @file + * @author (C) 2017 by Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_TIME_SAMPLE_REF_IMPL_H +#define INCLUDED_TIME_SAMPLE_REF_IMPL_H + +#include +#include "time_spec.h" + +namespace gr { + namespace gsm { + /* + Class for storing time reference and for conversions time<->sample number + */ + class time_sample_ref + { + private: + double d_samp_rate; + time_spec_t d_last_rx_time; + uint64_t d_current_start_offset; + public: + time_sample_ref(double samp_rate); + ~time_sample_ref(); + void update(time_spec_t last_rx_time, uint64_t current_start_offset); + time_spec_t offset_to_time(uint64_t offset); + uint64_t time_to_offset(time_spec_t time); + }; + } // namespace gsm +} // namespace gr +#endif// INCLUDED_TIME_SAMPLE_REF_IMPL_H diff --git a/lib/receiver/time_spec.cc b/lib/receiver/time_spec.cc new file mode 100644 index 0000000..205508d --- /dev/null +++ b/lib/receiver/time_spec.cc @@ -0,0 +1,170 @@ +// +// Copyright 2011-2013 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "time_spec.h" + +namespace gr { + namespace gsm { + + /*********************************************************************** + * Time spec system time + **********************************************************************/ + + #ifdef HAVE_CLOCK_GETTIME + #include + time_spec_t time_spec_t::get_system_time(void){ + timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); + return time_spec_t(ts.tv_sec, ts.tv_nsec, 1e9); + } + #endif /* HAVE_CLOCK_GETTIME */ + + + #ifdef HAVE_MACH_ABSOLUTE_TIME + #include + time_spec_t time_spec_t::get_system_time(void){ + mach_timebase_info_data_t info; mach_timebase_info(&info); + intmax_t nanosecs = mach_absolute_time()*info.numer/info.denom; + return time_spec_t::from_ticks(nanosecs, 1e9); + } + #endif /* HAVE_MACH_ABSOLUTE_TIME */ + + + #ifdef HAVE_QUERY_PERFORMANCE_COUNTER + #include + time_spec_t time_spec_t::get_system_time(void){ + LARGE_INTEGER counts, freq; + QueryPerformanceCounter(&counts); + QueryPerformanceFrequency(&freq); + return time_spec_t::from_ticks(counts.QuadPart, double(freq.QuadPart)); + } + #endif /* HAVE_QUERY_PERFORMANCE_COUNTER */ + + + #ifdef HAVE_MICROSEC_CLOCK + #include + namespace pt = boost::posix_time; + time_spec_t time_spec_t::get_system_time(void){ + pt::ptime time_now = pt::microsec_clock::universal_time(); + pt::time_duration time_dur = time_now - pt::from_time_t(0); + return time_spec_t( + time_t(time_dur.total_seconds()), + long(time_dur.fractional_seconds()), + double(pt::time_duration::ticks_per_second()) + ); + } + #endif /* HAVE_MICROSEC_CLOCK */ + + /*********************************************************************** + * Time spec constructors + **********************************************************************/ + #define time_spec_init(full, frac) { \ + const time_t _full = time_t(full); \ + const double _frac = double(frac); \ + const int _frac_int = int(_frac); \ + _full_secs = _full + _frac_int; \ + _frac_secs = _frac - _frac_int; \ + if (_frac_secs < 0) {\ + _full_secs -= 1; \ + _frac_secs += 1; \ + } \ + } + + inline long long fast_llround(const double x){ + return (long long)(x + 0.5); // assumption of non-negativity + } + + time_spec_t::time_spec_t(const time_spec_t & spec){ + time_spec_init(spec.get_full_secs(), spec.get_frac_secs()); + } + + time_spec_t::time_spec_t(double secs){ + time_spec_init(0, secs); + } + + time_spec_t::time_spec_t(time_t full_secs, double frac_secs){ + time_spec_init(full_secs, frac_secs); + } + + time_spec_t::time_spec_t(time_t full_secs, long tick_count, double tick_rate){ + const double frac_secs = tick_count/tick_rate; + time_spec_init(full_secs, frac_secs); + } + + time_spec_t time_spec_t::from_ticks(long long ticks, double tick_rate){ + const long long rate_i = (long long)(tick_rate); + const double rate_f = tick_rate - rate_i; + const time_t secs_full = time_t(ticks/rate_i); + const long long ticks_error = ticks - (secs_full*rate_i); + const double ticks_frac = ticks_error - secs_full*rate_f; + return time_spec_t(secs_full, ticks_frac/tick_rate); + } + + /*********************************************************************** + * Time spec accessors + **********************************************************************/ + long time_spec_t::get_tick_count(double tick_rate) const{ + return long(fast_llround(this->get_frac_secs()*tick_rate)); + } + + long long time_spec_t::to_ticks(double tick_rate) const{ + const long long rate_i = (long long)(tick_rate); + const double rate_f = tick_rate - rate_i; + const long long ticks_full = this->get_full_secs()*rate_i; + const double ticks_error = this->get_full_secs()*rate_f; + const double ticks_frac = this->get_frac_secs()*tick_rate; + return ticks_full + fast_llround(ticks_error + ticks_frac); + } + + double time_spec_t::get_real_secs(void) const{ + return this->get_full_secs() + this->get_frac_secs(); + } + + /*********************************************************************** + * Time spec math overloads + **********************************************************************/ + time_spec_t &time_spec_t::operator+=(const time_spec_t &rhs){ + time_spec_init( + this->get_full_secs() + rhs.get_full_secs(), + this->get_frac_secs() + rhs.get_frac_secs() + ); + return *this; + } + + time_spec_t &time_spec_t::operator-=(const time_spec_t &rhs){ + time_spec_init( + this->get_full_secs() - rhs.get_full_secs(), + this->get_frac_secs() - rhs.get_frac_secs() + ); + return *this; + } + + bool operator==(const time_spec_t &lhs, const time_spec_t &rhs){ + return + lhs.get_full_secs() == rhs.get_full_secs() and + lhs.get_frac_secs() == rhs.get_frac_secs() + ; + } + + bool operator<(const time_spec_t &lhs, const time_spec_t &rhs){ + return ( + (lhs.get_full_secs() < rhs.get_full_secs()) or ( + (lhs.get_full_secs() == rhs.get_full_secs()) and + (lhs.get_frac_secs() < rhs.get_frac_secs()) + )); + } + } +} diff --git a/lib/receiver/time_spec.h b/lib/receiver/time_spec.h new file mode 100644 index 0000000..cc7f104 --- /dev/null +++ b/lib/receiver/time_spec.h @@ -0,0 +1,147 @@ +// +// Copyright 2010-2012 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef INCLUDED_TYPES_TIME_SPEC_HPP +#define INCLUDED_TYPES_TIME_SPEC_HPP + +#include +#include + +namespace gr { + namespace gsm { + + /*! + * A time_spec_t holds a seconds and a fractional seconds time value. + * Depending upon usage, the time_spec_t can represent absolute times, + * relative times, or time differences (between absolute times). + * + * The time_spec_t provides clock-domain independent time storage, + * but can convert fractional seconds to/from clock-domain specific units. + * + * The fractional seconds are stored as double precision floating point. + * This gives the fractional seconds enough precision to unambiguously + * specify a clock-tick/sample-count up to rates of several petahertz. + */ + class time_spec_t : boost::additive, boost::totally_ordered{ + public: + + /*! + * Get the system time in time_spec_t format. + * Uses the highest precision clock available. + * \return the system time as a time_spec_t + */ + static time_spec_t get_system_time(void); + + /*! + * Copy constructor + */ + time_spec_t(const time_spec_t & spec); + + /*! + * Create a time_spec_t from a real-valued seconds count. + * \param secs the real-valued seconds count (default = 0) + */ + time_spec_t(double secs = 0); + + /*! + * Create a time_spec_t from whole and fractional seconds. + * \param full_secs the whole/integer seconds count + * \param frac_secs the fractional seconds count (default = 0) + */ + time_spec_t(time_t full_secs, double frac_secs = 0); + + /*! + * Create a time_spec_t from whole seconds and fractional ticks. + * Translation from clock-domain specific units. + * \param full_secs the whole/integer seconds count + * \param tick_count the fractional seconds tick count + * \param tick_rate the number of ticks per second + */ + time_spec_t(time_t full_secs, long tick_count, double tick_rate); + + /*! + * Create a time_spec_t from a 64-bit tick count. + * Translation from clock-domain specific units. + * \param ticks an integer count of ticks + * \param tick_rate the number of ticks per second + */ + static time_spec_t from_ticks(long long ticks, double tick_rate); + + /*! + * Convert the fractional seconds to clock ticks. + * Translation into clock-domain specific units. + * \param tick_rate the number of ticks per second + * \return the fractional seconds tick count + */ + long get_tick_count(double tick_rate) const; + + /*! + * Convert the time spec into a 64-bit tick count. + * Translation into clock-domain specific units. + * \param tick_rate the number of ticks per second + * \return an integer number of ticks + */ + long long to_ticks(const double tick_rate) const; + + /*! + * Get the time as a real-valued seconds count. + * Note: If this time_spec_t represents an absolute time, + * the precision of the fractional seconds may be lost. + * \return the real-valued seconds + */ + double get_real_secs(void) const; + + /*! + * Get the whole/integer part of the time in seconds. + * \return the whole/integer seconds + */ + time_t get_full_secs(void) const; + + /*! + * Get the fractional part of the time in seconds. + * \return the fractional seconds + */ + double get_frac_secs(void) const; + + //! Implement addable interface + time_spec_t &operator+=(const time_spec_t &); + + //! Implement subtractable interface + time_spec_t &operator-=(const time_spec_t &); + + //private time storage details + private: time_t _full_secs; double _frac_secs; + }; + + //! Implement equality_comparable interface + bool operator==(const time_spec_t &, const time_spec_t &); + + //! Implement less_than_comparable interface + bool operator<(const time_spec_t &, const time_spec_t &); + + inline time_t time_spec_t::get_full_secs(void) const{ + return this->_full_secs; + } + + inline double time_spec_t::get_frac_secs(void) const{ + return this->_frac_secs; + } + + } //namespace transceiver +} //namespace gr + +#endif /* INCLUDED_TYPES_TIME_SPEC_HPP */ -- cgit v1.2.3 From d3c95c9190fad124f2e1e934303cc43c1218d177 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 27 Sep 2017 21:58:49 +0200 Subject: Installation of gsm_gmsk_mod.py file --- python/transmitter/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/transmitter/CMakeLists.txt b/python/transmitter/CMakeLists.txt index 121ac8a..c32d6e1 100644 --- a/python/transmitter/CMakeLists.txt +++ b/python/transmitter/CMakeLists.txt @@ -19,5 +19,6 @@ GR_PYTHON_INSTALL( FILES - txtime_bursts_tagger.py DESTINATION ${GR_PYTHON_DIR}/grgsm + txtime_bursts_tagger.py + gsm_gmsk_mod.py DESTINATION ${GR_PYTHON_DIR}/grgsm ) -- cgit v1.2.3 From eb62dc173536a392b2279d572486956c90d75c99 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 27 Sep 2017 21:59:19 +0200 Subject: Changes in fn_time --- python/misc_utils/fn_time.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/python/misc_utils/fn_time.py b/python/misc_utils/fn_time.py index 71e93db..f15743e 100644 --- a/python/misc_utils/fn_time.py +++ b/python/misc_utils/fn_time.py @@ -44,7 +44,14 @@ def fnmod_delta(fn1, fn2): delta = delta + __hyper_frame return delta - + +def fn_time_diff_delta(fn_x, fn_ref, time_diff_hint=0): + frames_diff = int(round(time_diff_hint/__frame_period)) + fn_ref_hint = (fn_ref + frames_diff) + fn_delta = fnmod_delta(fn_x,fn_ref_hint)+frames_diff + + return fn_delta + #fn_time_delta computes difference between reference frame number and a second frame number. It also computes timestamp of the second frame number. The full list of parameters is following: #* fn_ref - reference frame number modulo __hyper_frame #* time_ref - precise timestamp of the first sample in the frame fn_ref @@ -59,13 +66,11 @@ def fn_time_delta(fn_ref, time_ref, fn_x, time_hint=None, ts_num=None): if ts_num is None: ts_num = 0 - time_diff = time_hint-time_ref - frames_diff = int(round(time_diff/__frame_period)) - fn_ref = (fn_ref + frames_diff) - fn_delta = fnmod_delta(fn_x,fn_ref)+frames_diff - time2_precise = fn_delta*__frame_period+time_ref+ts_num*__ts_period + time_diff_hint = time_hint-time_ref + fn_delta = fn_time_diff_delta(fn_x,fn_ref, time_diff_hint) + time_x_precise = fn_delta*__frame_period+time_ref+ts_num*__ts_period - return fn_delta, time2_precise + return fn_delta, time_x_precise if __name__ == "__main__": @@ -77,8 +82,8 @@ if __name__ == "__main__": time2_err = time2+error fn_delta, time2_precise = fn_time_delta(fn1, time1, fn2, time2_err) if fn_delta != fn2-fn1: - print "dupa:", fn2, error#, 'fn_delta:'+str(fn_delta), time2, error, frames_diff_h4, (time2-time1)/(__hyper_frame*__frame_period), time_diff_h4_prev, time_diff - time_diff = time2 - time2_precise - if time_diff > 0.1: + print "dupa:", fn2, error#, 'fn_delta:'+str(fn_delta), time2, error, frames_diff_h4, (time2-time1)/(__hyper_frame*__frame_period), time_diff_hint_h4_prev, time_diff_hint + time_diff_hint = time2 - time2_precise + if time_diff_hint > 0.1: print "dupa" -- cgit v1.2.3 From 7980eb9e92e9ea0a81154dd218c5f8dfa285d043 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 27 Sep 2017 22:00:00 +0200 Subject: Correction in txtime_bursts_tagger --- python/transmitter/txtime_bursts_tagger.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/transmitter/txtime_bursts_tagger.py b/python/transmitter/txtime_bursts_tagger.py index 41cb53b..c990fed 100644 --- a/python/transmitter/txtime_bursts_tagger.py +++ b/python/transmitter/txtime_bursts_tagger.py @@ -61,7 +61,9 @@ class txtime_bursts_tagger(gr.basic_block): fn = burst_with_header[11]+burst_with_header[10]*2**8+burst_with_header[9]*2**16+burst_with_header[8]*2**24 ts_num = burst_with_header[3] fn_delta, txtime = fn_time_delta(self.fn_ref, self.time_ref, fn, self.time_hint, ts_num) - tags_dict = pmt.dict_add(pmt.make_dict(), pmt.intern("txtime"), pmt.from_double(txtime)) + txtime_secs = int(txtime) + txtime_fracs = txtime-int(txtime) + tags_dict = pmt.dict_add(pmt.make_dict(), pmt.intern("tx_time"), pmt.make_tuple(pmt.from_uint64(txtime_secs),pmt.from_double(txtime_fracs))) new_msg = pmt.cons(tags_dict, pmt.cdr(msg)) self.message_port_pub(pmt.intern("bursts"), new_msg) -- cgit v1.2.3 From 79b3897f2821d8f920f607f0638c069b2ec4bed3 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 27 Sep 2017 22:03:12 +0200 Subject: Updates of links to examples and test_data git submodules --- examples | 2 +- test_data | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples b/examples index e4e387d..9d0cf41 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit e4e387dddc3d9b860ae0938902fd59c1a569138c +Subproject commit 9d0cf4157114878961627d36cb7897381c4798b8 diff --git a/test_data b/test_data index 86df03f..e2e5b44 160000 --- a/test_data +++ b/test_data @@ -1 +1 @@ -Subproject commit 86df03f54d86093e2fe22daae8bb8c170cf31e58 +Subproject commit e2e5b44bc2906d5f01944355ce5c83b39eec6fee -- cgit v1.2.3 From 2c7aa9fa5fc9feca4216ffd44880c4f0e64532c6 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 27 Sep 2017 22:14:32 +0200 Subject: Little change just to check test result --- python/transmitter/txtime_bursts_tagger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/transmitter/txtime_bursts_tagger.py b/python/transmitter/txtime_bursts_tagger.py index c990fed..f587f43 100644 --- a/python/transmitter/txtime_bursts_tagger.py +++ b/python/transmitter/txtime_bursts_tagger.py @@ -55,7 +55,7 @@ class txtime_bursts_tagger(gr.basic_block): self.fn_ref = pmt.car(fn_time) self.time_ref = pmt.cdr(fn_time) self.time_hint = self.time_ref - + def process_txtime_of_burst(self, msg): burst_with_header = pmt.to_python(pmt.cdr(msg)) fn = burst_with_header[11]+burst_with_header[10]*2**8+burst_with_header[9]*2**16+burst_with_header[8]*2**24 -- cgit v1.2.3 From 96f2ea75b07ec4f23a6155be956f828b9c361f7e Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Mon, 16 Oct 2017 15:47:08 +0200 Subject: Correction needed to make TX and RX integration work --- grc/transmitter/gsm_txtime_bursts_tagger.xml | 4 +-- lib/receiver/receiver_impl.cc | 54 ++++++++++++++++------------ lib/receiver/receiver_impl.h | 1 + python/transmitter/txtime_bursts_tagger.py | 28 +++++++++------ 4 files changed, 53 insertions(+), 34 deletions(-) diff --git a/grc/transmitter/gsm_txtime_bursts_tagger.xml b/grc/transmitter/gsm_txtime_bursts_tagger.xml index 8c3a203..4012c17 100644 --- a/grc/transmitter/gsm_txtime_bursts_tagger.xml +++ b/grc/transmitter/gsm_txtime_bursts_tagger.xml @@ -9,8 +9,8 @@ init_fn init_fn - 0 - int + None + raw part diff --git a/lib/receiver/receiver_impl.cc b/lib/receiver/receiver_impl.cc index db7d9dd..d57b4a1 100644 --- a/lib/receiver/receiver_impl.cc +++ b/lib/receiver/receiver_impl.cc @@ -74,6 +74,7 @@ namespace gr ) : gr::sync_block("receiver", gr::io_signature::make(1, -1, sizeof(gr_complex)), gr::io_signature::make(0, 0, 0)), + d_samples_consumed(0), d_rx_time_received(false), d_time_samp_ref(GSM_SYMBOL_RATE * osr), d_OSR(osr), @@ -183,21 +184,8 @@ namespace gr /* And storing it in time_sample_ref for sample number to time conversion */ std::vector rx_time_tags; - get_tags_in_window(rx_time_tags, 0, 0, noutput_items, pmt::string_to_symbol("rx_time")); - if(!rx_time_tags.empty()){ - d_rx_time_received = true; - tag_t rx_time_tag = *(rx_time_tags.begin()); - - uint64_t rx_time_full_part = to_uint64(tuple_ref(rx_time_tag.value,0)); - double rx_time_frac_part = to_double(tuple_ref(rx_time_tag.value,1)); - - time_spec_t current_rx_time = time_spec_t(rx_time_full_part, rx_time_frac_part); - uint64_t current_start_offset = rx_time_tag.offset; - d_time_samp_ref.update(current_rx_time, current_start_offset); -// std::cout << "Mam rx_time: " << current_rx_time.get_real_secs() << std::endl; - } - /* Main state machine */ + d_samples_consumed = 0; switch (d_state) { case fcch_search: fcch_search_handler(input, noutput_items); @@ -210,7 +198,21 @@ namespace gr break; } - return 0; + get_tags_in_window(rx_time_tags, 0, 0, d_samples_consumed, pmt::string_to_symbol("rx_time")); + if(!rx_time_tags.empty()){ + d_rx_time_received = true; + tag_t rx_time_tag = *(rx_time_tags.begin()); + + uint64_t rx_time_full_part = to_uint64(tuple_ref(rx_time_tag.value,0)); + double rx_time_frac_part = to_double(tuple_ref(rx_time_tag.value,1)); + + time_spec_t current_rx_time = time_spec_t(rx_time_full_part, rx_time_frac_part); + uint64_t current_start_offset = rx_time_tag.offset; + d_time_samp_ref.update(current_rx_time, current_start_offset); + std::cout << "Mam rx_time: " << current_rx_time.get_real_secs() << std::endl; + } + + return d_samples_consumed; } void @@ -270,7 +272,9 @@ namespace gr d_burst_nr++; /* Consume samples up to the next guard period */ - consume_each(burst_start + BURST_SIZE * d_OSR + 4 * d_OSR); + unsigned int to_consume = burst_start + BURST_SIZE * d_OSR + 4 * d_OSR; +// consume_each(to_consume); + d_samples_consumed += to_consume; /* Update current state */ d_state = synchronized; @@ -505,7 +509,8 @@ namespace gr /* Consume samples of the burst up to next guard period */ to_consume += TS_BITS * d_OSR + d_burst_nr.get_offset(); - consume_each(to_consume); +// consume_each(to_consume); + d_samples_consumed += to_consume; } } } @@ -696,7 +701,8 @@ namespace gr } d_counter += to_consume; - consume_each(to_consume); +// consume_each(to_consume); + d_samples_consumed += to_consume; return result; } @@ -747,7 +753,8 @@ namespace gr } d_counter += to_consume; - consume_each(to_consume); +// consume_each(to_consume); + d_samples_consumed += to_consume; return result; } @@ -1047,8 +1054,11 @@ namespace gr time_spec_t time_spec_of_first_sample = d_time_samp_ref.offset_to_time(nitems_read(0)+burst_start); uint64_t full = time_spec_of_first_sample.get_full_secs(); double frac = time_spec_of_first_sample.get_frac_secs(); - pdu_header = - pmt::dict_add(pdu_header, pmt::mp("fn_time"), pmt::cons(pmt::from_uint64(frame_number), pmt::cons(pmt::from_uint64(full), pmt::from_double(frac)))); + pdu_header = + pmt::dict_add(pdu_header, pmt::mp("fn_time"), + pmt::cons( + pmt::cons(pmt::from_uint64(be32toh(frame_number)), pmt::from_uint64(tn)), + pmt::cons(pmt::from_uint64(full), pmt::from_double(frac)))); } /* Copy burst to the buffer */ @@ -1056,7 +1066,7 @@ namespace gr /* Allocate a new message */ pmt::pmt_t blob = pmt::make_blob(buf, sizeof(gsmtap_hdr) + BURST_SIZE); - pmt::pmt_t msg = pmt::cons(pmt::PMT_NIL, blob); + pmt::pmt_t msg = pmt::cons(pdu_header, blob); /* Send message */ if (input_nr == 0) diff --git a/lib/receiver/receiver_impl.h b/lib/receiver/receiver_impl.h index 4972b62..d43bb27 100644 --- a/lib/receiver/receiver_impl.h +++ b/lib/receiver/receiver_impl.h @@ -35,6 +35,7 @@ namespace gr { class receiver_impl : public receiver { private: + unsigned int d_samples_consumed; bool d_rx_time_received; time_sample_ref d_time_samp_ref; unsigned int d_c0_burst_start; diff --git a/python/transmitter/txtime_bursts_tagger.py b/python/transmitter/txtime_bursts_tagger.py index f587f43..489af2a 100644 --- a/python/transmitter/txtime_bursts_tagger.py +++ b/python/transmitter/txtime_bursts_tagger.py @@ -47,25 +47,33 @@ class txtime_bursts_tagger(gr.basic_block): self.set_msg_handler(pmt.intern("bursts"), self.process_txtime_of_burst) def process_fn_time_reference(self, msg): - time_hint = pmt.to_python(pmt.dict_ref(pmt.car(msg), (pmt.intern("time_hint"),PMT_NIL))) - fn_time = pmt.to_python(pmt.dict_ref(pmt.car(msg), (pmt.intern("fn_time"),PMT_NIL))) + time_hint = pmt.to_python(pmt.dict_ref(msg, pmt.intern("time_hint"), pmt.PMT_NIL)) + fn_time = pmt.to_python(pmt.dict_ref(msg, pmt.intern("fn_time"), pmt.PMT_NIL)) + +# if self.fn_ref is None: if time_hint is not None: self.time_hint = time_hint elif fn_time is not None: - self.fn_ref = pmt.car(fn_time) - self.time_ref = pmt.cdr(fn_time) + self.fn_ref = fn_time[0][0] + self.ts = fn_time[0][1] + full = fn_time[1][0] + frac = fn_time[1][1] + + self.time_ref = full+frac self.time_hint = self.time_ref def process_txtime_of_burst(self, msg): burst_with_header = pmt.to_python(pmt.cdr(msg)) fn = burst_with_header[11]+burst_with_header[10]*2**8+burst_with_header[9]*2**16+burst_with_header[8]*2**24 ts_num = burst_with_header[3] - fn_delta, txtime = fn_time_delta(self.fn_ref, self.time_ref, fn, self.time_hint, ts_num) - txtime_secs = int(txtime) - txtime_fracs = txtime-int(txtime) - tags_dict = pmt.dict_add(pmt.make_dict(), pmt.intern("tx_time"), pmt.make_tuple(pmt.from_uint64(txtime_secs),pmt.from_double(txtime_fracs))) - new_msg = pmt.cons(tags_dict, pmt.cdr(msg)) - self.message_port_pub(pmt.intern("bursts"), new_msg) + if self.fn_ref is not None: + fn_delta, txtime = fn_time_delta(self.fn_ref, self.time_ref, fn, self.time_hint, ts_num) + txtime_secs = int(txtime) + txtime_fracs = txtime-int(txtime) + #print "txtime_secs",txtime_secs,"txtime_fracs",txtime_fracs + tags_dict = pmt.dict_add(pmt.make_dict(), pmt.intern("tx_time"), pmt.make_tuple(pmt.from_uint64(txtime_secs),pmt.from_double(txtime_fracs))) + new_msg = pmt.cons(tags_dict, pmt.cdr(msg)) + self.message_port_pub(pmt.intern("bursts"), new_msg) def set_fn_time_reference(self, init_fn, init_time): self.fn_ref = init_fn -- cgit v1.2.3 From ffd09acd8ddcab10ce602ea5ec27d4b1d5dbc75e Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Mon, 16 Oct 2017 15:47:38 +0200 Subject: Corrections in fn_time conversions --- python/misc_utils/fn_time.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/python/misc_utils/fn_time.py b/python/misc_utils/fn_time.py index f15743e..cf03681 100644 --- a/python/misc_utils/fn_time.py +++ b/python/misc_utils/fn_time.py @@ -59,31 +59,30 @@ def fn_time_diff_delta(fn_x, fn_ref, time_diff_hint=0): #* time_hint - coarse time for fn_x that is used as a hint to avoid ambiguities caused by modulo operation applied to frame numbers. The correct are values from range (where time2_precise is exact time of the first sample in frame fn_x) #* ts_num - number of timeslot in the frame -def fn_time_delta(fn_ref, time_ref, fn_x, time_hint=None, ts_num=None): +def fn_time_delta(fn_ref, time_ref, fn_x, time_hint=None, ts_num=0, ts_ref=0): if time_hint is None: time_hint = time_ref - if ts_num is None: - ts_num = 0 - time_diff_hint = time_hint-time_ref fn_delta = fn_time_diff_delta(fn_x,fn_ref, time_diff_hint) - time_x_precise = fn_delta*__frame_period+time_ref+ts_num*__ts_period + time_x_precise = fn_delta*__frame_period+time_ref+(ts_num-ts_ref)*__ts_period return fn_delta, time_x_precise if __name__ == "__main__": fn1 = 10000 + ts_ref = 4 time1 = 10 for fn2 in xrange(__hyper_frame/2+fn1-10,__hyper_frame/2*10+fn1+10,10): - time2 = time1 + (fn2-fn1)*__frame_period + ts_x = int(uniform(0,8)) + time2 = time1 + (fn2-fn1)*__frame_period + (ts_ref-ts_x)*__ts_period error = uniform(-6200,6200) time2_err = time2+error - fn_delta, time2_precise = fn_time_delta(fn1, time1, fn2, time2_err) + fn_delta, time2_precise = fn_time_delta(fn1, time1, fn2, time2_err, ts_x, ts_ref) if fn_delta != fn2-fn1: - print "dupa:", fn2, error#, 'fn_delta:'+str(fn_delta), time2, error, frames_diff_h4, (time2-time1)/(__hyper_frame*__frame_period), time_diff_hint_h4_prev, time_diff_hint + print "bad fn:", fn2, error#, 'fn_delta:'+str(fn_delta), time2, error, frames_diff_h4, (time2-time1)/(__hyper_frame*__frame_period), time_diff_hint_h4_prev, time_diff_hint time_diff_hint = time2 - time2_precise - if time_diff_hint > 0.1: - print "dupa" + if time_diff_hint > 0.0001: + print "bad time diff" -- cgit v1.2.3 From 714cb44959a4e075143bcb1a434603c0869f9796 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Mon, 16 Oct 2017 15:54:13 +0200 Subject: New pointer to examples --- examples | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples b/examples index 9d0cf41..52432ba 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 9d0cf4157114878961627d36cb7897381c4798b8 +Subproject commit 52432ba2d0210518370676fec970770aa6fc29b6 -- cgit v1.2.3 From 42b2186b1747150b298cff6db59ccbcc2595a85e Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Thu, 19 Oct 2017 09:20:23 +0200 Subject: Added timing advance and delay corerrection to txtime_burst_tagger block --- grc/transmitter/gsm_txtime_bursts_tagger.xml | 23 ++++++++++++++++++++--- python/transmitter/txtime_bursts_tagger.py | 16 ++++++++++++++-- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/grc/transmitter/gsm_txtime_bursts_tagger.xml b/grc/transmitter/gsm_txtime_bursts_tagger.xml index 4012c17..4e42886 100644 --- a/grc/transmitter/gsm_txtime_bursts_tagger.xml +++ b/grc/transmitter/gsm_txtime_bursts_tagger.xml @@ -3,8 +3,11 @@ txtime_bursts_tagger gsm_txtime_bursts_tagger import grgsm - grgsm.txtime_bursts_tagger($init_fn, $init_time, $time_hint) + grgsm.txtime_bursts_tagger($init_fn, $init_time, $time_hint, $timing_advance, $delay_correction) + set_fn_time_reference($init_fn, $init_time) set_time_hint($time_hint) + set_timing_advance($timing_advance) + set_delay_correction($delay_correction) init_fn @@ -30,14 +33,28 @@ part + + timing_advance + timing_advance + 0 + float + part + + + + delay_correction + delay_correction + 0 + float + part + + fn_time message 1 - - bursts message diff --git a/python/transmitter/txtime_bursts_tagger.py b/python/transmitter/txtime_bursts_tagger.py index 489af2a..a083c48 100644 --- a/python/transmitter/txtime_bursts_tagger.py +++ b/python/transmitter/txtime_bursts_tagger.py @@ -30,7 +30,7 @@ class txtime_bursts_tagger(gr.basic_block): """ A block that adds txtime metadata to a burst """ - def __init__(self, init_fn=0, init_time=0, time_hint=None): + def __init__(self, init_fn=0, init_time=0, time_hint=None, timing_advance=0, delay_correction=0): gr.basic_block.__init__(self, name="txtime_bursts_tagger", in_sig=[], @@ -39,6 +39,9 @@ class txtime_bursts_tagger(gr.basic_block): if time_hint is not None: self.set_time_hint(time_hint) + self.timing_advance = timing_advance + self.delay_correction = delay_correction + self.message_port_register_in(pmt.intern("fn_time")) self.message_port_register_in(pmt.intern("bursts")) self.message_port_register_out(pmt.intern("bursts")) @@ -50,7 +53,6 @@ class txtime_bursts_tagger(gr.basic_block): time_hint = pmt.to_python(pmt.dict_ref(msg, pmt.intern("time_hint"), pmt.PMT_NIL)) fn_time = pmt.to_python(pmt.dict_ref(msg, pmt.intern("fn_time"), pmt.PMT_NIL)) -# if self.fn_ref is None: if time_hint is not None: self.time_hint = time_hint elif fn_time is not None: @@ -68,10 +70,14 @@ class txtime_bursts_tagger(gr.basic_block): ts_num = burst_with_header[3] if self.fn_ref is not None: fn_delta, txtime = fn_time_delta(self.fn_ref, self.time_ref, fn, self.time_hint, ts_num) + txtime_corrected = txtime - self.delay_correction + txtime_final = txtime_corrected - self.timing_advance + txtime_secs = int(txtime) txtime_fracs = txtime-int(txtime) #print "txtime_secs",txtime_secs,"txtime_fracs",txtime_fracs tags_dict = pmt.dict_add(pmt.make_dict(), pmt.intern("tx_time"), pmt.make_tuple(pmt.from_uint64(txtime_secs),pmt.from_double(txtime_fracs))) + tags_dict = pmt.dict_add(tags_dict, pmt.intern("fn"), pmt.from_uint64(fn)) new_msg = pmt.cons(tags_dict, pmt.cdr(msg)) self.message_port_pub(pmt.intern("bursts"), new_msg) @@ -83,3 +89,9 @@ class txtime_bursts_tagger(gr.basic_block): def set_time_hint(self, time_hint): self.time_hint = time_hint + def set_delay_correction(delay_correction): + self.delay_correction = delay_correction + + def set_timing_advance(timing_advance): + self.timing_advance = timing_advance + -- cgit v1.2.3 From 12dd9cba1f816eb69115c379eab75a10ae8b0d52 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Thu, 19 Oct 2017 16:47:52 +0200 Subject: Updated examples pointer --- examples | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples b/examples index 52432ba..1b315c4 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 52432ba2d0210518370676fec970770aa6fc29b6 +Subproject commit 1b315c4233327d2c057e0e23c01d4892e1700358 -- cgit v1.2.3 From 33fbc285008edf64ea763d32ebe6e6b347fd93b2 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Tue, 31 Oct 2017 05:54:31 +0100 Subject: Correction of bursts tagger --- python/transmitter/txtime_bursts_tagger.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/transmitter/txtime_bursts_tagger.py b/python/transmitter/txtime_bursts_tagger.py index a083c48..de42f65 100644 --- a/python/transmitter/txtime_bursts_tagger.py +++ b/python/transmitter/txtime_bursts_tagger.py @@ -73,8 +73,8 @@ class txtime_bursts_tagger(gr.basic_block): txtime_corrected = txtime - self.delay_correction txtime_final = txtime_corrected - self.timing_advance - txtime_secs = int(txtime) - txtime_fracs = txtime-int(txtime) + txtime_secs = int(txtime_final) + txtime_fracs = txtime_final-int(txtime_final) #print "txtime_secs",txtime_secs,"txtime_fracs",txtime_fracs tags_dict = pmt.dict_add(pmt.make_dict(), pmt.intern("tx_time"), pmt.make_tuple(pmt.from_uint64(txtime_secs),pmt.from_double(txtime_fracs))) tags_dict = pmt.dict_add(tags_dict, pmt.intern("fn"), pmt.from_uint64(fn)) -- cgit v1.2.3 From 29ec39b3bd0c03113118f3735b2ea83f0d262844 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Tue, 31 Oct 2017 06:31:49 +0100 Subject: Updating examples pointer --- examples | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples b/examples index 1b315c4..8bc9414 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 1b315c4233327d2c057e0e23c01d4892e1700358 +Subproject commit 8bc9414a06b7e71132ad0c27264e914ea8f05b84 -- cgit v1.2.3 From 34ce7a02f071c0aa4661799aa566236c92955d74 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Tue, 31 Oct 2017 11:30:59 +0100 Subject: Added C++ version of fn_time --- include/grgsm/misc_utils/CMakeLists.txt | 3 +- include/grgsm/misc_utils/fn_time.h | 51 ++++++++++++++++ lib/misc_utils/CMakeLists.txt | 1 + lib/misc_utils/fn_time.cc | 105 ++++++++++++++++++++++++++++++++ swig/grgsm_swig.i | 2 + 5 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 include/grgsm/misc_utils/fn_time.h create mode 100644 lib/misc_utils/fn_time.cc diff --git a/include/grgsm/misc_utils/CMakeLists.txt b/include/grgsm/misc_utils/CMakeLists.txt index 878fcfd..5bfef6a 100644 --- a/include/grgsm/misc_utils/CMakeLists.txt +++ b/include/grgsm/misc_utils/CMakeLists.txt @@ -34,5 +34,6 @@ install(FILES message_printer.h tmsi_dumper.h msg_to_tag.h - controlled_fractional_resampler_cc.h DESTINATION include/grgsm/misc_utils + controlled_fractional_resampler_cc.h + fn_time.h DESTINATION include/grgsm/misc_utils ) diff --git a/include/grgsm/misc_utils/fn_time.h b/include/grgsm/misc_utils/fn_time.h new file mode 100644 index 0000000..240506a --- /dev/null +++ b/include/grgsm/misc_utils/fn_time.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* @file + * @author Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + + +#ifndef INCLUDED_GRGSM_FN_TIME_H +#define INCLUDED_GRGSM_FN_TIME_H + +#include +#include + +namespace gr { + namespace gsm { + + /** + * Computes difference between reference frame number + * and a second frame number. + * @param fn_ref reference frame number modulo GSM_HYPER_FRAME + * @param fn second frame number modulo GSM_HYPER_FRAME + * @param time_ref precise timestamp of the first sample in the fn_ref + * @param time_hint coarse time for fn that is used as a hint to avoid + * ambiguities caused by modulo operation applied to + * frame numbers + * @return difference between fn_ref and fn + */ + uhd::time_spec_t fn_time_delta(uint32_t fn_ref, uhd::time_spec_t time_ref, uint32_t fn_x, + uhd::time_spec_t time_hint, uint32_t ts_num, uint32_t ts_ref); + + } // namespace grgsm +} // namespace gr + +#endif /* INCLUDED_GRGSM_FN_TIME_H */ + diff --git a/lib/misc_utils/CMakeLists.txt b/lib/misc_utils/CMakeLists.txt index 1c51fb6..8597553 100644 --- a/lib/misc_utils/CMakeLists.txt +++ b/lib/misc_utils/CMakeLists.txt @@ -32,5 +32,6 @@ add_sources( message_printer_impl.cc msg_to_tag_impl.cc tmsi_dumper_impl.cc + fn_time.cc ) diff --git a/lib/misc_utils/fn_time.cc b/lib/misc_utils/fn_time.cc new file mode 100644 index 0000000..5248211 --- /dev/null +++ b/lib/misc_utils/fn_time.cc @@ -0,0 +1,105 @@ +/* -*- c++ -*- */ +/* @file + * @author Piotr Krysik + * @author Vadim Yanitskiy + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + +#include +#include +#include + +#define GSM_HYPER_FRAME 26 * 51 * 2048 +#define GSM_SYM_RATE 13.0e6 / 48.0 + +#define GSM_TS_PERIOD 156.25 / GSM_SYM_RATE +#define GSM_FN_PERIOD 8 * GSM_TS_PERIOD + +namespace gr { + namespace gsm { + using namespace uhd; + /** + * Computes difference between two frame numbers modulo + * GSM_HYPER_FRAME / 2. The result is correct if difference + * between the frame numbers is not bigger than GSM_HYPER_FRAME / 2. + * @param fn1 first frame number + * @param fn2 second frame number + * @return computed difference + */ + static uint32_t fnmod_delta(uint32_t fn1, uint32_t fn2) + { + uint32_t delta, h2; + + delta = (fn1 % GSM_HYPER_FRAME) - (fn2 % GSM_HYPER_FRAME); + h2 = GSM_HYPER_FRAME / 2; + + if (delta >= h2) + delta -= GSM_HYPER_FRAME; + else + delta += GSM_HYPER_FRAME; + + return delta; + } + + static int fn_time_diff_delta(uint32_t fn, uint32_t fn_ref, + time_spec_t time_diff_hint) + { + int frames_diff, fn_delta; + + frames_diff = int(round(time_diff_hint.get_real_secs() / GSM_FN_PERIOD)); + fn_delta = fnmod_delta(fn, fn_ref + frames_diff) + frames_diff; + + return fn_delta; + } + + /** + * Computes difference between reference frame number + * and a second frame number. + * @param fn_ref reference frame number modulo GSM_HYPER_FRAME + * @param fn second frame number modulo GSM_HYPER_FRAME + * @param time_ref precise timestamp of the first sample in the fn_ref + * @param time_hint coarse time for fn that is used as a hint to avoid + * ambiguities caused by modulo operation applied to + * frame numbers + * @return difference between fn_ref and fn + */ + time_spec_t fn_time_delta(uint32_t fn_ref, time_spec_t time_ref, uint32_t fn_x, + time_spec_t time_hint, uint32_t ts_num, uint32_t ts_ref) + { + time_spec_t time_diff_hint = time_hint - time_ref; + uint32_t fn_delta = fn_time_diff_delta(fn_x,fn_ref, time_diff_hint); + time_spec_t time_x_precise = fn_delta * GSM_FN_PERIOD + + time_ref + (ts_num - ts_ref) * GSM_TS_PERIOD; + + return time_x_precise; + } +/* + def fn_time_delta(fn_ref, time_ref, fn_x, time_hint=None, ts_num=0, ts_ref=0): + if time_hint is None: + time_hint = time_ref + + time_diff_hint = time_hint-time_ref + fn_delta = fn_time_diff_delta(fn_x,fn_ref, time_diff_hint) + time_x_precise = fn_delta*__frame_period+time_ref+(ts_num-ts_ref)*__ts_period + + return fn_delta, time_x_precise +*/ + } /* namespace gsm */ +} /* namespace gr */ + diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i index a67e264..08d95f1 100644 --- a/swig/grgsm_swig.i +++ b/swig/grgsm_swig.i @@ -65,6 +65,7 @@ #include "grgsm/misc_utils/msg_to_tag.h" #include "grgsm/misc_utils/controlled_fractional_resampler_cc.h" #include "grgsm/trx_interface/trx.h" +#include "grgsm/misc_utils/fn_time.h" %} %include "constants.i" @@ -146,3 +147,4 @@ GR_SWIG_BLOCK_MAGIC2(gsm, message_source); GR_SWIG_BLOCK_MAGIC2(gsm, message_sink); %include "grgsm/trx_interface/trx.h" GR_SWIG_BLOCK_MAGIC2(grgsm, trx); +%include "grgsm/misc_utils/fn_time.h" -- cgit v1.2.3 From 1dd2afe367b52cc1d77ca11a3832bf1fdcac6ef2 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Tue, 31 Oct 2017 12:57:26 +0100 Subject: Changed fn_time to use time_spec_t copied from libUHD --- include/grgsm/misc_utils/CMakeLists.txt | 1 + include/grgsm/misc_utils/fn_time.h | 6 +- include/grgsm/misc_utils/time_spec.h | 147 +++++++++++++++++++++++++++ lib/misc_utils/CMakeLists.txt | 1 + lib/misc_utils/fn_time.cc | 4 +- lib/misc_utils/time_spec.cc | 170 ++++++++++++++++++++++++++++++++ lib/receiver/CMakeLists.txt | 1 - lib/receiver/time_sample_ref.h | 2 +- lib/receiver/time_spec.cc | 170 -------------------------------- lib/receiver/time_spec.h | 147 --------------------------- python/misc_utils/CMakeLists.txt | 3 +- swig/grgsm_swig.i | 4 +- 12 files changed, 329 insertions(+), 327 deletions(-) create mode 100644 include/grgsm/misc_utils/time_spec.h create mode 100644 lib/misc_utils/time_spec.cc delete mode 100644 lib/receiver/time_spec.cc delete mode 100644 lib/receiver/time_spec.h diff --git a/include/grgsm/misc_utils/CMakeLists.txt b/include/grgsm/misc_utils/CMakeLists.txt index 5bfef6a..978695e 100644 --- a/include/grgsm/misc_utils/CMakeLists.txt +++ b/include/grgsm/misc_utils/CMakeLists.txt @@ -35,5 +35,6 @@ install(FILES tmsi_dumper.h msg_to_tag.h controlled_fractional_resampler_cc.h + time_spec.h fn_time.h DESTINATION include/grgsm/misc_utils ) diff --git a/include/grgsm/misc_utils/fn_time.h b/include/grgsm/misc_utils/fn_time.h index 240506a..560ee4a 100644 --- a/include/grgsm/misc_utils/fn_time.h +++ b/include/grgsm/misc_utils/fn_time.h @@ -25,7 +25,7 @@ #define INCLUDED_GRGSM_FN_TIME_H #include -#include +#include namespace gr { namespace gsm { @@ -41,8 +41,8 @@ namespace gr { * frame numbers * @return difference between fn_ref and fn */ - uhd::time_spec_t fn_time_delta(uint32_t fn_ref, uhd::time_spec_t time_ref, uint32_t fn_x, - uhd::time_spec_t time_hint, uint32_t ts_num, uint32_t ts_ref); + time_spec_t fn_time_delta2(uint32_t fn_ref, time_spec_t time_ref, uint32_t fn_x, + time_spec_t time_hint, uint32_t ts_num, uint32_t ts_ref); } // namespace grgsm } // namespace gr diff --git a/include/grgsm/misc_utils/time_spec.h b/include/grgsm/misc_utils/time_spec.h new file mode 100644 index 0000000..cc7f104 --- /dev/null +++ b/include/grgsm/misc_utils/time_spec.h @@ -0,0 +1,147 @@ +// +// Copyright 2010-2012 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef INCLUDED_TYPES_TIME_SPEC_HPP +#define INCLUDED_TYPES_TIME_SPEC_HPP + +#include +#include + +namespace gr { + namespace gsm { + + /*! + * A time_spec_t holds a seconds and a fractional seconds time value. + * Depending upon usage, the time_spec_t can represent absolute times, + * relative times, or time differences (between absolute times). + * + * The time_spec_t provides clock-domain independent time storage, + * but can convert fractional seconds to/from clock-domain specific units. + * + * The fractional seconds are stored as double precision floating point. + * This gives the fractional seconds enough precision to unambiguously + * specify a clock-tick/sample-count up to rates of several petahertz. + */ + class time_spec_t : boost::additive, boost::totally_ordered{ + public: + + /*! + * Get the system time in time_spec_t format. + * Uses the highest precision clock available. + * \return the system time as a time_spec_t + */ + static time_spec_t get_system_time(void); + + /*! + * Copy constructor + */ + time_spec_t(const time_spec_t & spec); + + /*! + * Create a time_spec_t from a real-valued seconds count. + * \param secs the real-valued seconds count (default = 0) + */ + time_spec_t(double secs = 0); + + /*! + * Create a time_spec_t from whole and fractional seconds. + * \param full_secs the whole/integer seconds count + * \param frac_secs the fractional seconds count (default = 0) + */ + time_spec_t(time_t full_secs, double frac_secs = 0); + + /*! + * Create a time_spec_t from whole seconds and fractional ticks. + * Translation from clock-domain specific units. + * \param full_secs the whole/integer seconds count + * \param tick_count the fractional seconds tick count + * \param tick_rate the number of ticks per second + */ + time_spec_t(time_t full_secs, long tick_count, double tick_rate); + + /*! + * Create a time_spec_t from a 64-bit tick count. + * Translation from clock-domain specific units. + * \param ticks an integer count of ticks + * \param tick_rate the number of ticks per second + */ + static time_spec_t from_ticks(long long ticks, double tick_rate); + + /*! + * Convert the fractional seconds to clock ticks. + * Translation into clock-domain specific units. + * \param tick_rate the number of ticks per second + * \return the fractional seconds tick count + */ + long get_tick_count(double tick_rate) const; + + /*! + * Convert the time spec into a 64-bit tick count. + * Translation into clock-domain specific units. + * \param tick_rate the number of ticks per second + * \return an integer number of ticks + */ + long long to_ticks(const double tick_rate) const; + + /*! + * Get the time as a real-valued seconds count. + * Note: If this time_spec_t represents an absolute time, + * the precision of the fractional seconds may be lost. + * \return the real-valued seconds + */ + double get_real_secs(void) const; + + /*! + * Get the whole/integer part of the time in seconds. + * \return the whole/integer seconds + */ + time_t get_full_secs(void) const; + + /*! + * Get the fractional part of the time in seconds. + * \return the fractional seconds + */ + double get_frac_secs(void) const; + + //! Implement addable interface + time_spec_t &operator+=(const time_spec_t &); + + //! Implement subtractable interface + time_spec_t &operator-=(const time_spec_t &); + + //private time storage details + private: time_t _full_secs; double _frac_secs; + }; + + //! Implement equality_comparable interface + bool operator==(const time_spec_t &, const time_spec_t &); + + //! Implement less_than_comparable interface + bool operator<(const time_spec_t &, const time_spec_t &); + + inline time_t time_spec_t::get_full_secs(void) const{ + return this->_full_secs; + } + + inline double time_spec_t::get_frac_secs(void) const{ + return this->_frac_secs; + } + + } //namespace transceiver +} //namespace gr + +#endif /* INCLUDED_TYPES_TIME_SPEC_HPP */ diff --git a/lib/misc_utils/CMakeLists.txt b/lib/misc_utils/CMakeLists.txt index 8597553..81f2ca8 100644 --- a/lib/misc_utils/CMakeLists.txt +++ b/lib/misc_utils/CMakeLists.txt @@ -32,6 +32,7 @@ add_sources( message_printer_impl.cc msg_to_tag_impl.cc tmsi_dumper_impl.cc + time_spec.cc fn_time.cc ) diff --git a/lib/misc_utils/fn_time.cc b/lib/misc_utils/fn_time.cc index 5248211..25c8e65 100644 --- a/lib/misc_utils/fn_time.cc +++ b/lib/misc_utils/fn_time.cc @@ -23,7 +23,6 @@ #include #include -#include #define GSM_HYPER_FRAME 26 * 51 * 2048 #define GSM_SYM_RATE 13.0e6 / 48.0 @@ -33,7 +32,6 @@ namespace gr { namespace gsm { - using namespace uhd; /** * Computes difference between two frame numbers modulo * GSM_HYPER_FRAME / 2. The result is correct if difference @@ -79,7 +77,7 @@ namespace gr { * frame numbers * @return difference between fn_ref and fn */ - time_spec_t fn_time_delta(uint32_t fn_ref, time_spec_t time_ref, uint32_t fn_x, + time_spec_t fn_time_delta2(uint32_t fn_ref, time_spec_t time_ref, uint32_t fn_x, time_spec_t time_hint, uint32_t ts_num, uint32_t ts_ref) { time_spec_t time_diff_hint = time_hint - time_ref; diff --git a/lib/misc_utils/time_spec.cc b/lib/misc_utils/time_spec.cc new file mode 100644 index 0000000..205508d --- /dev/null +++ b/lib/misc_utils/time_spec.cc @@ -0,0 +1,170 @@ +// +// Copyright 2011-2013 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "time_spec.h" + +namespace gr { + namespace gsm { + + /*********************************************************************** + * Time spec system time + **********************************************************************/ + + #ifdef HAVE_CLOCK_GETTIME + #include + time_spec_t time_spec_t::get_system_time(void){ + timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); + return time_spec_t(ts.tv_sec, ts.tv_nsec, 1e9); + } + #endif /* HAVE_CLOCK_GETTIME */ + + + #ifdef HAVE_MACH_ABSOLUTE_TIME + #include + time_spec_t time_spec_t::get_system_time(void){ + mach_timebase_info_data_t info; mach_timebase_info(&info); + intmax_t nanosecs = mach_absolute_time()*info.numer/info.denom; + return time_spec_t::from_ticks(nanosecs, 1e9); + } + #endif /* HAVE_MACH_ABSOLUTE_TIME */ + + + #ifdef HAVE_QUERY_PERFORMANCE_COUNTER + #include + time_spec_t time_spec_t::get_system_time(void){ + LARGE_INTEGER counts, freq; + QueryPerformanceCounter(&counts); + QueryPerformanceFrequency(&freq); + return time_spec_t::from_ticks(counts.QuadPart, double(freq.QuadPart)); + } + #endif /* HAVE_QUERY_PERFORMANCE_COUNTER */ + + + #ifdef HAVE_MICROSEC_CLOCK + #include + namespace pt = boost::posix_time; + time_spec_t time_spec_t::get_system_time(void){ + pt::ptime time_now = pt::microsec_clock::universal_time(); + pt::time_duration time_dur = time_now - pt::from_time_t(0); + return time_spec_t( + time_t(time_dur.total_seconds()), + long(time_dur.fractional_seconds()), + double(pt::time_duration::ticks_per_second()) + ); + } + #endif /* HAVE_MICROSEC_CLOCK */ + + /*********************************************************************** + * Time spec constructors + **********************************************************************/ + #define time_spec_init(full, frac) { \ + const time_t _full = time_t(full); \ + const double _frac = double(frac); \ + const int _frac_int = int(_frac); \ + _full_secs = _full + _frac_int; \ + _frac_secs = _frac - _frac_int; \ + if (_frac_secs < 0) {\ + _full_secs -= 1; \ + _frac_secs += 1; \ + } \ + } + + inline long long fast_llround(const double x){ + return (long long)(x + 0.5); // assumption of non-negativity + } + + time_spec_t::time_spec_t(const time_spec_t & spec){ + time_spec_init(spec.get_full_secs(), spec.get_frac_secs()); + } + + time_spec_t::time_spec_t(double secs){ + time_spec_init(0, secs); + } + + time_spec_t::time_spec_t(time_t full_secs, double frac_secs){ + time_spec_init(full_secs, frac_secs); + } + + time_spec_t::time_spec_t(time_t full_secs, long tick_count, double tick_rate){ + const double frac_secs = tick_count/tick_rate; + time_spec_init(full_secs, frac_secs); + } + + time_spec_t time_spec_t::from_ticks(long long ticks, double tick_rate){ + const long long rate_i = (long long)(tick_rate); + const double rate_f = tick_rate - rate_i; + const time_t secs_full = time_t(ticks/rate_i); + const long long ticks_error = ticks - (secs_full*rate_i); + const double ticks_frac = ticks_error - secs_full*rate_f; + return time_spec_t(secs_full, ticks_frac/tick_rate); + } + + /*********************************************************************** + * Time spec accessors + **********************************************************************/ + long time_spec_t::get_tick_count(double tick_rate) const{ + return long(fast_llround(this->get_frac_secs()*tick_rate)); + } + + long long time_spec_t::to_ticks(double tick_rate) const{ + const long long rate_i = (long long)(tick_rate); + const double rate_f = tick_rate - rate_i; + const long long ticks_full = this->get_full_secs()*rate_i; + const double ticks_error = this->get_full_secs()*rate_f; + const double ticks_frac = this->get_frac_secs()*tick_rate; + return ticks_full + fast_llround(ticks_error + ticks_frac); + } + + double time_spec_t::get_real_secs(void) const{ + return this->get_full_secs() + this->get_frac_secs(); + } + + /*********************************************************************** + * Time spec math overloads + **********************************************************************/ + time_spec_t &time_spec_t::operator+=(const time_spec_t &rhs){ + time_spec_init( + this->get_full_secs() + rhs.get_full_secs(), + this->get_frac_secs() + rhs.get_frac_secs() + ); + return *this; + } + + time_spec_t &time_spec_t::operator-=(const time_spec_t &rhs){ + time_spec_init( + this->get_full_secs() - rhs.get_full_secs(), + this->get_frac_secs() - rhs.get_frac_secs() + ); + return *this; + } + + bool operator==(const time_spec_t &lhs, const time_spec_t &rhs){ + return + lhs.get_full_secs() == rhs.get_full_secs() and + lhs.get_frac_secs() == rhs.get_frac_secs() + ; + } + + bool operator<(const time_spec_t &lhs, const time_spec_t &rhs){ + return ( + (lhs.get_full_secs() < rhs.get_full_secs()) or ( + (lhs.get_full_secs() == rhs.get_full_secs()) and + (lhs.get_frac_secs() < rhs.get_frac_secs()) + )); + } + } +} diff --git a/lib/receiver/CMakeLists.txt b/lib/receiver/CMakeLists.txt index 1c5fd53..123eba5 100644 --- a/lib/receiver/CMakeLists.txt +++ b/lib/receiver/CMakeLists.txt @@ -23,6 +23,5 @@ add_sources( receiver_config.cc receiver_impl.cc viterbi_detector.cc - time_spec.cc time_sample_ref.cc ) diff --git a/lib/receiver/time_sample_ref.h b/lib/receiver/time_sample_ref.h index 1fecb81..793944d 100644 --- a/lib/receiver/time_sample_ref.h +++ b/lib/receiver/time_sample_ref.h @@ -24,7 +24,7 @@ #define INCLUDED_TIME_SAMPLE_REF_IMPL_H #include -#include "time_spec.h" +#include namespace gr { namespace gsm { diff --git a/lib/receiver/time_spec.cc b/lib/receiver/time_spec.cc deleted file mode 100644 index 205508d..0000000 --- a/lib/receiver/time_spec.cc +++ /dev/null @@ -1,170 +0,0 @@ -// -// Copyright 2011-2013 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include "time_spec.h" - -namespace gr { - namespace gsm { - - /*********************************************************************** - * Time spec system time - **********************************************************************/ - - #ifdef HAVE_CLOCK_GETTIME - #include - time_spec_t time_spec_t::get_system_time(void){ - timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); - return time_spec_t(ts.tv_sec, ts.tv_nsec, 1e9); - } - #endif /* HAVE_CLOCK_GETTIME */ - - - #ifdef HAVE_MACH_ABSOLUTE_TIME - #include - time_spec_t time_spec_t::get_system_time(void){ - mach_timebase_info_data_t info; mach_timebase_info(&info); - intmax_t nanosecs = mach_absolute_time()*info.numer/info.denom; - return time_spec_t::from_ticks(nanosecs, 1e9); - } - #endif /* HAVE_MACH_ABSOLUTE_TIME */ - - - #ifdef HAVE_QUERY_PERFORMANCE_COUNTER - #include - time_spec_t time_spec_t::get_system_time(void){ - LARGE_INTEGER counts, freq; - QueryPerformanceCounter(&counts); - QueryPerformanceFrequency(&freq); - return time_spec_t::from_ticks(counts.QuadPart, double(freq.QuadPart)); - } - #endif /* HAVE_QUERY_PERFORMANCE_COUNTER */ - - - #ifdef HAVE_MICROSEC_CLOCK - #include - namespace pt = boost::posix_time; - time_spec_t time_spec_t::get_system_time(void){ - pt::ptime time_now = pt::microsec_clock::universal_time(); - pt::time_duration time_dur = time_now - pt::from_time_t(0); - return time_spec_t( - time_t(time_dur.total_seconds()), - long(time_dur.fractional_seconds()), - double(pt::time_duration::ticks_per_second()) - ); - } - #endif /* HAVE_MICROSEC_CLOCK */ - - /*********************************************************************** - * Time spec constructors - **********************************************************************/ - #define time_spec_init(full, frac) { \ - const time_t _full = time_t(full); \ - const double _frac = double(frac); \ - const int _frac_int = int(_frac); \ - _full_secs = _full + _frac_int; \ - _frac_secs = _frac - _frac_int; \ - if (_frac_secs < 0) {\ - _full_secs -= 1; \ - _frac_secs += 1; \ - } \ - } - - inline long long fast_llround(const double x){ - return (long long)(x + 0.5); // assumption of non-negativity - } - - time_spec_t::time_spec_t(const time_spec_t & spec){ - time_spec_init(spec.get_full_secs(), spec.get_frac_secs()); - } - - time_spec_t::time_spec_t(double secs){ - time_spec_init(0, secs); - } - - time_spec_t::time_spec_t(time_t full_secs, double frac_secs){ - time_spec_init(full_secs, frac_secs); - } - - time_spec_t::time_spec_t(time_t full_secs, long tick_count, double tick_rate){ - const double frac_secs = tick_count/tick_rate; - time_spec_init(full_secs, frac_secs); - } - - time_spec_t time_spec_t::from_ticks(long long ticks, double tick_rate){ - const long long rate_i = (long long)(tick_rate); - const double rate_f = tick_rate - rate_i; - const time_t secs_full = time_t(ticks/rate_i); - const long long ticks_error = ticks - (secs_full*rate_i); - const double ticks_frac = ticks_error - secs_full*rate_f; - return time_spec_t(secs_full, ticks_frac/tick_rate); - } - - /*********************************************************************** - * Time spec accessors - **********************************************************************/ - long time_spec_t::get_tick_count(double tick_rate) const{ - return long(fast_llround(this->get_frac_secs()*tick_rate)); - } - - long long time_spec_t::to_ticks(double tick_rate) const{ - const long long rate_i = (long long)(tick_rate); - const double rate_f = tick_rate - rate_i; - const long long ticks_full = this->get_full_secs()*rate_i; - const double ticks_error = this->get_full_secs()*rate_f; - const double ticks_frac = this->get_frac_secs()*tick_rate; - return ticks_full + fast_llround(ticks_error + ticks_frac); - } - - double time_spec_t::get_real_secs(void) const{ - return this->get_full_secs() + this->get_frac_secs(); - } - - /*********************************************************************** - * Time spec math overloads - **********************************************************************/ - time_spec_t &time_spec_t::operator+=(const time_spec_t &rhs){ - time_spec_init( - this->get_full_secs() + rhs.get_full_secs(), - this->get_frac_secs() + rhs.get_frac_secs() - ); - return *this; - } - - time_spec_t &time_spec_t::operator-=(const time_spec_t &rhs){ - time_spec_init( - this->get_full_secs() - rhs.get_full_secs(), - this->get_frac_secs() - rhs.get_frac_secs() - ); - return *this; - } - - bool operator==(const time_spec_t &lhs, const time_spec_t &rhs){ - return - lhs.get_full_secs() == rhs.get_full_secs() and - lhs.get_frac_secs() == rhs.get_frac_secs() - ; - } - - bool operator<(const time_spec_t &lhs, const time_spec_t &rhs){ - return ( - (lhs.get_full_secs() < rhs.get_full_secs()) or ( - (lhs.get_full_secs() == rhs.get_full_secs()) and - (lhs.get_frac_secs() < rhs.get_frac_secs()) - )); - } - } -} diff --git a/lib/receiver/time_spec.h b/lib/receiver/time_spec.h deleted file mode 100644 index cc7f104..0000000 --- a/lib/receiver/time_spec.h +++ /dev/null @@ -1,147 +0,0 @@ -// -// Copyright 2010-2012 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef INCLUDED_TYPES_TIME_SPEC_HPP -#define INCLUDED_TYPES_TIME_SPEC_HPP - -#include -#include - -namespace gr { - namespace gsm { - - /*! - * A time_spec_t holds a seconds and a fractional seconds time value. - * Depending upon usage, the time_spec_t can represent absolute times, - * relative times, or time differences (between absolute times). - * - * The time_spec_t provides clock-domain independent time storage, - * but can convert fractional seconds to/from clock-domain specific units. - * - * The fractional seconds are stored as double precision floating point. - * This gives the fractional seconds enough precision to unambiguously - * specify a clock-tick/sample-count up to rates of several petahertz. - */ - class time_spec_t : boost::additive, boost::totally_ordered{ - public: - - /*! - * Get the system time in time_spec_t format. - * Uses the highest precision clock available. - * \return the system time as a time_spec_t - */ - static time_spec_t get_system_time(void); - - /*! - * Copy constructor - */ - time_spec_t(const time_spec_t & spec); - - /*! - * Create a time_spec_t from a real-valued seconds count. - * \param secs the real-valued seconds count (default = 0) - */ - time_spec_t(double secs = 0); - - /*! - * Create a time_spec_t from whole and fractional seconds. - * \param full_secs the whole/integer seconds count - * \param frac_secs the fractional seconds count (default = 0) - */ - time_spec_t(time_t full_secs, double frac_secs = 0); - - /*! - * Create a time_spec_t from whole seconds and fractional ticks. - * Translation from clock-domain specific units. - * \param full_secs the whole/integer seconds count - * \param tick_count the fractional seconds tick count - * \param tick_rate the number of ticks per second - */ - time_spec_t(time_t full_secs, long tick_count, double tick_rate); - - /*! - * Create a time_spec_t from a 64-bit tick count. - * Translation from clock-domain specific units. - * \param ticks an integer count of ticks - * \param tick_rate the number of ticks per second - */ - static time_spec_t from_ticks(long long ticks, double tick_rate); - - /*! - * Convert the fractional seconds to clock ticks. - * Translation into clock-domain specific units. - * \param tick_rate the number of ticks per second - * \return the fractional seconds tick count - */ - long get_tick_count(double tick_rate) const; - - /*! - * Convert the time spec into a 64-bit tick count. - * Translation into clock-domain specific units. - * \param tick_rate the number of ticks per second - * \return an integer number of ticks - */ - long long to_ticks(const double tick_rate) const; - - /*! - * Get the time as a real-valued seconds count. - * Note: If this time_spec_t represents an absolute time, - * the precision of the fractional seconds may be lost. - * \return the real-valued seconds - */ - double get_real_secs(void) const; - - /*! - * Get the whole/integer part of the time in seconds. - * \return the whole/integer seconds - */ - time_t get_full_secs(void) const; - - /*! - * Get the fractional part of the time in seconds. - * \return the fractional seconds - */ - double get_frac_secs(void) const; - - //! Implement addable interface - time_spec_t &operator+=(const time_spec_t &); - - //! Implement subtractable interface - time_spec_t &operator-=(const time_spec_t &); - - //private time storage details - private: time_t _full_secs; double _frac_secs; - }; - - //! Implement equality_comparable interface - bool operator==(const time_spec_t &, const time_spec_t &); - - //! Implement less_than_comparable interface - bool operator<(const time_spec_t &, const time_spec_t &); - - inline time_t time_spec_t::get_full_secs(void) const{ - return this->_full_secs; - } - - inline double time_spec_t::get_frac_secs(void) const{ - return this->_frac_secs; - } - - } //namespace transceiver -} //namespace gr - -#endif /* INCLUDED_TYPES_TIME_SPEC_HPP */ diff --git a/python/misc_utils/CMakeLists.txt b/python/misc_utils/CMakeLists.txt index 1accda9..ec732a4 100644 --- a/python/misc_utils/CMakeLists.txt +++ b/python/misc_utils/CMakeLists.txt @@ -22,5 +22,6 @@ GR_PYTHON_INSTALL( arfcn.py clock_offset_corrector_tagged.py hier_block.py - fn_time.py DESTINATION ${GR_PYTHON_DIR}/grgsm + fn_time.py + DESTINATION ${GR_PYTHON_DIR}/grgsm ) diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i index 08d95f1..d5132dc 100644 --- a/swig/grgsm_swig.i +++ b/swig/grgsm_swig.i @@ -65,6 +65,7 @@ #include "grgsm/misc_utils/msg_to_tag.h" #include "grgsm/misc_utils/controlled_fractional_resampler_cc.h" #include "grgsm/trx_interface/trx.h" +#include "grgsm/misc_utils/time_spec.h" #include "grgsm/misc_utils/fn_time.h" %} @@ -147,4 +148,5 @@ GR_SWIG_BLOCK_MAGIC2(gsm, message_source); GR_SWIG_BLOCK_MAGIC2(gsm, message_sink); %include "grgsm/trx_interface/trx.h" GR_SWIG_BLOCK_MAGIC2(grgsm, trx); -%include "grgsm/misc_utils/fn_time.h" +//%include "grgsm/misc_utils/time_spec.h" +//%include "grgsm/misc_utils/fn_time.h" -- cgit v1.2.3 From 8926c1f621a1244d958a169fa5972eac61ede30e Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Tue, 31 Oct 2017 13:01:43 +0100 Subject: Correction in time_spec.cc --- lib/misc_utils/time_spec.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/misc_utils/time_spec.cc b/lib/misc_utils/time_spec.cc index 205508d..39b0a86 100644 --- a/lib/misc_utils/time_spec.cc +++ b/lib/misc_utils/time_spec.cc @@ -15,7 +15,7 @@ // along with this program. If not, see . // -#include "time_spec.h" +#include namespace gr { namespace gsm { -- cgit v1.2.3 From 6e41d06bbfa897f6287ea14ee473683aa3576f5a Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Fri, 3 Nov 2017 09:56:49 +0100 Subject: Corrections in fn_time --- include/grgsm/misc_utils/fn_time.h | 12 ++++--- lib/misc_utils/fn_time.cc | 67 +++++++++++++++++--------------------- python/misc_utils/fn_time.py | 20 +++++++----- swig/grgsm_swig.i | 7 ++-- 4 files changed, 54 insertions(+), 52 deletions(-) diff --git a/include/grgsm/misc_utils/fn_time.h b/include/grgsm/misc_utils/fn_time.h index 560ee4a..b26c21b 100644 --- a/include/grgsm/misc_utils/fn_time.h +++ b/include/grgsm/misc_utils/fn_time.h @@ -1,6 +1,7 @@ /* -*- c++ -*- */ /* @file * @author Piotr Krysik + * @author Vadim Yanitskiy * @section LICENSE * * Gr-gsm is free software; you can redistribute it and/or modify @@ -24,8 +25,9 @@ #ifndef INCLUDED_GRGSM_FN_TIME_H #define INCLUDED_GRGSM_FN_TIME_H +#include #include -#include +#include namespace gr { namespace gsm { @@ -41,10 +43,12 @@ namespace gr { * frame numbers * @return difference between fn_ref and fn */ - time_spec_t fn_time_delta2(uint32_t fn_ref, time_spec_t time_ref, uint32_t fn_x, - time_spec_t time_hint, uint32_t ts_num, uint32_t ts_ref); + typedef std::pair time_format; + + GRGSM_API time_format fn_time_delta_cpp(uint32_t fn_ref, time_format time_ref, uint32_t fn_x, + time_format time_hint, uint32_t ts_num, uint32_t ts_ref); - } // namespace grgsm + } // namespace gsm } // namespace gr #endif /* INCLUDED_GRGSM_FN_TIME_H */ diff --git a/lib/misc_utils/fn_time.cc b/lib/misc_utils/fn_time.cc index 25c8e65..2773f33 100644 --- a/lib/misc_utils/fn_time.cc +++ b/lib/misc_utils/fn_time.cc @@ -22,35 +22,38 @@ */ #include +#include #include -#define GSM_HYPER_FRAME 26 * 51 * 2048 -#define GSM_SYM_RATE 13.0e6 / 48.0 +#define GSM_HYPER_FRAME (26 * 51 * 2048) +#define GSM_SYM_RATE (13.0e6 / 48.0) -#define GSM_TS_PERIOD 156.25 / GSM_SYM_RATE -#define GSM_FN_PERIOD 8 * GSM_TS_PERIOD +#define GSM_TS_PERIOD (156.25 / GSM_SYM_RATE) +#define GSM_FN_PERIOD (8 * GSM_TS_PERIOD) namespace gr { namespace gsm { - /** - * Computes difference between two frame numbers modulo - * GSM_HYPER_FRAME / 2. The result is correct if difference - * between the frame numbers is not bigger than GSM_HYPER_FRAME / 2. - * @param fn1 first frame number - * @param fn2 second frame number - * @return computed difference - */ - static uint32_t fnmod_delta(uint32_t fn1, uint32_t fn2) + /** + * Computes difference between two frame numbers modulo + * GSM_HYPER_FRAME / 2. The result is correct if difference + * between the frame numbers is not bigger than GSM_HYPER_FRAME / 2. + * @param fn1 first frame number + * @param fn2 second frame number + * @return computed difference + */ + static int fnmod_delta(uint32_t fn1, uint32_t fn2) { - uint32_t delta, h2; + int delta, h2; delta = (fn1 % GSM_HYPER_FRAME) - (fn2 % GSM_HYPER_FRAME); + h2 = GSM_HYPER_FRAME / 2; - if (delta >= h2) - delta -= GSM_HYPER_FRAME; - else - delta += GSM_HYPER_FRAME; + if (delta >= h2) { + delta -= GSM_HYPER_FRAME; + } else if(delta < -h2) { + delta += GSM_HYPER_FRAME; + } return delta; } @@ -59,7 +62,6 @@ namespace gr { time_spec_t time_diff_hint) { int frames_diff, fn_delta; - frames_diff = int(round(time_diff_hint.get_real_secs() / GSM_FN_PERIOD)); fn_delta = fnmod_delta(fn, fn_ref + frames_diff) + frames_diff; @@ -77,27 +79,16 @@ namespace gr { * frame numbers * @return difference between fn_ref and fn */ - time_spec_t fn_time_delta2(uint32_t fn_ref, time_spec_t time_ref, uint32_t fn_x, - time_spec_t time_hint, uint32_t ts_num, uint32_t ts_ref) + time_format fn_time_delta_cpp(uint32_t fn_ref, time_format time_ref, uint32_t fn_x, + time_format time_hint, uint32_t ts_num, uint32_t ts_ref) { - time_spec_t time_diff_hint = time_hint - time_ref; - uint32_t fn_delta = fn_time_diff_delta(fn_x,fn_ref, time_diff_hint); - time_spec_t time_x_precise = fn_delta * GSM_FN_PERIOD - + time_ref + (ts_num - ts_ref) * GSM_TS_PERIOD; - - return time_x_precise; + time_spec_t time_diff_hint = time_spec_t(time_hint.first, time_hint.second) - time_spec_t(time_ref.first, time_ref.second); + int fn_delta = fn_time_diff_delta(fn_x, fn_ref, time_diff_hint); + time_spec_t time_x_precise = fn_delta * GSM_FN_PERIOD + time_spec_t(time_ref.first, time_ref.second) + (static_cast(ts_num) - static_cast(ts_ref)) * GSM_TS_PERIOD; + + return time_format(time_x_precise.get_full_secs(), time_x_precise.get_frac_secs()); } -/* - def fn_time_delta(fn_ref, time_ref, fn_x, time_hint=None, ts_num=0, ts_ref=0): - if time_hint is None: - time_hint = time_ref - - time_diff_hint = time_hint-time_ref - fn_delta = fn_time_diff_delta(fn_x,fn_ref, time_diff_hint) - time_x_precise = fn_delta*__frame_period+time_ref+(ts_num-ts_ref)*__ts_period - - return fn_delta, time_x_precise -*/ + } /* namespace gsm */ } /* namespace gr */ diff --git a/python/misc_utils/fn_time.py b/python/misc_utils/fn_time.py index cf03681..96314b8 100644 --- a/python/misc_utils/fn_time.py +++ b/python/misc_utils/fn_time.py @@ -22,6 +22,7 @@ # from math import floor, ceil from random import uniform +from grgsm import fn_time_delta_cpp __hyper_frame = 26*51*2048 __symb_rate = 13.0e6/48.0 @@ -37,7 +38,7 @@ __frame_period = 8*__ts_period def fnmod_delta(fn1, fn2): h2 = __hyper_frame/2 delta = (fn1%__hyper_frame)-(fn2%__hyper_frame) - + if delta >= h2: delta = delta - __hyper_frame elif delta < -h2: @@ -49,7 +50,7 @@ def fn_time_diff_delta(fn_x, fn_ref, time_diff_hint=0): frames_diff = int(round(time_diff_hint/__frame_period)) fn_ref_hint = (fn_ref + frames_diff) fn_delta = fnmod_delta(fn_x,fn_ref_hint)+frames_diff - + return fn_delta #fn_time_delta computes difference between reference frame number and a second frame number. It also computes timestamp of the second frame number. The full list of parameters is following: @@ -73,16 +74,19 @@ def fn_time_delta(fn_ref, time_ref, fn_x, time_hint=None, ts_num=0, ts_ref=0): if __name__ == "__main__": fn1 = 10000 ts_ref = 4 - time1 = 10 - for fn2 in xrange(__hyper_frame/2+fn1-10,__hyper_frame/2*10+fn1+10,10): + time1 = 10.5 + for fn2 in xrange(__hyper_frame/2+fn1-10,__hyper_frame/2*10+fn1+100,10): ts_x = int(uniform(0,8)) - time2 = time1 + (fn2-fn1)*__frame_period + (ts_ref-ts_x)*__ts_period + time2 = time1 + (fn2-fn1)*__frame_period + (ts_x-ts_ref)*__ts_period error = uniform(-6200,6200) time2_err = time2+error fn_delta, time2_precise = fn_time_delta(fn1, time1, fn2, time2_err, ts_x, ts_ref) + time2_precise_cpp = fn_time_delta_cpp(fn1, (int(time1),time1-int(time1)), fn2, (int(time2_err),time2_err-int(time2_err)), ts_x, ts_ref) if fn_delta != fn2-fn1: print "bad fn:", fn2, error#, 'fn_delta:'+str(fn_delta), time2, error, frames_diff_h4, (time2-time1)/(__hyper_frame*__frame_period), time_diff_hint_h4_prev, time_diff_hint - time_diff_hint = time2 - time2_precise - if time_diff_hint > 0.0001: - print "bad time diff" +# time_diff_hint = time2 - time2_precise + time_diff_hint = time2_precise_cpp[0]+time2_precise_cpp[1] - time2_precise + if abs(time_diff_hint) > 0.0001: + print "time2_precise_cpp",time2_precise_cpp," time2_precise",time2_precise," time_ref",time1," time_hint",time2_err + print "" diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i index d5132dc..56e988d 100644 --- a/swig/grgsm_swig.i +++ b/swig/grgsm_swig.i @@ -23,6 +23,9 @@ #define GRGSM_API +%include +%template(pairud) std::pair; + %include "gnuradio.i" // the common stuff //load generated python docstrings @@ -65,7 +68,7 @@ #include "grgsm/misc_utils/msg_to_tag.h" #include "grgsm/misc_utils/controlled_fractional_resampler_cc.h" #include "grgsm/trx_interface/trx.h" -#include "grgsm/misc_utils/time_spec.h" +//#include "grgsm/misc_utils/time_spec.h" #include "grgsm/misc_utils/fn_time.h" %} @@ -149,4 +152,4 @@ GR_SWIG_BLOCK_MAGIC2(gsm, message_sink); %include "grgsm/trx_interface/trx.h" GR_SWIG_BLOCK_MAGIC2(grgsm, trx); //%include "grgsm/misc_utils/time_spec.h" -//%include "grgsm/misc_utils/fn_time.h" +%include "grgsm/misc_utils/fn_time.h" -- cgit v1.2.3 From d32ba5b47170c6f3b49815e8e9ea1c9c3054d7a9 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Fri, 3 Nov 2017 09:58:13 +0100 Subject: Removed unused (and problematic during SWIG) part of time_spec_t and exposed time_spec_t in the library's ABI --- include/grgsm/misc_utils/time_spec.h | 10 ++------ lib/misc_utils/time_spec.cc | 48 ------------------------------------ swig/grgsm_swig.i | 22 +++++++++++++++++ 3 files changed, 24 insertions(+), 56 deletions(-) diff --git a/include/grgsm/misc_utils/time_spec.h b/include/grgsm/misc_utils/time_spec.h index cc7f104..6ae5963 100644 --- a/include/grgsm/misc_utils/time_spec.h +++ b/include/grgsm/misc_utils/time_spec.h @@ -18,6 +18,7 @@ #ifndef INCLUDED_TYPES_TIME_SPEC_HPP #define INCLUDED_TYPES_TIME_SPEC_HPP +#include #include #include @@ -36,16 +37,9 @@ namespace gr { * This gives the fractional seconds enough precision to unambiguously * specify a clock-tick/sample-count up to rates of several petahertz. */ - class time_spec_t : boost::additive, boost::totally_ordered{ + class GRGSM_API time_spec_t : boost::additive, boost::totally_ordered{ public: - /*! - * Get the system time in time_spec_t format. - * Uses the highest precision clock available. - * \return the system time as a time_spec_t - */ - static time_spec_t get_system_time(void); - /*! * Copy constructor */ diff --git a/lib/misc_utils/time_spec.cc b/lib/misc_utils/time_spec.cc index 39b0a86..5293da2 100644 --- a/lib/misc_utils/time_spec.cc +++ b/lib/misc_utils/time_spec.cc @@ -20,54 +20,6 @@ namespace gr { namespace gsm { - /*********************************************************************** - * Time spec system time - **********************************************************************/ - - #ifdef HAVE_CLOCK_GETTIME - #include - time_spec_t time_spec_t::get_system_time(void){ - timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); - return time_spec_t(ts.tv_sec, ts.tv_nsec, 1e9); - } - #endif /* HAVE_CLOCK_GETTIME */ - - - #ifdef HAVE_MACH_ABSOLUTE_TIME - #include - time_spec_t time_spec_t::get_system_time(void){ - mach_timebase_info_data_t info; mach_timebase_info(&info); - intmax_t nanosecs = mach_absolute_time()*info.numer/info.denom; - return time_spec_t::from_ticks(nanosecs, 1e9); - } - #endif /* HAVE_MACH_ABSOLUTE_TIME */ - - - #ifdef HAVE_QUERY_PERFORMANCE_COUNTER - #include - time_spec_t time_spec_t::get_system_time(void){ - LARGE_INTEGER counts, freq; - QueryPerformanceCounter(&counts); - QueryPerformanceFrequency(&freq); - return time_spec_t::from_ticks(counts.QuadPart, double(freq.QuadPart)); - } - #endif /* HAVE_QUERY_PERFORMANCE_COUNTER */ - - - #ifdef HAVE_MICROSEC_CLOCK - #include - namespace pt = boost::posix_time; - time_spec_t time_spec_t::get_system_time(void){ - pt::ptime time_now = pt::microsec_clock::universal_time(); - pt::time_duration time_dur = time_now - pt::from_time_t(0); - return time_spec_t( - time_t(time_dur.total_seconds()), - long(time_dur.fractional_seconds()), - double(pt::time_duration::ticks_per_second()) - ); - } - #endif /* HAVE_MICROSEC_CLOCK */ - /*********************************************************************** * Time spec constructors **********************************************************************/ diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i index 56e988d..2743e80 100644 --- a/swig/grgsm_swig.i +++ b/swig/grgsm_swig.i @@ -151,5 +151,27 @@ GR_SWIG_BLOCK_MAGIC2(gsm, message_source); GR_SWIG_BLOCK_MAGIC2(gsm, message_sink); %include "grgsm/trx_interface/trx.h" GR_SWIG_BLOCK_MAGIC2(grgsm, trx); + +//#pragma SWIG nowarn=319 //%include "grgsm/misc_utils/time_spec.h" + +//%extend gr::gsm::time_spec_t{ +// gr::gsm::time_spec_t __add__(const gr::gsm::time_spec_t &what) +// { +// gr::gsm::time_spec_t temp = *self; +// temp += what; +// return temp; +// } +// gr::gsm::time_spec_t __sub__(const gr::gsm::time_spec_t &what) +// { +// gr::gsm::time_spec_t temp = *self; +// temp -= what; +// return temp; +// } +// bool __eq__(const gr::gsm::time_spec_t &what) +// { +// return (what == *self); +// } +//}; + %include "grgsm/misc_utils/fn_time.h" -- cgit v1.2.3 From 5f1185edd4f7cb3feb8bc7106c7a5417dd9c592d Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Fri, 3 Nov 2017 11:27:06 +0100 Subject: change just to invoke automatic tests on TravisCI --- lib/trx_interface/trx_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/trx_interface/trx_impl.h b/lib/trx_interface/trx_impl.h index 19e4848..d335922 100644 --- a/lib/trx_interface/trx_impl.h +++ b/lib/trx_interface/trx_impl.h @@ -22,7 +22,7 @@ #ifndef INCLUDED_GRGSM_TRX_IMPL_H #define INCLUDED_GRGSM_TRX_IMPL_H - + #include #include -- cgit v1.2.3 From 517464c0a9d410cccf5b4f7eb471dce9de58cff5 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Sun, 5 Nov 2017 12:23:15 +0100 Subject: Added txtime_setter block (a c++ version of txtime_bursts_tagger Python block) --- grc/gsm_block_tree.xml | 1 + grc/transmitter/CMakeLists.txt | 3 +- grc/transmitter/gsm_txtime_setter.xml | 84 ++++++++++++++++++ include/grgsm/CMakeLists.txt | 1 + include/grgsm/transmitter/txtime_setter.h | 62 +++++++++++++ lib/CMakeLists.txt | 1 + lib/transmitter/CMakeLists.txt | 22 +++++ lib/transmitter/txtime_setter_impl.cc | 139 ++++++++++++++++++++++++++++++ lib/transmitter/txtime_setter_impl.h | 60 +++++++++++++ python/CMakeLists.txt | 1 + python/qa_txtime_setter.py | 43 +++++++++ swig/grgsm_swig.i | 3 + 12 files changed, 419 insertions(+), 1 deletion(-) create mode 100644 grc/transmitter/gsm_txtime_setter.xml create mode 100644 include/grgsm/transmitter/txtime_setter.h create mode 100644 lib/transmitter/CMakeLists.txt create mode 100644 lib/transmitter/txtime_setter_impl.cc create mode 100644 lib/transmitter/txtime_setter_impl.h create mode 100755 python/qa_txtime_setter.py diff --git a/grc/gsm_block_tree.xml b/grc/gsm_block_tree.xml index ac3670e..ae41f4d 100644 --- a/grc/gsm_block_tree.xml +++ b/grc/gsm_block_tree.xml @@ -24,6 +24,7 @@ Transmitter gsm_txtime_bursts_tagger + gsm_txtime_setter gsm_gmsk_mod diff --git a/grc/transmitter/CMakeLists.txt b/grc/transmitter/CMakeLists.txt index c41f56a..e512d10 100644 --- a/grc/transmitter/CMakeLists.txt +++ b/grc/transmitter/CMakeLists.txt @@ -19,5 +19,6 @@ install(FILES gsm_gmsk_mod.xml - gsm_txtime_bursts_tagger.xml DESTINATION share/gnuradio/grc/blocks + gsm_txtime_bursts_tagger.xml + gsm_txtime_setter.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/transmitter/gsm_txtime_setter.xml b/grc/transmitter/gsm_txtime_setter.xml new file mode 100644 index 0000000..648f4d9 --- /dev/null +++ b/grc/transmitter/gsm_txtime_setter.xml @@ -0,0 +1,84 @@ + + + txtime_setter + gsm_txtime_setter + import grgsm + grgsm.txtime_setter($init_fn if ($init_fn is not None) else 0xffffffff, $init_time_secs, $init_time_fracs, $time_hint_secs, $time_hint_fracs, $timing_advance, $delay_correction) + + set_fn_time_reference($init_fn, $init_time_secs, $init_time_fracs) + set_time_hint($time_hint_secs, $time_hint_secs) + set_timing_advance($timing_advance) + set_delay_correction($delay_correction) + + + init_fn + init_fn + None + raw + part + + + + init_time_secs + init_time_secs + 0 + int + part + + + init_time_fracs + init_time_fracs + 0 + float + part + + + + time_hint_secs + time_hint_secs + 0 + int + part + + + time_hint_fracs + time_hint_fracs + 0 + float + part + + + + timing_advance + timing_advance + 0 + float + part + + + + delay_correction + delay_correction + 0 + float + part + + + + fn_time + message + 1 + + + + bursts_in + message + 1 + + + + bursts_out + message + 1 + + diff --git a/include/grgsm/CMakeLists.txt b/include/grgsm/CMakeLists.txt index 1ce9134..59034dc 100644 --- a/include/grgsm/CMakeLists.txt +++ b/include/grgsm/CMakeLists.txt @@ -35,4 +35,5 @@ add_subdirectory(receiver) add_subdirectory(misc_utils) add_subdirectory(qa_utils) add_subdirectory(flow_control) +add_subdirectory(transmitter) add_subdirectory(trx_interface) diff --git a/include/grgsm/transmitter/txtime_setter.h b/include/grgsm/transmitter/txtime_setter.h new file mode 100644 index 0000000..0bf0b03 --- /dev/null +++ b/include/grgsm/transmitter/txtime_setter.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* @file + * @author Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + + +#ifndef INCLUDED_GSM_TXTIME_SETTER_H +#define INCLUDED_GSM_TXTIME_SETTER_H + +#include +#include + +namespace gr { + namespace gsm { + + /*! + * \brief <+description of block+> + * \ingroup gsm + * + */ + class GRGSM_API txtime_setter : virtual public gr::block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of gsm::txtime_setter. + * + * To avoid accidental use of raw pointers, gsm::txtime_setter's + * constructor is in a private implementation + * class. gsm::txtime_setter::make is the public interface for + * creating new instances. + */ + static sptr make(uint32_t init_fn, uint64_t init_time_secs, double init_time_fracs, uint64_t time_hint_secs, double time_hint_fracs, double timing_advance, double delay_correction); + virtual void set_fn_time_reference(uint32_t fn, uint32_t ts, uint64_t time_secs, double time_fracs) = 0; + virtual void set_time_hint(uint64_t time_hint_secs, double time_hint_fracs) = 0; + virtual void set_delay_correction(double delay_correction) = 0; + virtual void set_timing_advance(double timing_advance) = 0; + }; + + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GSM_TXTIME_SETTER_H */ + diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 511d459..60758a1 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -70,6 +70,7 @@ add_subdirectory(flow_control) add_subdirectory(misc_utils) add_subdirectory(qa_utils) add_subdirectory(receiver) +add_subdirectory(transmitter) add_subdirectory(trx_interface) ######################################################################## diff --git a/lib/transmitter/CMakeLists.txt b/lib/transmitter/CMakeLists.txt new file mode 100644 index 0000000..31658fd --- /dev/null +++ b/lib/transmitter/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +add_sources( + txtime_setter_impl.cc +) diff --git a/lib/transmitter/txtime_setter_impl.cc b/lib/transmitter/txtime_setter_impl.cc new file mode 100644 index 0000000..9ff1d8a --- /dev/null +++ b/lib/transmitter/txtime_setter_impl.cc @@ -0,0 +1,139 @@ +/* -*- c++ -*- */ +/* @file + * @author Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "txtime_setter_impl.h" + +namespace gr { + namespace gsm { + + txtime_setter::sptr + txtime_setter::make(uint32_t init_fn, uint64_t init_time_secs, double init_time_fracs, uint64_t time_hint_secs, double time_hint_fracs, double timing_advance, double delay_correction) + { + return gnuradio::get_initial_sptr + (new txtime_setter_impl(init_fn, init_time_secs, init_time_fracs, time_hint_secs, time_hint_fracs, timing_advance, delay_correction)); + } + + /* + * The private constructor + */ + txtime_setter_impl::txtime_setter_impl(uint32_t init_fn, uint64_t init_time_secs, double init_time_fracs, uint64_t time_hint_secs, double time_hint_fracs, double timing_advance, double delay_correction) + : gr::block("txtime_setter", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), + d_fn_ref(init_fn), + d_ts_ref(0), + d_time_ref(init_time_secs,init_time_fracs), + d_time_hint(time_hint_secs,time_hint_fracs), + d_timing_advance(timing_advance), + d_delay_correction(delay_correction) + { + message_port_register_in(pmt::intern("fn_time")); + message_port_register_in(pmt::intern("bursts_in")); + message_port_register_out(pmt::intern("bursts_out")); + + set_msg_handler(pmt::intern("fn_time"), boost::bind(&txtime_setter_impl::process_fn_time_reference, this, _1)); + set_msg_handler(pmt::intern("bursts_in"), boost::bind(&txtime_setter_impl::process_txtime_of_burst, this, _1)); + } + + /* + * Our virtual destructor. + */ + txtime_setter_impl::~txtime_setter_impl() + { + } + + void txtime_setter_impl::process_fn_time_reference(pmt::pmt_t msg) + { +// d_time_hint = pmt::to_python(pmt::dict_ref(msg, pmt::intern("time_hint"), pmt::PMT_NIL)) + pmt::pmt_t not_found = pmt::intern("not_found"); + pmt::pmt_t fn_time = pmt::dict_ref(msg, pmt::intern("fn_time"), not_found); + pmt::pmt_t time_hint = pmt::dict_ref(msg, pmt::intern("fn_time"), not_found); + + if(fn_time != not_found) + { + uint32_t fn_ref = static_cast(pmt::to_uint64(pmt::car(pmt::car(fn_time)))); + uint32_t ts = static_cast(pmt::to_uint64(pmt::cdr(pmt::car(fn_time)))); + uint64_t time_secs = pmt::to_uint64(pmt::car(pmt::cdr(fn_time))); + double time_fracs = pmt::to_double(pmt::cdr(pmt::cdr(fn_time))); + set_fn_time_reference(fn_ref, ts, time_secs, time_fracs); + } else if(time_hint != not_found) { + set_time_hint(pmt::to_uint64(pmt::car(fn_time)), pmt::to_double(pmt::cdr(fn_time))); + } + + } + + void txtime_setter_impl::process_txtime_of_burst(pmt::pmt_t burst) + { + pmt::pmt_t header_plus_burst = pmt::cdr(burst); + int8_t * burst_int8 = (int8_t *)pmt::blob_data(header_plus_burst); + gsmtap_hdr * header = (gsmtap_hdr *)(burst_int8); + + uint32_t frame_nr = be32toh(header->frame_number); + uint32_t ts_num = header->timeslot; + + if(d_fn_ref != 0xffffffff) + { + time_format txtime = fn_time_delta_cpp(d_fn_ref, d_time_ref, frame_nr, d_time_hint, ts_num, d_ts_ref); + time_spec_t txtime_spec = time_spec_t(txtime.first, txtime.second); + txtime_spec = txtime_spec - d_delay_correction; + txtime_spec = txtime_spec - d_timing_advance; + + pmt::pmt_t tags_dict = pmt::dict_add(pmt::make_dict(), pmt::intern("tx_time"), pmt::make_tuple(pmt::from_uint64(txtime_spec.get_full_secs()),pmt::from_double(txtime_spec.get_frac_secs()))); + tags_dict = pmt::dict_add(tags_dict, pmt::intern("fn"), pmt::from_uint64(frame_nr)); + tags_dict = pmt::dict_add(tags_dict, pmt::intern("ts"), pmt::from_uint64(ts_num)); + pmt::pmt_t new_msg = pmt::cons(tags_dict, pmt::cdr(burst)); + message_port_pub(pmt::intern("bursts_out"), new_msg); + } + } + + void txtime_setter_impl::set_fn_time_reference(uint32_t fn, uint32_t ts, uint64_t time_secs, double time_fracs) + { + d_fn_ref = fn; + d_ts_ref = ts; + d_time_ref = std::make_pair(time_secs, time_fracs); + set_time_hint(time_secs, time_fracs); + } + + void txtime_setter_impl::set_time_hint(uint64_t time_hint_secs, double time_hint_fracs) + { + d_time_hint = std::make_pair(time_hint_secs, time_hint_fracs); + } + + void txtime_setter_impl::set_delay_correction(double delay_correction) + { + d_delay_correction = delay_correction; + } + + void txtime_setter_impl::set_timing_advance(double timing_advance) + { + d_timing_advance = timing_advance; + } + + } /* namespace gsm */ +} /* namespace gr */ + diff --git a/lib/transmitter/txtime_setter_impl.h b/lib/transmitter/txtime_setter_impl.h new file mode 100644 index 0000000..e3f195a --- /dev/null +++ b/lib/transmitter/txtime_setter_impl.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* @file + * @author Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef INCLUDED_GSM_TXTIME_SETTER_IMPL_H +#define INCLUDED_GSM_TXTIME_SETTER_IMPL_H + +#include +#include +#include + +namespace gr { + namespace gsm { + + class txtime_setter_impl : public txtime_setter + { + private: + uint32_t d_fn_ref; + uint32_t d_ts_ref; + time_format d_time_ref; + time_format d_time_hint; + double d_timing_advance; + double d_delay_correction; + + public: + txtime_setter_impl(uint32_t init_fn, uint64_t init_time_secs, double init_time_fracs, uint64_t time_hint_secs, double time_hint_fracs, double timing_advance, double delay_correction); + ~txtime_setter_impl(); + + // Where all the action really happens + void process_fn_time_reference(pmt::pmt_t msg); + void process_txtime_of_burst(pmt::pmt_t msg); + void set_fn_time_reference(uint32_t fn, uint32_t ts, uint64_t time_secs, double time_fracs); + void set_time_hint(uint64_t time_hint_secs, double time_hint_fracs); + void set_delay_correction(double delay_correction); + void set_timing_advance(double timing_advance); + }; + + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GSM_TXTIME_SETTER_IMPL_H */ + diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 0997931..72f657a 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -59,3 +59,4 @@ GR_ADD_TEST(qa_dummy_burst_filter ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DI #GR_ADD_TEST(qa_msg_to_tag ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_msg_to_tag.py) #GR_ADD_TEST(qa_controlled_fractional_resampler_cc ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_controlled_fractional_resampler_cc.py) #GR_ADD_TEST(qa_uplink_downlink_splitter ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_uplink_downlink_splitter.py) +GR_ADD_TEST(qa_txtime_setter ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_txtime_setter.py) diff --git a/python/qa_txtime_setter.py b/python/qa_txtime_setter.py new file mode 100755 index 0000000..d5509a9 --- /dev/null +++ b/python/qa_txtime_setter.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# @file +# @author Piotr Krysik +# @section LICENSE +# +# Gr-gsm is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# Gr-gsm is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with gr-gsm; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# +# + +from gnuradio import gr, gr_unittest +from gnuradio import blocks +import grgsm_swig as grgsm + +class qa_txtime_setter (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_t (self): + # set up fg + self.tb.run () + # check data + + +if __name__ == '__main__': + gr_unittest.run(qa_txtime_setter, "qa_txtime_setter.xml") diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i index 2743e80..b4fecf6 100644 --- a/swig/grgsm_swig.i +++ b/swig/grgsm_swig.i @@ -70,6 +70,7 @@ #include "grgsm/trx_interface/trx.h" //#include "grgsm/misc_utils/time_spec.h" #include "grgsm/misc_utils/fn_time.h" +#include "grgsm/transmitter/txtime_setter.h" %} %include "constants.i" @@ -175,3 +176,5 @@ GR_SWIG_BLOCK_MAGIC2(grgsm, trx); //}; %include "grgsm/misc_utils/fn_time.h" +%include "grgsm/transmitter/txtime_setter.h" +GR_SWIG_BLOCK_MAGIC2(gsm, txtime_setter); -- cgit v1.2.3 From 776b67f82c47d065b7e8de004a0402e163afd009 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Sun, 5 Nov 2017 12:24:17 +0100 Subject: Missing cmakelists file for txtime_setter --- include/grgsm/transmitter/CMakeLists.txt | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 include/grgsm/transmitter/CMakeLists.txt diff --git a/include/grgsm/transmitter/CMakeLists.txt b/include/grgsm/transmitter/CMakeLists.txt new file mode 100644 index 0000000..78aad43 --- /dev/null +++ b/include/grgsm/transmitter/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# Install public header files +######################################################################## +install(FILES + txtime_setter.h DESTINATION include/grgsm/transmitter +) -- cgit v1.2.3 From 264fbf69f7d578db5b7c2cdc45ed9d66b0d3ae6d Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Sun, 5 Nov 2017 12:25:51 +0100 Subject: Corrected namespaces from grgsm to gsm --- .../grgsm/flow_control/uplink_downlink_splitter.h | 4 +- .../controlled_fractional_resampler_cc.h | 2 +- include/grgsm/misc_utils/msg_to_tag.h | 2 +- include/grgsm/trx_interface/trx.h | 4 +- lib/flow_control/uplink_downlink_splitter_impl.cc | 4 +- lib/flow_control/uplink_downlink_splitter_impl.h | 4 +- .../controlled_fractional_resampler_cc_impl.cc | 2 +- .../controlled_fractional_resampler_cc_impl.h | 2 +- lib/misc_utils/msg_to_tag_impl.cc | 2 +- lib/misc_utils/msg_to_tag_impl.h | 2 +- lib/trx_interface/trx_impl.cc | 4 +- lib/trx_interface/trx_impl.h | 4 +- lib/trx_interface/udp_socket.cc | 4 +- lib/trx_interface/udp_socket.h | 4 +- swig/grgsm_swig.i | 5 +- swig/grgsm_swig.i.orig | 151 --------------------- 16 files changed, 25 insertions(+), 175 deletions(-) delete mode 100644 swig/grgsm_swig.i.orig diff --git a/include/grgsm/flow_control/uplink_downlink_splitter.h b/include/grgsm/flow_control/uplink_downlink_splitter.h index 0dbc0bc..874c0b6 100644 --- a/include/grgsm/flow_control/uplink_downlink_splitter.h +++ b/include/grgsm/flow_control/uplink_downlink_splitter.h @@ -28,7 +28,7 @@ #include namespace gr { - namespace grgsm { + namespace gsm { /*! * \brief <+description of block+> @@ -51,7 +51,7 @@ namespace gr { static sptr make(); }; - } // namespace grgsm + } // namespace gsm } // namespace gr #endif /* INCLUDED_GRGSM_UPLINK_DOWNLINK_SPLITTER_H */ diff --git a/include/grgsm/misc_utils/controlled_fractional_resampler_cc.h b/include/grgsm/misc_utils/controlled_fractional_resampler_cc.h index b085f94..9dae6b8 100644 --- a/include/grgsm/misc_utils/controlled_fractional_resampler_cc.h +++ b/include/grgsm/misc_utils/controlled_fractional_resampler_cc.h @@ -57,7 +57,7 @@ namespace gr { virtual void set_resamp_ratio(float resamp_ratio) = 0; }; - } // namespace grgsm + } // namespace gsm } // namespace gr #endif /* INCLUDED_GRGSM_CONTROLLED_FRACTIONAL_RESAMPLER_CC_H */ diff --git a/include/grgsm/misc_utils/msg_to_tag.h b/include/grgsm/misc_utils/msg_to_tag.h index 87e2e78..c7b4e10 100644 --- a/include/grgsm/misc_utils/msg_to_tag.h +++ b/include/grgsm/misc_utils/msg_to_tag.h @@ -50,7 +50,7 @@ namespace gr { static sptr make(); }; - } // namespace grgsm + } // namespace gsm } // namespace gr #endif /* INCLUDED_GRGSM_MSG_TO_TAG_H */ diff --git a/include/grgsm/trx_interface/trx.h b/include/grgsm/trx_interface/trx.h index 997ef62..c55bf36 100644 --- a/include/grgsm/trx_interface/trx.h +++ b/include/grgsm/trx_interface/trx.h @@ -27,7 +27,7 @@ #include namespace gr { - namespace grgsm { + namespace gsm { /*! * \brief <+description of block+> @@ -56,7 +56,7 @@ namespace gr { virtual int ts_filter_get_tn(void) = 0; }; - } // namespace grgsm + } // namespace gsm } // namespace gr #endif /* INCLUDED_GRGSM_TRX_H */ diff --git a/lib/flow_control/uplink_downlink_splitter_impl.cc b/lib/flow_control/uplink_downlink_splitter_impl.cc index 691feb3..de5ae30 100644 --- a/lib/flow_control/uplink_downlink_splitter_impl.cc +++ b/lib/flow_control/uplink_downlink_splitter_impl.cc @@ -30,7 +30,7 @@ #include #define BURST_SIZE 148 namespace gr { - namespace grgsm { + namespace gsm { uplink_downlink_splitter::sptr uplink_downlink_splitter::make() @@ -71,6 +71,6 @@ namespace gr { uplink_downlink_splitter_impl::~uplink_downlink_splitter_impl() { } - } /* namespace grgsm */ + } /* namespace gsm */ } /* namespace gr */ diff --git a/lib/flow_control/uplink_downlink_splitter_impl.h b/lib/flow_control/uplink_downlink_splitter_impl.h index fb8b2b8..5edfe5a 100644 --- a/lib/flow_control/uplink_downlink_splitter_impl.h +++ b/lib/flow_control/uplink_downlink_splitter_impl.h @@ -26,7 +26,7 @@ #include namespace gr { - namespace grgsm { + namespace gsm { class uplink_downlink_splitter_impl : public uplink_downlink_splitter { @@ -36,7 +36,7 @@ namespace gr { void process_msg(pmt::pmt_t msg); }; - } // namespace grgsm + } // namespace gsm } // namespace gr #endif /* INCLUDED_GRGSM_UPLINK_DOWNLINK_SPLITTER_IMPL_H */ diff --git a/lib/misc_utils/controlled_fractional_resampler_cc_impl.cc b/lib/misc_utils/controlled_fractional_resampler_cc_impl.cc index 3376c67..36cf170 100644 --- a/lib/misc_utils/controlled_fractional_resampler_cc_impl.cc +++ b/lib/misc_utils/controlled_fractional_resampler_cc_impl.cc @@ -177,6 +177,6 @@ namespace gr { set_relative_rate(1.0 / resamp_ratio); } - } /* namespace grgsm */ + } /* namespace gsm */ } /* namespace gr */ diff --git a/lib/misc_utils/controlled_fractional_resampler_cc_impl.h b/lib/misc_utils/controlled_fractional_resampler_cc_impl.h index 24e00ed..1ca8082 100644 --- a/lib/misc_utils/controlled_fractional_resampler_cc_impl.h +++ b/lib/misc_utils/controlled_fractional_resampler_cc_impl.h @@ -64,7 +64,7 @@ namespace gr { void set_resamp_ratio(float resamp_ratio); }; - } // namespace grgsm + } // namespace gsm } // namespace gr #endif /* INCLUDED_GRGSM_CONTROLLED_FRACTIONAL_RESAMPLER_CC_IMPL_H */ diff --git a/lib/misc_utils/msg_to_tag_impl.cc b/lib/misc_utils/msg_to_tag_impl.cc index 0ab65e7..e08c7e6 100644 --- a/lib/misc_utils/msg_to_tag_impl.cc +++ b/lib/misc_utils/msg_to_tag_impl.cc @@ -94,6 +94,6 @@ namespace gr { return noutput_items; } - } /* namespace grgsm */ + } /* namespace gsm */ } /* namespace gr */ diff --git a/lib/misc_utils/msg_to_tag_impl.h b/lib/misc_utils/msg_to_tag_impl.h index 39c6ca3..55e1fae 100644 --- a/lib/misc_utils/msg_to_tag_impl.h +++ b/lib/misc_utils/msg_to_tag_impl.h @@ -44,7 +44,7 @@ namespace gr { gr_vector_void_star &output_items); }; - } // namespace grgsm + } // namespace gsm } // namespace gr #endif /* INCLUDED_GRGSM_MSG_TO_TAG_IMPL_H */ diff --git a/lib/trx_interface/trx_impl.cc b/lib/trx_interface/trx_impl.cc index 2068da3..8c348ac 100644 --- a/lib/trx_interface/trx_impl.cc +++ b/lib/trx_interface/trx_impl.cc @@ -44,7 +44,7 @@ static uint8_t rach_synch_seq[] = { }; namespace gr { - namespace grgsm { + namespace gsm { trx::sptr trx::make( @@ -269,5 +269,5 @@ namespace gr { message_port_pub(pmt::mp("bursts"), msg); } - } /* namespace grgsm */ + } /* namespace gsm */ } /* namespace gr */ diff --git a/lib/trx_interface/trx_impl.h b/lib/trx_interface/trx_impl.h index 19e4848..44a914e 100644 --- a/lib/trx_interface/trx_impl.h +++ b/lib/trx_interface/trx_impl.h @@ -29,7 +29,7 @@ #include namespace gr { - namespace grgsm { + namespace gsm { class trx_impl : public trx { @@ -54,7 +54,7 @@ namespace gr { void handle_ul_burst(uint8_t *payload, size_t len); }; - } // namespace grgsm + } // namespace gsm } // namespace gr #endif /* INCLUDED_GRGSM_TRX_IMPL_H */ diff --git a/lib/trx_interface/udp_socket.cc b/lib/trx_interface/udp_socket.cc index be4bb66..5c689c7 100644 --- a/lib/trx_interface/udp_socket.cc +++ b/lib/trx_interface/udp_socket.cc @@ -35,7 +35,7 @@ using boost::asio::ip::udp; namespace gr { - namespace grgsm { + namespace gsm { udp_socket::udp_socket( const std::string &remote_addr, @@ -115,5 +115,5 @@ namespace gr { boost::asio::placeholders::bytes_transferred)); } - } /* namespace blocks */ + } /* namespace gsm */ }/* namespace gr */ diff --git a/lib/trx_interface/udp_socket.h b/lib/trx_interface/udp_socket.h index 5bcc42b..15b2c66 100644 --- a/lib/trx_interface/udp_socket.h +++ b/lib/trx_interface/udp_socket.h @@ -32,7 +32,7 @@ #include namespace gr { - namespace grgsm { + namespace gsm { class udp_socket { @@ -63,7 +63,7 @@ namespace gr { boost::function udp_rx_handler; }; - } /* namespace blocks */ + } /* namespace gsm */ } /* namespace gr */ #endif /* INCLUDED_GRGSM_TRX_UDP_SOCKET_H */ diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i index b4fecf6..64c1024 100644 --- a/swig/grgsm_swig.i +++ b/swig/grgsm_swig.i @@ -109,7 +109,7 @@ GR_SWIG_BLOCK_MAGIC2(gsm, burst_fnr_filter); %include "grgsm/flow_control/dummy_burst_filter.h" GR_SWIG_BLOCK_MAGIC2(gsm, dummy_burst_filter); %include "grgsm/flow_control/uplink_downlink_splitter.h" -GR_SWIG_BLOCK_MAGIC2(grgsm, uplink_downlink_splitter); +GR_SWIG_BLOCK_MAGIC2(gsm, uplink_downlink_splitter); %include "grgsm/misc_utils/bursts_printer.h" @@ -151,7 +151,7 @@ GR_SWIG_BLOCK_MAGIC2(gsm, message_source); %include "grgsm/qa_utils/message_sink.h" GR_SWIG_BLOCK_MAGIC2(gsm, message_sink); %include "grgsm/trx_interface/trx.h" -GR_SWIG_BLOCK_MAGIC2(grgsm, trx); +GR_SWIG_BLOCK_MAGIC2(gsm, trx); //#pragma SWIG nowarn=319 //%include "grgsm/misc_utils/time_spec.h" @@ -176,5 +176,6 @@ GR_SWIG_BLOCK_MAGIC2(grgsm, trx); //}; %include "grgsm/misc_utils/fn_time.h" + %include "grgsm/transmitter/txtime_setter.h" GR_SWIG_BLOCK_MAGIC2(gsm, txtime_setter); diff --git a/swig/grgsm_swig.i.orig b/swig/grgsm_swig.i.orig deleted file mode 100644 index 888f07a..0000000 --- a/swig/grgsm_swig.i.orig +++ /dev/null @@ -1,151 +0,0 @@ -/* -*- c++ -*- */ -/* - * @file - * @author (C) 2014 by Piotr Krysik - * @section LICENSE - * - * Gr-gsm is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * Gr-gsm is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with gr-gsm; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -#define GRGSM_API - -%include "gnuradio.i" // the common stuff - -//load generated python docstrings -%include "grgsm_swig_doc.i" - -%{ -#include "grgsm/constants.h" -#include "grgsm/receiver/receiver.h" -#include "grgsm/receiver/clock_offset_control.h" -#include "grgsm/receiver/cx_channel_hopper.h" -#include "grgsm/decoding/control_channels_decoder.h" -#include "grgsm/decoding/tch_f_decoder.h" -#include "grgsm/decryption/decryption.h" -#include "grgsm/demapping/universal_ctrl_chans_demapper.h" -#include "grgsm/demapping/tch_f_chans_demapper.h" -#include "grgsm/flow_control/common.h" -#include "grgsm/flow_control/burst_timeslot_splitter.h" -#include "grgsm/flow_control/burst_sdcch_subslot_splitter.h" -#include "grgsm/flow_control/burst_timeslot_filter.h" -#include "grgsm/flow_control/burst_sdcch_subslot_filter.h" -#include "grgsm/flow_control/burst_fnr_filter.h" -#include "grgsm/flow_control/dummy_burst_filter.h" -#include "grgsm/flow_control/uplink_downlink_splitter.h" -#include "grgsm/misc_utils/bursts_printer.h" -#include "grgsm/misc_utils/controlled_rotator_cc.h" -#include "grgsm/misc_utils/extract_system_info.h" -#include "grgsm/misc_utils/extract_immediate_assignment.h" -#include "grgsm/misc_utils/message_printer.h" -#include "grgsm/misc_utils/tmsi_dumper.h" -#include "grgsm/misc_utils/burst_file_sink.h" -#include "grgsm/misc_utils/burst_file_source.h" -#include "grgsm/misc_utils/collect_system_info.h" -#include "grgsm/misc_utils/extract_cmc.h" -#include "grgsm/qa_utils/burst_sink.h" -#include "grgsm/qa_utils/burst_source.h" -#include "grgsm/qa_utils/message_source.h" -#include "grgsm/qa_utils/message_sink.h" -#include "grgsm/misc_utils/message_file_sink.h" -#include "grgsm/misc_utils/message_file_source.h" -#include "grgsm/misc_utils/msg_to_tag.h" -#include "grgsm/misc_utils/controlled_fractional_resampler_cc.h" -#include "grgsm/trx_interface/trx.h" -%} - -%include "constants.i" - -%include "grgsm/receiver/receiver.h" -GR_SWIG_BLOCK_MAGIC2(gsm, receiver); -%include "grgsm/receiver/clock_offset_control.h" -GR_SWIG_BLOCK_MAGIC2(gsm, clock_offset_control); -%include "grgsm/receiver/cx_channel_hopper.h" -GR_SWIG_BLOCK_MAGIC2(gsm, cx_channel_hopper); - -%include "grgsm/decoding/control_channels_decoder.h" -GR_SWIG_BLOCK_MAGIC2(gsm, control_channels_decoder); -%include "grgsm/decoding/tch_f_decoder.h" -GR_SWIG_BLOCK_MAGIC2(gsm, tch_f_decoder); - -%include "grgsm/decryption/decryption.h" -GR_SWIG_BLOCK_MAGIC2(gsm, decryption); - -%include "grgsm/demapping/universal_ctrl_chans_demapper.h" -GR_SWIG_BLOCK_MAGIC2(gsm, universal_ctrl_chans_demapper); -%include "grgsm/demapping/tch_f_chans_demapper.h" -GR_SWIG_BLOCK_MAGIC2(gsm, tch_f_chans_demapper); - -%include "grgsm/flow_control/common.h" -%include "grgsm/flow_control/burst_timeslot_splitter.h" -GR_SWIG_BLOCK_MAGIC2(gsm, burst_timeslot_splitter); -%include "grgsm/flow_control/burst_sdcch_subslot_splitter.h" -GR_SWIG_BLOCK_MAGIC2(gsm, burst_sdcch_subslot_splitter); -%include "grgsm/flow_control/burst_timeslot_filter.h" -GR_SWIG_BLOCK_MAGIC2(gsm, burst_timeslot_filter); -%include "grgsm/flow_control/burst_sdcch_subslot_filter.h" -GR_SWIG_BLOCK_MAGIC2(gsm, burst_sdcch_subslot_filter); -%include "grgsm/flow_control/burst_fnr_filter.h" -GR_SWIG_BLOCK_MAGIC2(gsm, burst_fnr_filter); -%include "grgsm/flow_control/dummy_burst_filter.h" -GR_SWIG_BLOCK_MAGIC2(gsm, dummy_burst_filter); -%include "grgsm/flow_control/uplink_downlink_splitter.h" -GR_SWIG_BLOCK_MAGIC2(grgsm, uplink_downlink_splitter); - - -%include "grgsm/misc_utils/bursts_printer.h" -GR_SWIG_BLOCK_MAGIC2(gsm, bursts_printer); -%include "grgsm/misc_utils/burst_file_sink.h" -GR_SWIG_BLOCK_MAGIC2(gsm, burst_file_sink); -%include "grgsm/misc_utils/burst_file_source.h" -GR_SWIG_BLOCK_MAGIC2(gsm, burst_file_source); -%include "grgsm/misc_utils/collect_system_info.h" -GR_SWIG_BLOCK_MAGIC2(gsm, collect_system_info); -%include "grgsm/misc_utils/extract_system_info.h" -GR_SWIG_BLOCK_MAGIC2(gsm, extract_system_info); -%include "grgsm/misc_utils/extract_immediate_assignment.h" -GR_SWIG_BLOCK_MAGIC2(gsm, extract_immediate_assignment); -%include "grgsm/misc_utils/controlled_rotator_cc.h" -GR_SWIG_BLOCK_MAGIC2(gsm, controlled_rotator_cc); -%include "grgsm/misc_utils/message_printer.h" -GR_SWIG_BLOCK_MAGIC2(gsm, message_printer); -%include "grgsm/misc_utils/tmsi_dumper.h" -GR_SWIG_BLOCK_MAGIC2(gsm, tmsi_dumper); -%include "grgsm/misc_utils/message_file_sink.h" -GR_SWIG_BLOCK_MAGIC2(gsm, message_file_sink); -%include "grgsm/misc_utils/message_file_source.h" -GR_SWIG_BLOCK_MAGIC2(gsm, message_file_source); -%include "grgsm/misc_utils/msg_to_tag.h" -GR_SWIG_BLOCK_MAGIC2(gsm, msg_to_tag); -%include "grgsm/misc_utils/controlled_fractional_resampler_cc.h" -GR_SWIG_BLOCK_MAGIC2(gsm, controlled_fractional_resampler_cc); -%include "grgsm/misc_utils/extract_cmc.h" -GR_SWIG_BLOCK_MAGIC2(gsm, extract_cmc); - - -%include "grgsm/qa_utils/burst_sink.h" -GR_SWIG_BLOCK_MAGIC2(gsm, burst_sink); -%include "grgsm/qa_utils/burst_source.h" -GR_SWIG_BLOCK_MAGIC2(gsm, burst_source); -%include "grgsm/qa_utils/message_source.h" -GR_SWIG_BLOCK_MAGIC2(gsm, message_source); -%include "grgsm/qa_utils/message_sink.h" -GR_SWIG_BLOCK_MAGIC2(gsm, message_sink); -<<<<<<< HEAD -%include "grgsm/trx_interface/trx.h" -GR_SWIG_BLOCK_MAGIC2(grgsm, trx); -======= ->>>>>>> development -- cgit v1.2.3 From 873e44e68d188b5c26621b8ee8fd0c33bf9bd29d Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 17 Oct 2017 06:52:01 +0700 Subject: python/trx: follow GNU Radio class naming conventions --- python/trx/ctrl_if.py | 4 ++-- python/trx/ctrl_if_bb.py | 8 ++++---- python/trx/fake_pm.py | 2 +- python/trx/radio_if.py | 2 +- python/trx/udp_link.py | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/python/trx/ctrl_if.py b/python/trx/ctrl_if.py index a9050ef..7dee0f8 100644 --- a/python/trx/ctrl_if.py +++ b/python/trx/ctrl_if.py @@ -22,9 +22,9 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -from grgsm import UDPLink +from grgsm.trx import udp_link -class CTRLInterface(UDPLink): +class ctrl_if(udp_link): def handle_rx(self, data): if self.verify_req(data): request = self.prepare_req(data) diff --git a/python/trx/ctrl_if_bb.py b/python/trx/ctrl_if_bb.py index b0d54f9..b08f62c 100644 --- a/python/trx/ctrl_if_bb.py +++ b/python/trx/ctrl_if_bb.py @@ -22,12 +22,12 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -from ctrl_if import CTRLInterface +from ctrl_if import ctrl_if -class CTRLInterfaceBB(CTRLInterface): +class ctrl_if_bb(ctrl_if): def __init__(self, remote_addr, remote_port, bind_port, tb, pm): print("[i] Init CTRL interface") - CTRLInterface.__init__(self, remote_addr, remote_port, bind_port) + ctrl_if.__init__(self, remote_addr, remote_port, bind_port) # Set link to the follow graph (top block) self.tb = tb @@ -36,7 +36,7 @@ class CTRLInterfaceBB(CTRLInterface): def shutdown(self): print("[i] Shutdown CTRL interface") - CTRLInterface.shutdown(self) + ctrl_if.shutdown(self) def parse_cmd(self, request): # Power control diff --git a/python/trx/fake_pm.py b/python/trx/fake_pm.py index 1d76916..72cf771 100644 --- a/python/trx/fake_pm.py +++ b/python/trx/fake_pm.py @@ -24,7 +24,7 @@ from random import randint -class FakePM: +class fake_pm: # Freq. list for good power level bts_list = [] diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py index c162f69..40fcabb 100644 --- a/python/trx/radio_if.py +++ b/python/trx/radio_if.py @@ -32,7 +32,7 @@ from math import pi from gnuradio import blocks from gnuradio import gr -class RadioInterface(gr.top_block): +class radio_if(gr.top_block): # PHY specific variables samp_rate = 2000000 shiftoff = 400e3 diff --git a/python/trx/udp_link.py b/python/trx/udp_link.py index 0d90ec9..584a6ac 100644 --- a/python/trx/udp_link.py +++ b/python/trx/udp_link.py @@ -25,7 +25,7 @@ import socket import select -class UDPLink: +class udp_link: def __init__(self, remote_addr, remote_port, bind_port): self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.sock.bind(('0.0.0.0', bind_port)) -- cgit v1.2.3 From eecab7eaf4516da814c50b269a727c070f0a636e Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 17 Oct 2017 07:14:23 +0700 Subject: python/trx: install helper classes as a grgsm submodule --- python/__init__.py | 6 ------ python/trx/CMakeLists.txt | 7 ++++--- python/trx/__init__.py | 27 +++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 python/trx/__init__.py diff --git a/python/__init__.py b/python/__init__.py index 9e99e72..ad551ac 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -58,12 +58,6 @@ from gsm_sdcch8_demapper import gsm_sdcch8_demapper from gsm_gmsk_mod import gsm_gmsk_mod from fn_time import * from txtime_bursts_tagger import * -#from ctrl_if import * -#from ctrl_if_bb import * -#from fake_pm import * -#from radio_if import * -#from udp_link import * - import arfcn diff --git a/python/trx/CMakeLists.txt b/python/trx/CMakeLists.txt index a0ad38f..d8e9164 100644 --- a/python/trx/CMakeLists.txt +++ b/python/trx/CMakeLists.txt @@ -19,9 +19,10 @@ GR_PYTHON_INSTALL( FILES - ctrl_if_bb.py + __init__.py + udp_link.py ctrl_if.py + ctrl_if_bb.py fake_pm.py - radio_if.py - udp_link.py DESTINATION ${GR_PYTHON_DIR}/grgsm + radio_if.py DESTINATION ${GR_PYTHON_DIR}/grgsm/trx ) diff --git a/python/trx/__init__.py b/python/trx/__init__.py new file mode 100644 index 0000000..81e569c --- /dev/null +++ b/python/trx/__init__.py @@ -0,0 +1,27 @@ +# +# Copyright 2008,2009 Free Software Foundation, Inc. +# +# This application is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This application is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +''' +This is a set of helper classes for the grgsm_trx application. +''' + +from udp_link import udp_link +from ctrl_if import ctrl_if +from ctrl_if_bb import ctrl_if_bb +from fake_pm import fake_pm +from radio_if import radio_if -- cgit v1.2.3 From ba7ad29638ecb08af8c7a38dc98c8da715a5fcde Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 17 Oct 2017 07:21:59 +0700 Subject: apps/grgsm_trx: import helper classes from grgsm.trx --- apps/grgsm_trx | 12 ++-- apps/trx/ctrl_if.py | 82 ----------------------- apps/trx/ctrl_if_bb.py | 142 --------------------------------------- apps/trx/fake_pm.py | 53 --------------- apps/trx/grgsm_trx.py | 155 ------------------------------------------- apps/trx/radio_if.py | 175 ------------------------------------------------- apps/trx/udp_link.py | 56 ---------------- 7 files changed, 6 insertions(+), 669 deletions(-) delete mode 100644 apps/trx/ctrl_if.py delete mode 100644 apps/trx/ctrl_if_bb.py delete mode 100644 apps/trx/fake_pm.py delete mode 100755 apps/trx/grgsm_trx.py delete mode 100644 apps/trx/radio_if.py delete mode 100644 apps/trx/udp_link.py diff --git a/apps/grgsm_trx b/apps/grgsm_trx index fbc9350..a5cb1ee 100755 --- a/apps/grgsm_trx +++ b/apps/grgsm_trx @@ -25,9 +25,9 @@ import signal import getopt import sys -from ctrl_if_bb import CTRLInterfaceBB -from radio_if import RadioInterface -from fake_pm import FakePM +from grgsm.trx import ctrl_if_bb +from grgsm.trx import radio_if +from grgsm.trx import fake_pm COPYRIGHT = \ "Copyright (C) 2016-2017 by Vadim Yanitskiy \n" \ @@ -57,17 +57,17 @@ class Application: def run(self): # Init Radio interface - self.radio = RadioInterface(self.phy_args, self.phy_subdev_spec, + self.radio = radio_if(self.phy_args, self.phy_subdev_spec, self.phy_sample_rate, self.phy_gain, self.phy_ppm, self.remote_addr, self.base_port) # Power measurement emulation # Noise: -120 .. -105 # BTS: -75 .. -50 - self.pm = FakePM(-120, -105, -75, -50) + self.pm = fake_pm(-120, -105, -75, -50) # Init TRX CTRL interface - self.server = CTRLInterfaceBB(self.remote_addr, + self.server = ctrl_if_bb(self.remote_addr, self.base_port + 101, self.base_port + 1, self.radio, self.pm) diff --git a/apps/trx/ctrl_if.py b/apps/trx/ctrl_if.py deleted file mode 100644 index 0129d7f..0000000 --- a/apps/trx/ctrl_if.py +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf-8 -*- - -# GR-GSM based transceiver -# CTRL interface implementation -# -# (C) 2016-2017 by Vadim Yanitskiy -# -# All Rights Reserved -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -from udp_link import UDPLink - -class CTRLInterface(UDPLink): - def handle_rx(self, data): - if self.verify_req(data): - request = self.prepare_req(data) - rc = self.parse_cmd(request) - - if type(rc) is tuple: - self.send_response(request, rc[0], rc[1]) - else: - self.send_response(request, rc) - else: - print("[!] Wrong data on CTRL interface") - - def verify_req(self, data): - # Verify command signature - return data.startswith("CMD") - - def prepare_req(self, data): - # Strip signature, paddings and \0 - request = data[4:].strip().strip("\0") - # Split into a command and arguments - request = request.split(" ") - # Now we have something like ["TXTUNE", "941600"] - return request - - def verify_cmd(self, request, cmd, argc): - # Check if requested command matches - if request[0] != cmd: - return False - - # And has enough arguments - if len(request) - 1 != argc: - return False - - # Check if all arguments are numeric - for v in request[1:]: - if not v.isdigit(): - return False - - return True - - def send_response(self, request, response_code, params = None): - # Include status code, for example ["TXTUNE", "0", "941600"] - request.insert(1, str(response_code)) - - # Optionally append command specific parameters - if params is not None: - request += params - - # Add the response signature, and join back to string - response = "RSP " + " ".join(request) + "\0" - # Now we have something like "RSP TXTUNE 0 941600" - self.send(response) - - def parse_cmd(self, request): - raise NotImplementedError diff --git a/apps/trx/ctrl_if_bb.py b/apps/trx/ctrl_if_bb.py deleted file mode 100644 index b0d54f9..0000000 --- a/apps/trx/ctrl_if_bb.py +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf-8 -*- - -# GR-GSM based transceiver -# CTRL interface for OsmocomBB -# -# (C) 2016-2017 by Vadim Yanitskiy -# -# All Rights Reserved -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -from ctrl_if import CTRLInterface - -class CTRLInterfaceBB(CTRLInterface): - def __init__(self, remote_addr, remote_port, bind_port, tb, pm): - print("[i] Init CTRL interface") - CTRLInterface.__init__(self, remote_addr, remote_port, bind_port) - - # Set link to the follow graph (top block) - self.tb = tb - # Power measurement - self.pm = pm - - def shutdown(self): - print("[i] Shutdown CTRL interface") - CTRLInterface.shutdown(self) - - def parse_cmd(self, request): - # Power control - if self.verify_cmd(request, "POWERON", 0): - print("[i] Recv POWERON CMD") - - # Ensure transceiver isn't working - if self.tb.trx_started: - print("[!] Transceiver already started") - return -1 - - # Ensure transceiver is ready to start - if not self.tb.check_available(): - print("[!] Transceiver isn't ready to start") - return -1 - - print("[i] Starting transceiver...") - self.tb.trx_started = True - self.tb.start() - - return 0 - - elif self.verify_cmd(request, "POWEROFF", 0): - print("[i] Recv POWEROFF cmd") - - # TODO: flush all buffers between blocks - if self.tb.trx_started: - print("[i] Stopping transceiver...") - self.tb.trx_started = False - self.tb.stop() - self.tb.wait() - - return 0 - - elif self.verify_cmd(request, "SETRXGAIN", 1): - print("[i] Recv SETRXGAIN cmd") - - # TODO: check gain value - gain = int(request[1]) - self.tb.set_gain(gain) - - return 0 - - # Tuning Control - elif self.verify_cmd(request, "RXTUNE", 1): - print("[i] Recv RXTUNE cmd") - - # TODO: check freq range - freq = int(request[1]) * 1000 - self.tb.set_fc(freq) - - return 0 - - elif self.verify_cmd(request, "TXTUNE", 1): - print("[i] Recv TXTUNE cmd") - - # TODO: is not implemented yet - return 0 - - # Timeslot management - elif self.verify_cmd(request, "SETSLOT", 2): - print("[i] Recv SETSLOT cmd") - - # Obtain TS index - tn = int(request[1]) - if tn not in range(0, 8): - print("[!] TS index should be in range: 0..7") - return -1 - - # Ignore timeslot type for now - # Value 0 means 'drop all' - config = -1 if int(request[2]) == 0 else tn - - print("[i] Configure timeslot filter to: %s" - % ("drop all" if config == -1 else "TS %d" % tn)) - - # HACK: configure built-in timeslot filter - self.tb.gsm_trx_if.ts_filter_set_tn(config) - - return 0 - - # Power measurement - elif self.verify_cmd(request, "MEASURE", 1): - print("[i] Recv MEASURE cmd") - - # TODO: check freq range - meas_freq = int(request[1]) * 1000 - - # HACK: send fake low power values - # until actual power measurement is implemented - meas_dbm = str(self.pm.measure(meas_freq)) - - return (0, [meas_dbm]) - - # Misc - elif self.verify_cmd(request, "ECHO", 0): - print("[i] Recv ECHO cmd") - return 0 - - # Wrong / unknown command - else: - print("[!] Wrong request on CTRL interface") - return -1 diff --git a/apps/trx/fake_pm.py b/apps/trx/fake_pm.py deleted file mode 100644 index 1d76916..0000000 --- a/apps/trx/fake_pm.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf-8 -*- - -# Virtual Um-interface (fake transceiver) -# Power measurement emulation for BB -# -# (C) 2017 by Vadim Yanitskiy -# -# All Rights Reserved -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -from random import randint - -class FakePM: - # Freq. list for good power level - bts_list = [] - - def __init__(self, noise_min, noise_max, bts_min, bts_max): - # Save power level ranges - self.noise_min = noise_min - self.noise_max = noise_max - self.bts_min = bts_min - self.bts_max = bts_max - - def measure(self, bts): - if bts in self.bts_list: - return randint(self.bts_min, self.bts_max) - else: - return randint(self.noise_min, self.noise_max) - - def update_bts_list(self, new_list): - self.bts_list = new_list - - def add_bts_list(self, add_list): - self.bts_list += add_list - - def del_bts_list(self, del_list): - for item in del_list: - if item in self.bts_list: - self.bts_list.remove(item) diff --git a/apps/trx/grgsm_trx.py b/apps/trx/grgsm_trx.py deleted file mode 100755 index fbc9350..0000000 --- a/apps/trx/grgsm_trx.py +++ /dev/null @@ -1,155 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf-8 -*- - -# GR-GSM based transceiver -# -# (C) 2016-2017 by Vadim Yanitskiy -# -# All Rights Reserved -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -import signal -import getopt -import sys - -from ctrl_if_bb import CTRLInterfaceBB -from radio_if import RadioInterface -from fake_pm import FakePM - -COPYRIGHT = \ - "Copyright (C) 2016-2017 by Vadim Yanitskiy \n" \ - "License GPLv2+: GNU GPL version 2 or later " \ - "\n" \ - "This is free software: you are free to change and redistribute it.\n" \ - "There is NO WARRANTY, to the extent permitted by law.\n" - -class Application: - # Application variables - remote_addr = "127.0.0.1" - base_port = 5700 - - # PHY specific - phy_sample_rate = 2000000 - phy_subdev_spec = False - phy_gain = 30 - phy_args = "" - phy_ppm = 0 - - def __init__(self): - self.print_copyright() - self.parse_argv() - - # Set up signal handlers - signal.signal(signal.SIGINT, self.sig_handler) - - def run(self): - # Init Radio interface - self.radio = RadioInterface(self.phy_args, self.phy_subdev_spec, - self.phy_sample_rate, self.phy_gain, self.phy_ppm, - self.remote_addr, self.base_port) - - # Power measurement emulation - # Noise: -120 .. -105 - # BTS: -75 .. -50 - self.pm = FakePM(-120, -105, -75, -50) - - # Init TRX CTRL interface - self.server = CTRLInterfaceBB(self.remote_addr, - self.base_port + 101, self.base_port + 1, - self.radio, self.pm) - - print("[i] Init complete") - - # Enter main loop - while True: - self.server.loop() - - def shutdown(self): - print("[i] Shutting down...") - self.server.shutdown() - self.radio.shutdown() - - def print_copyright(self): - print(COPYRIGHT) - - def print_help(self): - s = " Usage: " + sys.argv[0] + " [options]\n\n" \ - " Some help...\n" \ - " -h --help this text\n\n" - - # TRX specific - s += " TRX interface specific\n" \ - " -s --remote-addr Set remote address (default 127.0.0.1)\n" \ - " -p --base-port Set base port number (default 5700)\n\n" - - # PHY specific - s += " Radio interface specific\n" \ - " -a --device-args Set device arguments\n" \ - " -s --sample-rate Set PHY sample rate (default 2000000)\n" \ - " -S --subdev-spec Set PHY sub-device specification\n" \ - " -g --gain Set PHY gain (default 30)\n" \ - " --ppm Set PHY frequency correction (default 0)\n" - - print(s) - - def parse_argv(self): - try: - opts, args = getopt.getopt(sys.argv[1:], - "a:p:i:s:S:g:h", - ["help", "remote-addr=", "base-port=", "device-args=", - "gain=", "subdev-spec=", "sample-rate=", "ppm="]) - except getopt.GetoptError as err: - # Print(help and exit) - self.print_help() - print("[!] " + str(err)) - sys.exit(2) - - for o, v in opts: - if o in ("-h", "--help"): - self.print_help() - sys.exit(2) - - # TRX specific - elif o in ("-i", "--remote-addr"): - self.remote_addr = v - elif o in ("-p", "--base-port"): - if int(v) >= 0 and int(v) <= 65535: - self.base_port = int(v) - else: - print("[!] The port number should be in range [0-65536]") - sys.exit(2) - - # PHY specific - elif o in ("-a", "--device-args"): - self.phy_args = v - elif o in ("-g", "--gain"): - self.phy_gain = int(v) - elif o in ("-S", "--subdev-spec"): - self.phy_subdev_spec = v - elif o in ("-s", "--sample-rate"): - self.phy_sample_rate = int(v) - elif o in ("--ppm"): - self.phy_ppm = int(v) - - def sig_handler(self, signum, frame): - print("Signal %d received" % signum) - if signum is signal.SIGINT: - self.shutdown() - sys.exit(0) - -if __name__ == '__main__': - app = Application() - app.run() diff --git a/apps/trx/radio_if.py b/apps/trx/radio_if.py deleted file mode 100644 index c162f69..0000000 --- a/apps/trx/radio_if.py +++ /dev/null @@ -1,175 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf-8 -*- - -# GR-GSM based transceiver -# Follow graph implementation -# -# (C) 2016-2017 by Vadim Yanitskiy -# -# All Rights Reserved -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -import pmt -import time -import grgsm -import osmosdr - -from math import pi - -from gnuradio import blocks -from gnuradio import gr - -class RadioInterface(gr.top_block): - # PHY specific variables - samp_rate = 2000000 - shiftoff = 400e3 - subdev_spec = "" # TODO: use it - device_args = "" - fc = 941.6e6 # TODO: set ARFCN to 0? - gain = 30 - ppm = 0 - - # Application state flags - trx_started = False - fc_set = False - - def __init__(self, phy_args, phy_subdev_spec, - phy_sample_rate, phy_gain, phy_ppm, - trx_remote_addr, trx_base_port): - print("[i] Init Radio interface") - - # TRX block specific variables - self.trx_remote_addr = trx_remote_addr - self.trx_base_port = trx_base_port - - # PHY specific variables - self.subdev_spec = phy_subdev_spec - self.samp_rate = phy_sample_rate - self.device_args = phy_args - self.gain = phy_gain - self.ppm = phy_ppm - - gr.top_block.__init__(self, "GR-GSM TRX") - shift_fc = self.fc - self.shiftoff - - ################################################## - # PHY Definition - ################################################## - self.phy = osmosdr.source( - args = "numchan=%d %s" % (1, self.device_args)) - - self.phy.set_bandwidth(250e3 + abs(self.shiftoff), 0) - self.phy.set_center_freq(shift_fc, 0) - self.phy.set_sample_rate(self.samp_rate) - self.phy.set_freq_corr(self.ppm, 0) - self.phy.set_iq_balance_mode(2, 0) - self.phy.set_dc_offset_mode(2, 0) - self.phy.set_gain_mode(False, 0) - self.phy.set_gain(self.gain, 0) - self.phy.set_if_gain(20, 0) - self.phy.set_bb_gain(20, 0) - self.phy.set_antenna("", 0) - - ################################################## - # GR-GSM Magic - ################################################## - self.blocks_rotator = blocks.rotator_cc( - -2 * pi * self.shiftoff / self.samp_rate) - - self.gsm_input = grgsm.gsm_input( - ppm = self.ppm, osr = 4, fc = self.fc, - samp_rate_in = self.samp_rate) - - self.gsm_receiver = grgsm.receiver(4, ([0]), ([])) - - self.gsm_clck_ctrl = grgsm.clock_offset_control( - shift_fc, self.samp_rate, osr = 4) - - self.gsm_trx_if = grgsm.trx(self.trx_remote_addr, - str(self.trx_base_port)) - - ################################################## - # Connections - ################################################## - self.connect((self.phy, 0), (self.blocks_rotator, 0)) - self.connect((self.blocks_rotator, 0), (self.gsm_input, 0)) - self.connect((self.gsm_input, 0), (self.gsm_receiver, 0)) - - self.msg_connect((self.gsm_receiver, 'measurements'), - (self.gsm_clck_ctrl, 'measurements')) - - self.msg_connect((self.gsm_clck_ctrl, 'ctrl'), - (self.gsm_input, 'ctrl_in')) - - self.msg_connect((self.gsm_receiver, 'C0'), - (self.gsm_trx_if, 'bursts')) - - def check_available(self): - return self.fc_set - - def shutdown(self): - print("[i] Shutdown Radio interface") - self.stop() - self.wait() - - def get_args(self): - return self.args - - def set_args(self, args): - self.args = args - - def get_fc(self): - return self.fc - - def set_fc(self, fc): - self.phy.set_center_freq(fc - self.shiftoff, 0) - self.gsm_input.set_fc(fc) - self.fc_set = True - self.fc = fc - - def get_gain(self): - return self.gain - - def set_gain(self, gain): - self.phy.set_gain(gain, 0) - self.gain = gain - - def get_ppm(self): - return self.ppm - - def set_ppm(self, ppm): - self.rtlsdr_source_0.set_freq_corr(ppm, 0) - self.ppm = ppm - - def get_samp_rate(self): - return self.samp_rate - - def set_samp_rate(self, samp_rate): - self.blocks_rotator.set_phase_inc( - -2 * pi * self.shiftoff / samp_rate) - self.gsm_input.set_samp_rate_in(samp_rate) - self.phy.set_sample_rate(samp_rate) - self.samp_rate = samp_rate - - def get_shiftoff(self): - return self.shiftoff - - def set_shiftoff(self, shiftoff): - self.blocks_rotator.set_phase_inc( - -2 * pi * shiftoff / self.samp_rate) - self.phy.set_bandwidth(250e3 + abs(shiftoff), 0) - self.phy.set_center_freq(self.fc - shiftoff, 0) - self.shiftoff = shiftoff diff --git a/apps/trx/udp_link.py b/apps/trx/udp_link.py deleted file mode 100644 index 0d90ec9..0000000 --- a/apps/trx/udp_link.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python2 -# -*- coding: utf-8 -*- - -# GR-GSM based transceiver -# UDP link implementation -# -# (C) 2017 by Vadim Yanitskiy -# -# All Rights Reserved -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -import socket -import select - -class UDPLink: - def __init__(self, remote_addr, remote_port, bind_port): - self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - self.sock.bind(('0.0.0.0', bind_port)) - self.sock.setblocking(0) - - # Save remote info - self.remote_addr = remote_addr - self.remote_port = remote_port - - def loop(self): - r_event, w_event, x_event = select.select([self.sock], [], []) - - # Check for incoming data - if self.sock in r_event: - data, addr = self.sock.recvfrom(128) - self.handle_rx(data.decode()) - - def shutdown(self): - self.sock.close(); - - def send(self, data): - if type(data) not in [bytearray, bytes]: - data = data.encode() - - self.sock.sendto(data, (self.remote_addr, self.remote_port)) - - def handle_rx(self, data): - raise NotImplementedError -- cgit v1.2.3 From e601c366bd179f908d4f34da9fe535c2606cac32 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 17 Oct 2017 08:24:25 +0700 Subject: Refactor the 'TRX Burst Interface' block The following changes were made: - Both implementation and headers were merged with misc_utils - Fixed namespace mess: was gr::grgsm, became gr::gsm - More accurate class name was chosen: "trx_burst_if" --- grc/CMakeLists.txt | 1 - grc/misc_utils/CMakeLists.txt | 1 + grc/misc_utils/gsm_trx_burst_if.xml | 75 +++++++++ grc/trx_interface/CMakeLists.txt | 22 --- grc/trx_interface/gsm_trx.xml | 75 --------- include/grgsm/CMakeLists.txt | 1 - include/grgsm/misc_utils/CMakeLists.txt | 1 + include/grgsm/misc_utils/trx_burst_if.h | 63 ++++++++ include/grgsm/trx_interface/trx.h | 63 -------- lib/CMakeLists.txt | 1 - lib/misc_utils/CMakeLists.txt | 2 + lib/misc_utils/trx_burst_if_impl.cc | 275 ++++++++++++++++++++++++++++++++ lib/misc_utils/trx_burst_if_impl.h | 61 +++++++ lib/misc_utils/udp_socket.cc | 119 ++++++++++++++ lib/misc_utils/udp_socket.h | 69 ++++++++ lib/trx_interface/CMakeLists.txt | 23 --- lib/trx_interface/trx_impl.cc | 273 ------------------------------- lib/trx_interface/trx_impl.h | 61 ------- lib/trx_interface/udp_socket.cc | 119 -------------- lib/trx_interface/udp_socket.h | 69 -------- swig/grgsm_swig.i | 6 +- 21 files changed, 669 insertions(+), 711 deletions(-) create mode 100644 grc/misc_utils/gsm_trx_burst_if.xml delete mode 100644 grc/trx_interface/CMakeLists.txt delete mode 100644 grc/trx_interface/gsm_trx.xml create mode 100644 include/grgsm/misc_utils/trx_burst_if.h delete mode 100644 include/grgsm/trx_interface/trx.h create mode 100644 lib/misc_utils/trx_burst_if_impl.cc create mode 100644 lib/misc_utils/trx_burst_if_impl.h create mode 100644 lib/misc_utils/udp_socket.cc create mode 100644 lib/misc_utils/udp_socket.h delete mode 100644 lib/trx_interface/CMakeLists.txt delete mode 100644 lib/trx_interface/trx_impl.cc delete mode 100644 lib/trx_interface/trx_impl.h delete mode 100644 lib/trx_interface/udp_socket.cc delete mode 100644 lib/trx_interface/udp_socket.h diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 26a91d5..c3646a2 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -23,7 +23,6 @@ add_subdirectory(demapping) add_subdirectory(receiver) add_subdirectory(flow_control) add_subdirectory(misc_utils) -add_subdirectory(trx_interface) add_subdirectory(transmitter) install(FILES gsm_block_tree.xml DESTINATION share/gnuradio/grc/blocks diff --git a/grc/misc_utils/CMakeLists.txt b/grc/misc_utils/CMakeLists.txt index adb90d3..9407caf 100644 --- a/grc/misc_utils/CMakeLists.txt +++ b/grc/misc_utils/CMakeLists.txt @@ -31,6 +31,7 @@ install(FILES gsm_burst_file_source.xml gsm_message_file_sink.xml gsm_message_file_source.xml + gsm_trx_burst_if.xml gsm_msg_to_tag.xml gsm_controlled_fractional_resampler_cc.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/misc_utils/gsm_trx_burst_if.xml b/grc/misc_utils/gsm_trx_burst_if.xml new file mode 100644 index 0000000..d3dab5c --- /dev/null +++ b/grc/misc_utils/gsm_trx_burst_if.xml @@ -0,0 +1,75 @@ + + + TRX Burst Interface + grgsm_trx_burst_if + import grgsm + grgsm.trx_burst_if($remote_addr, $base_port) + + + base_port + base_port + 5700 + string + + + + remote_addr + remote_addr + 127.0.0.1 + string + + + + bursts + message + 1 + + + + bursts + message + 1 + + + + OsmoTRX like UDP interface for external applications. + + There are three UDP sockets: CLCK, CTRL and DATA. + Give a base port B (5700 by default), the SCH clock + interface is at port P=B. The TRX-side control interface + is on port P=B+100+1 and the data interface is on an odd + numbered port P=B+100+2. + + Indications on the SCH Clock Interface (CLCK) + The SCH clock interface is output only (from the radio). + CLOCK gives the current value of the BTS clock to + be used by external applications. The indications are + sent whenever a transmission packet arrives that is too + late or too early. + + Commands on Control Interface (CTRL) + The control interface uses a command-response protocol. + Commands are NULL-terminated ASCII strings. Each command + has a corresponding response. This interface isn't handled + by this particular block, and should be implemented outside. + + Messages on the Data Interface + Messages on the data interface carry one radio burst per + UDP message. + + Received Data Burst: + 1 byte timeslot index + 4 bytes GSM frame number, big endian + 1 byte RSSI in -dBm + 2 bytes correlator timing offset in 1/256 symbol steps, + 2's-comp, big endian + 148 bytes soft symbol estimates, 0 -> definite "0", + 255 -> definite "1" + + Transmit Data Burst: + 1 byte timeslot index + 4 bytes GSM frame number, big endian + 1 byte transmit level wrt ARFCN max, -dB (attenuation) + 148 bytes output symbol values, 0 & 1 + + diff --git a/grc/trx_interface/CMakeLists.txt b/grc/trx_interface/CMakeLists.txt deleted file mode 100644 index 752b7a7..0000000 --- a/grc/trx_interface/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2011,2012 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -install(FILES - gsm_trx.xml DESTINATION share/gnuradio/grc/blocks -) diff --git a/grc/trx_interface/gsm_trx.xml b/grc/trx_interface/gsm_trx.xml deleted file mode 100644 index cbe268c..0000000 --- a/grc/trx_interface/gsm_trx.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - TRX Interface - grgsm_trx_interface - import grgsm - grgsm.trx($remote_addr, $base_port) - - - base_port - base_port - 5700 - string - - - - remote_addr - remote_addr - 127.0.0.1 - string - - - - bursts - message - 1 - - - - bursts - message - 1 - - - - OsmoTRX like UDP interface for external applications. - - There are three UDP sockets: CLCK, CTRL and DATA. - Give a base port B (5700 by default), the SCH clock - interface is at port P=B. The TRX-side control interface - is on port P=B+100+1 and the data interface is on an odd - numbered port P=B+100+2. - - Indications on the SCH Clock Interface (CLCK) - The SCH clock interface is output only (from the radio). - CLOCK gives the current value of the BTS clock to - be used by external applications. The indications are - sent whenever a transmission packet arrives that is too - late or too early. - - Commands on Control Interface (CTRL) - The control interface uses a command-response protocol. - Commands are NULL-terminated ASCII strings. Each command - has a corresponding response. This interface isn't handled - by this particular block, and should be implemented outside. - - Messages on the Data Interface - Messages on the data interface carry one radio burst per - UDP message. - - Received Data Burst: - 1 byte timeslot index - 4 bytes GSM frame number, big endian - 1 byte RSSI in -dBm - 2 bytes correlator timing offset in 1/256 symbol steps, - 2's-comp, big endian - 148 bytes soft symbol estimates, 0 -> definite "0", - 255 -> definite "1" - - Transmit Data Burst: - 1 byte timeslot index - 4 bytes GSM frame number, big endian - 1 byte transmit level wrt ARFCN max, -dB (attenuation) - 148 bytes output symbol values, 0 & 1 - - diff --git a/include/grgsm/CMakeLists.txt b/include/grgsm/CMakeLists.txt index 59034dc..0b58018 100644 --- a/include/grgsm/CMakeLists.txt +++ b/include/grgsm/CMakeLists.txt @@ -36,4 +36,3 @@ add_subdirectory(misc_utils) add_subdirectory(qa_utils) add_subdirectory(flow_control) add_subdirectory(transmitter) -add_subdirectory(trx_interface) diff --git a/include/grgsm/misc_utils/CMakeLists.txt b/include/grgsm/misc_utils/CMakeLists.txt index 978695e..8ac1f52 100644 --- a/include/grgsm/misc_utils/CMakeLists.txt +++ b/include/grgsm/misc_utils/CMakeLists.txt @@ -34,6 +34,7 @@ install(FILES message_printer.h tmsi_dumper.h msg_to_tag.h + trx_burst_if.h controlled_fractional_resampler_cc.h time_spec.h fn_time.h DESTINATION include/grgsm/misc_utils diff --git a/include/grgsm/misc_utils/trx_burst_if.h b/include/grgsm/misc_utils/trx_burst_if.h new file mode 100644 index 0000000..18ceef1 --- /dev/null +++ b/include/grgsm/misc_utils/trx_burst_if.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* @file + * @author Vadim Yanitskiy + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef INCLUDED_GRGSM_TRX_BURST_IF_H +#define INCLUDED_GRGSM_TRX_BURST_IF_H + +#include +#include + +namespace gr { + namespace gsm { + + /*! + * \brief <+description of block+> + * \ingroup grgsm + * + */ + class GRGSM_API trx_burst_if : virtual public gr::block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of grgsm::trx_burst_if. + * + * To avoid accidental use of raw pointers, grgsm::trx_burst_if's + * constructor is in a private implementation + * class. grgsm::trx_burst_if::make is the public interface for + * creating new instances. + */ + static sptr make( + const std::string &remote_addr, + const std::string &base_port); + + /* Expose internal timeslot filter API */ + virtual void ts_filter_set_tn(int tn) = 0; + virtual int ts_filter_get_tn(void) = 0; + }; + + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GRGSM_TRX_BURST_IF_H */ + diff --git a/include/grgsm/trx_interface/trx.h b/include/grgsm/trx_interface/trx.h deleted file mode 100644 index c55bf36..0000000 --- a/include/grgsm/trx_interface/trx.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- c++ -*- */ -/* @file - * @author Vadim Yanitskiy - * @section LICENSE - * - * Gr-gsm is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * Gr-gsm is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with gr-gsm; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef INCLUDED_GRGSM_TRX_H -#define INCLUDED_GRGSM_TRX_H - -#include -#include - -namespace gr { - namespace gsm { - - /*! - * \brief <+description of block+> - * \ingroup grgsm - * - */ - class GRGSM_API trx : virtual public gr::block - { - public: - typedef boost::shared_ptr sptr; - - /*! - * \brief Return a shared_ptr to a new instance of grgsm::trx. - * - * To avoid accidental use of raw pointers, grgsm::trx's - * constructor is in a private implementation - * class. grgsm::trx::make is the public interface for - * creating new instances. - */ - static sptr make( - const std::string &remote_addr, - const std::string &base_port); - - /* Expose internal timeslot filter API */ - virtual void ts_filter_set_tn(int tn) = 0; - virtual int ts_filter_get_tn(void) = 0; - }; - - } // namespace gsm -} // namespace gr - -#endif /* INCLUDED_GRGSM_TRX_H */ - diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 60758a1..9ca7b88 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -71,7 +71,6 @@ add_subdirectory(misc_utils) add_subdirectory(qa_utils) add_subdirectory(receiver) add_subdirectory(transmitter) -add_subdirectory(trx_interface) ######################################################################## # Setup library diff --git a/lib/misc_utils/CMakeLists.txt b/lib/misc_utils/CMakeLists.txt index 81f2ca8..370f11c 100644 --- a/lib/misc_utils/CMakeLists.txt +++ b/lib/misc_utils/CMakeLists.txt @@ -34,5 +34,7 @@ add_sources( tmsi_dumper_impl.cc time_spec.cc fn_time.cc + udp_socket.cc + trx_burst_if_impl.cc ) diff --git a/lib/misc_utils/trx_burst_if_impl.cc b/lib/misc_utils/trx_burst_if_impl.cc new file mode 100644 index 0000000..432ad2f --- /dev/null +++ b/lib/misc_utils/trx_burst_if_impl.cc @@ -0,0 +1,275 @@ +/* -*- c++ -*- */ +/* @file + * @author Vadim Yanitskiy + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "udp_socket.h" +#include "trx_burst_if_impl.h" + +#define BURST_SIZE 148 +#define DATA_IF_MTU 160 + +/** + * 41-bit RACH synchronization sequence + * GSM 05.02 Chapter 5.2.7 Access burst (AB) + */ +static uint8_t rach_synch_seq[] = { + 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, + 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, +}; + +namespace gr { + namespace gsm { + + trx_burst_if::sptr + trx_burst_if::make( + const std::string &remote_addr, + const std::string &base_port) + { + int base_port_int = boost::lexical_cast (base_port); + + return gnuradio::get_initial_sptr + (new trx_burst_if_impl(remote_addr, base_port_int)); + } + + /* + * The private constructor + */ + trx_burst_if_impl::trx_burst_if_impl( + const std::string &remote_addr, + int base_port + ) : gr::block("trx_burst_if", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)) + { + message_port_register_in(pmt::mp("bursts")); + message_port_register_out(pmt::mp("bursts")); + + // Bind a port handler + set_msg_handler(pmt::mp("bursts"), + boost::bind(&trx_burst_if_impl::handle_dl_burst, this, _1)); + + // Prepare port numbers + std::string clck_src_port = boost::lexical_cast (base_port + 0); + std::string clck_dst_port = boost::lexical_cast (base_port + 100); + std::string data_src_port = boost::lexical_cast (base_port + 2); + std::string data_dst_port = boost::lexical_cast (base_port + 102); + + // Init DATA & CLCK interfaces + d_data_sock = new udp_socket(remote_addr, + data_src_port, data_dst_port, DATA_IF_MTU); + d_clck_sock = new udp_socket(remote_addr, + clck_src_port, clck_dst_port, DATA_IF_MTU); + + // Bind DATA interface handler + d_data_sock->udp_rx_handler = boost::bind( + &trx_burst_if_impl::handle_ul_burst, this, _1, _2); + + // Init timeslot filter + d_ts_filter_tn = -1; + } + + /* + * Our virtual destructor. + */ + trx_burst_if_impl::~trx_burst_if_impl() + { + // Release all UDP sockets and free memory + delete d_data_sock; + delete d_clck_sock; + } + + /* + * Timeslot filter API (getter and setter) + */ + void + trx_burst_if_impl::ts_filter_set_tn(int tn) + { + d_ts_filter_tn = (tn >= 0 && tn <= 7) ? tn : -1; + } + + int + trx_burst_if_impl::ts_filter_get_tn(void) + { + return d_ts_filter_tn; + } + + /* + * Check if burst is a RACH burst + */ + bool trx_burst_if_impl::detect_rach(uint8_t *burst) + { + // Compare synchronization sequence + for (int i = 0; i < 41; i++) + if (burst[i + 8] != rach_synch_seq[i]) + return false; + + // Make sure TB and GP are filled by 0x00 + for (int i = 0; i < 63; i++) + if (burst[i + 85] != 0x00) + return false; + + return true; + } + + /* + * Create an UDP payload with clock indication + */ + void + trx_burst_if_impl::clck_ind_send(uint32_t frame_nr) + { + char buf[20]; + size_t n; + + n = snprintf(buf, 20, "IND CLOCK %u", frame_nr); + d_clck_sock->udp_send((uint8_t *) buf, n + 1); + } + + /* + * Create an UDP payload with burst bits + * and some channel data. + */ + void + trx_burst_if_impl::burst_pack(pmt::pmt_t msg, uint8_t *buf) + { + pmt::pmt_t header_plus_burst = pmt::cdr(msg); + + // Extract GSMTAP header from message + gsmtap_hdr *header = (gsmtap_hdr *) + pmt::blob_data(header_plus_burst); + + // Pack timeslot index + buf[0] = header->timeslot; + + // Extract frame number + uint32_t frame_nr = be32toh(header->frame_number); + + // HACK: send clock indications every 51-th frame + if (frame_nr % 51 == 0) + clck_ind_send(frame_nr); + + // Pack frame number + buf[1] = (frame_nr >> 24) & 0xff; + buf[2] = (frame_nr >> 16) & 0xff; + buf[3] = (frame_nr >> 8) & 0xff; + buf[4] = (frame_nr >> 0) & 0xff; + + // Pack RSSI (-dBm) + buf[5] = -(uint8_t) header->signal_dbm; + + // Pack correlator timing offset (TOA) + // FIXME: where to find this value? + buf[6] = 0; + buf[7] = 0; + + // Extract bits {0..1} from message + // Despite GR-GSM uses int8_t, they are not real sbits {-127..127} + uint8_t *burst = (uint8_t *) + (pmt::blob_data(header_plus_burst)) + sizeof(gsmtap_hdr); + + // Convert to transceiver interface specific bits {255..0} + for (int i = 0; i < 148; i++) + buf[8 + i] = burst[i] ? 255 : 0; + + // Fill two unused bytes + buf[156] = 0x00; + buf[157] = 0x00; + } + + void + trx_burst_if_impl::handle_dl_burst(pmt::pmt_t msg) + { + // 8 bytes of header + 148 bytes of burst + // + two unused, but required bytes + // otherwise bursts would be rejected + uint8_t buf[158]; + + // Compose a new UDP payload with burst + burst_pack(msg, buf); + + // Timeslot filter + if (d_ts_filter_tn != -1 && buf[0] != d_ts_filter_tn) + return; + + // Send a burst + d_data_sock->udp_send(buf, 158); + } + + void + trx_burst_if_impl::handle_ul_burst(uint8_t *payload, size_t len) + { + // Check length according to the protocol + if (len != 154) + return; + + /* Make sure TS index is correct */ + if (payload[0] >= 8) + return; + + /* Unpack and check frame number */ + uint32_t fn = (payload[1] << 24) + | (payload[2] << 16) + | (payload[3] << 8) + | payload[4]; + + if (fn >= 2715648) + return; + + // Prepare a buffer for GSMTAP header and burst + uint8_t buf[sizeof(gsmtap_hdr) + BURST_SIZE]; + + // Set up pointer to GSMTAP header structure + struct gsmtap_hdr *header = (struct gsmtap_hdr *) buf; + memset(header, 0x00, sizeof(struct gsmtap_hdr)); + + // Fill in basic info + header->version = GSMTAP_VERSION; + header->hdr_len = sizeof(gsmtap_hdr) / 4; + header->type = GSMTAP_TYPE_UM_BURST; + + // Set timeslot index and frame number + header->timeslot = payload[0]; + header->frame_number = htobe32(fn); + + // Check if one is a RACH burst + header->sub_type = detect_rach(payload + 6) ? + GSMTAP_BURST_ACCESS : GSMTAP_BURST_NORMAL; + + // Copy burst bits (0 & 1) for source message + memcpy(buf + sizeof(gsmtap_hdr), payload + 6, BURST_SIZE); + + // Create a pmt blob + pmt::pmt_t blob = pmt::make_blob(buf, sizeof(gsmtap_hdr) + BURST_SIZE); + pmt::pmt_t msg = pmt::cons(pmt::PMT_NIL, blob); + + /* Send a message to the output */ + message_port_pub(pmt::mp("bursts"), msg); + } + + } /* namespace gsm */ +} /* namespace gr */ diff --git a/lib/misc_utils/trx_burst_if_impl.h b/lib/misc_utils/trx_burst_if_impl.h new file mode 100644 index 0000000..23d2264 --- /dev/null +++ b/lib/misc_utils/trx_burst_if_impl.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* @file + * @author Vadim Yanitskiy + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef INCLUDED_GRGSM_TRX_BURST_IF_IMPL_H +#define INCLUDED_GRGSM_TRX_BURST_IF_IMPL_H + +#include + +#include +#include + +namespace gr { + namespace gsm { + + class trx_burst_if_impl : public trx_burst_if + { + private: + udp_socket *d_data_sock; + udp_socket *d_clck_sock; + int d_ts_filter_tn; + + bool detect_rach(uint8_t *burst); + void clck_ind_send(uint32_t frame_nr); + void burst_pack(pmt::pmt_t msg, uint8_t *buf); + + public: + trx_burst_if_impl(const std::string &remote_addr, int base_port); + ~trx_burst_if_impl(); + + /* Timeslot filter API */ + void ts_filter_set_tn(int tn); + int ts_filter_get_tn(void); + + void handle_dl_burst(pmt::pmt_t msg); + void handle_ul_burst(uint8_t *payload, size_t len); + }; + + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GRGSM_TRX_BURST_IF_IMPL_H */ + diff --git a/lib/misc_utils/udp_socket.cc b/lib/misc_utils/udp_socket.cc new file mode 100644 index 0000000..5c689c7 --- /dev/null +++ b/lib/misc_utils/udp_socket.cc @@ -0,0 +1,119 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include +#include "udp_socket.h" + +using boost::asio::ip::udp; + +namespace gr { + namespace gsm { + + udp_socket::udp_socket( + const std::string &remote_addr, + const std::string &src_port, + const std::string &dst_port, + size_t mtu) + { + // Resize receive buffer according to MTU value + d_rxbuf.resize(mtu); + + // Resolve remote host address + udp::resolver resolver(d_io_service); + + udp::resolver::query rx_query( + udp::v4(), remote_addr, src_port, + boost::asio::ip::resolver_query_base::passive); + udp::resolver::query tx_query( + udp::v4(), remote_addr, dst_port, + boost::asio::ip::resolver_query_base::passive); + + d_udp_endpoint_rx = *resolver.resolve(rx_query); + d_udp_endpoint_tx = *resolver.resolve(tx_query); + + // Create a socket + d_udp_socket.reset(new udp::socket(d_io_service, d_udp_endpoint_rx)); + + // Setup read handler + d_udp_socket->async_receive_from( + boost::asio::buffer(d_rxbuf), d_udp_endpoint_rx, + boost::bind(&udp_socket::handle_udp_read, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + + // Start server + d_thread = gr::thread::thread( + boost::bind(&udp_socket::run_io_service, this)); + } + + udp_socket::~udp_socket() + { + // Stop server + d_io_service.stop(); + d_thread.interrupt(); + d_thread.join(); + } + + void + udp_socket::run_io_service(void) + { + d_io_service.run(); + } + + void + udp_socket::udp_send(uint8_t *data, size_t len) + { + d_udp_socket->send_to( + boost::asio::buffer(data, len), + d_udp_endpoint_tx); + } + + void + udp_socket::handle_udp_read( + const boost::system::error_code& error, + size_t bytes_transferred) + { + if (error) + return; + + // Call incoming data handler + if (udp_rx_handler != NULL) + udp_rx_handler((uint8_t *) &d_rxbuf[0], bytes_transferred); + + d_udp_socket->async_receive_from( + boost::asio::buffer(d_rxbuf), d_udp_endpoint_rx, + boost::bind(&udp_socket::handle_udp_read, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + + } /* namespace gsm */ +}/* namespace gr */ diff --git a/lib/misc_utils/udp_socket.h b/lib/misc_utils/udp_socket.h new file mode 100644 index 0000000..15b2c66 --- /dev/null +++ b/lib/misc_utils/udp_socket.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GRGSM_TRX_UDP_SOCKET_H +#define INCLUDED_GRGSM_TRX_UDP_SOCKET_H + +#include + +#include +#include +#include +#include +#include + +namespace gr { + namespace gsm { + + class udp_socket + { + private: + boost::asio::io_service d_io_service; + std::vector d_rxbuf; + gr::thread::thread d_thread; + bool d_started; + bool d_finished; + + boost::asio::ip::udp::endpoint d_udp_endpoint_rx; + boost::asio::ip::udp::endpoint d_udp_endpoint_tx; + boost::shared_ptr d_udp_socket; + + void handle_udp_read(const boost::system::error_code& error, + size_t bytes_transferred); + void run_io_service(void); + + public: + udp_socket( + const std::string &remote_addr, + const std::string &src_port, + const std::string &dst_port, + size_t mtu); + ~udp_socket(); + + void udp_send(uint8_t *data, size_t len); + boost::function udp_rx_handler; + }; + + } /* namespace gsm */ +} /* namespace gr */ + +#endif /* INCLUDED_GRGSM_TRX_UDP_SOCKET_H */ diff --git a/lib/trx_interface/CMakeLists.txt b/lib/trx_interface/CMakeLists.txt deleted file mode 100644 index 12767b9..0000000 --- a/lib/trx_interface/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2011,2012 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -add_sources( - trx_impl.cc - udp_socket.cc -) diff --git a/lib/trx_interface/trx_impl.cc b/lib/trx_interface/trx_impl.cc deleted file mode 100644 index 8c348ac..0000000 --- a/lib/trx_interface/trx_impl.cc +++ /dev/null @@ -1,273 +0,0 @@ -/* -*- c++ -*- */ -/* @file - * @author Vadim Yanitskiy - * @section LICENSE - * - * Gr-gsm is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * Gr-gsm is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with gr-gsm; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -#include "udp_socket.h" -#include "trx_impl.h" - -#define BURST_SIZE 148 -#define DATA_IF_MTU 160 - -/** - * 41-bit RACH synchronization sequence - * GSM 05.02 Chapter 5.2.7 Access burst (AB) - */ -static uint8_t rach_synch_seq[] = { - 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, - 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, - 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, -}; - -namespace gr { - namespace gsm { - - trx::sptr - trx::make( - const std::string &remote_addr, - const std::string &base_port) - { - int base_port_int = boost::lexical_cast (base_port); - - return gnuradio::get_initial_sptr - (new trx_impl(remote_addr, base_port_int)); - } - - /* - * The private constructor - */ - trx_impl::trx_impl(const std::string &remote_addr, int base_port) - : gr::block("trx", - gr::io_signature::make(0, 0, 0), - gr::io_signature::make(0, 0, 0)) - { - message_port_register_in(pmt::mp("bursts")); - message_port_register_out(pmt::mp("bursts")); - - // Bind a port handler - set_msg_handler(pmt::mp("bursts"), - boost::bind(&trx_impl::handle_dl_burst, this, _1)); - - // Prepare port numbers - std::string clck_src_port = boost::lexical_cast (base_port + 0); - std::string clck_dst_port = boost::lexical_cast (base_port + 100); - std::string data_src_port = boost::lexical_cast (base_port + 2); - std::string data_dst_port = boost::lexical_cast (base_port + 102); - - // Init DATA & CLCK interfaces - d_data_sock = new udp_socket(remote_addr, - data_src_port, data_dst_port, DATA_IF_MTU); - d_clck_sock = new udp_socket(remote_addr, - clck_src_port, clck_dst_port, DATA_IF_MTU); - - // Bind DATA interface handler - d_data_sock->udp_rx_handler = boost::bind( - &trx_impl::handle_ul_burst, this, _1, _2); - - // Init timeslot filter - d_ts_filter_tn = -1; - } - - /* - * Our virtual destructor. - */ - trx_impl::~trx_impl() - { - // Release all UDP sockets and free memory - delete d_data_sock; - delete d_clck_sock; - } - - /* - * Timeslot filter API (getter and setter) - */ - void - trx_impl::ts_filter_set_tn(int tn) - { - d_ts_filter_tn = (tn >= 0 && tn <= 7) ? tn : -1; - } - - int - trx_impl::ts_filter_get_tn(void) - { - return d_ts_filter_tn; - } - - /* - * Check if burst is a RACH burst - */ - bool trx_impl::detect_rach(uint8_t *burst) - { - // Compare synchronization sequence - for (int i = 0; i < 41; i++) - if (burst[i + 8] != rach_synch_seq[i]) - return false; - - // Make sure TB and GP are filled by 0x00 - for (int i = 0; i < 63; i++) - if (burst[i + 85] != 0x00) - return false; - - return true; - } - - /* - * Create an UDP payload with clock indication - */ - void - trx_impl::clck_ind_send(uint32_t frame_nr) - { - char buf[20]; - size_t n; - - n = snprintf(buf, 20, "IND CLOCK %u", frame_nr); - d_clck_sock->udp_send((uint8_t *) buf, n + 1); - } - - /* - * Create an UDP payload with burst bits - * and some channel data. - */ - void - trx_impl::burst_pack(pmt::pmt_t msg, uint8_t *buf) - { - pmt::pmt_t header_plus_burst = pmt::cdr(msg); - - // Extract GSMTAP header from message - gsmtap_hdr *header = (gsmtap_hdr *) - pmt::blob_data(header_plus_burst); - - // Pack timeslot index - buf[0] = header->timeslot; - - // Extract frame number - uint32_t frame_nr = be32toh(header->frame_number); - - // HACK: send clock indications every 51-th frame - if (frame_nr % 51 == 0) - clck_ind_send(frame_nr); - - // Pack frame number - buf[1] = (frame_nr >> 24) & 0xff; - buf[2] = (frame_nr >> 16) & 0xff; - buf[3] = (frame_nr >> 8) & 0xff; - buf[4] = (frame_nr >> 0) & 0xff; - - // Pack RSSI (-dBm) - buf[5] = -(uint8_t) header->signal_dbm; - - // Pack correlator timing offset (TOA) - // FIXME: where to find this value? - buf[6] = 0; - buf[7] = 0; - - // Extract bits {0..1} from message - // Despite GR-GSM uses int8_t, they are not real sbits {-127..127} - uint8_t *burst = (uint8_t *) - (pmt::blob_data(header_plus_burst)) + sizeof(gsmtap_hdr); - - // Convert to transceiver interface specific bits {255..0} - for (int i = 0; i < 148; i++) - buf[8 + i] = burst[i] ? 255 : 0; - - // Fill two unused bytes - buf[156] = 0x00; - buf[157] = 0x00; - } - - void - trx_impl::handle_dl_burst(pmt::pmt_t msg) - { - // 8 bytes of header + 148 bytes of burst - // + two unused, but required bytes - // otherwise bursts would be rejected - uint8_t buf[158]; - - // Compose a new UDP payload with burst - burst_pack(msg, buf); - - // Timeslot filter - if (d_ts_filter_tn != -1 && buf[0] != d_ts_filter_tn) - return; - - // Send a burst - d_data_sock->udp_send(buf, 158); - } - - void - trx_impl::handle_ul_burst(uint8_t *payload, size_t len) - { - // Check length according to the protocol - if (len != 154) - return; - - /* Make sure TS index is correct */ - if (payload[0] >= 8) - return; - - /* Unpack and check frame number */ - uint32_t fn = (payload[1] << 24) - | (payload[2] << 16) - | (payload[3] << 8) - | payload[4]; - - if (fn >= 2715648) - return; - - // Prepare a buffer for GSMTAP header and burst - uint8_t buf[sizeof(gsmtap_hdr) + BURST_SIZE]; - - // Set up pointer to GSMTAP header structure - struct gsmtap_hdr *header = (struct gsmtap_hdr *) buf; - memset(header, 0x00, sizeof(struct gsmtap_hdr)); - - // Fill in basic info - header->version = GSMTAP_VERSION; - header->hdr_len = sizeof(gsmtap_hdr) / 4; - header->type = GSMTAP_TYPE_UM_BURST; - - // Set timeslot index and frame number - header->timeslot = payload[0]; - header->frame_number = htobe32(fn); - - // Check if one is a RACH burst - header->sub_type = detect_rach(payload + 6) ? - GSMTAP_BURST_ACCESS : GSMTAP_BURST_NORMAL; - - // Copy burst bits (0 & 1) for source message - memcpy(buf + sizeof(gsmtap_hdr), payload + 6, BURST_SIZE); - - // Create a pmt blob - pmt::pmt_t blob = pmt::make_blob(buf, sizeof(gsmtap_hdr) + BURST_SIZE); - pmt::pmt_t msg = pmt::cons(pmt::PMT_NIL, blob); - - /* Send a message to the output */ - message_port_pub(pmt::mp("bursts"), msg); - } - - } /* namespace gsm */ -} /* namespace gr */ diff --git a/lib/trx_interface/trx_impl.h b/lib/trx_interface/trx_impl.h deleted file mode 100644 index 6fecf17..0000000 --- a/lib/trx_interface/trx_impl.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- c++ -*- */ -/* @file - * @author Vadim Yanitskiy - * @section LICENSE - * - * Gr-gsm is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * Gr-gsm is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with gr-gsm; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef INCLUDED_GRGSM_TRX_IMPL_H -#define INCLUDED_GRGSM_TRX_IMPL_H - -#include - -#include -#include - -namespace gr { - namespace gsm { - - class trx_impl : public trx - { - private: - udp_socket *d_data_sock; - udp_socket *d_clck_sock; - int d_ts_filter_tn; - - bool detect_rach(uint8_t *burst); - void clck_ind_send(uint32_t frame_nr); - void burst_pack(pmt::pmt_t msg, uint8_t *buf); - - public: - trx_impl(const std::string &remote_addr, int base_port); - ~trx_impl(); - - /* Timeslot filter API */ - void ts_filter_set_tn(int tn); - int ts_filter_get_tn(void); - - void handle_dl_burst(pmt::pmt_t msg); - void handle_ul_burst(uint8_t *payload, size_t len); - }; - - } // namespace gsm -} // namespace gr - -#endif /* INCLUDED_GRGSM_TRX_IMPL_H */ - diff --git a/lib/trx_interface/udp_socket.cc b/lib/trx_interface/udp_socket.cc deleted file mode 100644 index 5c689c7..0000000 --- a/lib/trx_interface/udp_socket.cc +++ /dev/null @@ -1,119 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2013 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include - -#include -#include "udp_socket.h" - -using boost::asio::ip::udp; - -namespace gr { - namespace gsm { - - udp_socket::udp_socket( - const std::string &remote_addr, - const std::string &src_port, - const std::string &dst_port, - size_t mtu) - { - // Resize receive buffer according to MTU value - d_rxbuf.resize(mtu); - - // Resolve remote host address - udp::resolver resolver(d_io_service); - - udp::resolver::query rx_query( - udp::v4(), remote_addr, src_port, - boost::asio::ip::resolver_query_base::passive); - udp::resolver::query tx_query( - udp::v4(), remote_addr, dst_port, - boost::asio::ip::resolver_query_base::passive); - - d_udp_endpoint_rx = *resolver.resolve(rx_query); - d_udp_endpoint_tx = *resolver.resolve(tx_query); - - // Create a socket - d_udp_socket.reset(new udp::socket(d_io_service, d_udp_endpoint_rx)); - - // Setup read handler - d_udp_socket->async_receive_from( - boost::asio::buffer(d_rxbuf), d_udp_endpoint_rx, - boost::bind(&udp_socket::handle_udp_read, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - - // Start server - d_thread = gr::thread::thread( - boost::bind(&udp_socket::run_io_service, this)); - } - - udp_socket::~udp_socket() - { - // Stop server - d_io_service.stop(); - d_thread.interrupt(); - d_thread.join(); - } - - void - udp_socket::run_io_service(void) - { - d_io_service.run(); - } - - void - udp_socket::udp_send(uint8_t *data, size_t len) - { - d_udp_socket->send_to( - boost::asio::buffer(data, len), - d_udp_endpoint_tx); - } - - void - udp_socket::handle_udp_read( - const boost::system::error_code& error, - size_t bytes_transferred) - { - if (error) - return; - - // Call incoming data handler - if (udp_rx_handler != NULL) - udp_rx_handler((uint8_t *) &d_rxbuf[0], bytes_transferred); - - d_udp_socket->async_receive_from( - boost::asio::buffer(d_rxbuf), d_udp_endpoint_rx, - boost::bind(&udp_socket::handle_udp_read, this, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); - } - - } /* namespace gsm */ -}/* namespace gr */ diff --git a/lib/trx_interface/udp_socket.h b/lib/trx_interface/udp_socket.h deleted file mode 100644 index 15b2c66..0000000 --- a/lib/trx_interface/udp_socket.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2013 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GRGSM_TRX_UDP_SOCKET_H -#define INCLUDED_GRGSM_TRX_UDP_SOCKET_H - -#include - -#include -#include -#include -#include -#include - -namespace gr { - namespace gsm { - - class udp_socket - { - private: - boost::asio::io_service d_io_service; - std::vector d_rxbuf; - gr::thread::thread d_thread; - bool d_started; - bool d_finished; - - boost::asio::ip::udp::endpoint d_udp_endpoint_rx; - boost::asio::ip::udp::endpoint d_udp_endpoint_tx; - boost::shared_ptr d_udp_socket; - - void handle_udp_read(const boost::system::error_code& error, - size_t bytes_transferred); - void run_io_service(void); - - public: - udp_socket( - const std::string &remote_addr, - const std::string &src_port, - const std::string &dst_port, - size_t mtu); - ~udp_socket(); - - void udp_send(uint8_t *data, size_t len); - boost::function udp_rx_handler; - }; - - } /* namespace gsm */ -} /* namespace gr */ - -#endif /* INCLUDED_GRGSM_TRX_UDP_SOCKET_H */ diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i index 64c1024..4901b44 100644 --- a/swig/grgsm_swig.i +++ b/swig/grgsm_swig.i @@ -67,10 +67,10 @@ #include "grgsm/misc_utils/message_file_source.h" #include "grgsm/misc_utils/msg_to_tag.h" #include "grgsm/misc_utils/controlled_fractional_resampler_cc.h" -#include "grgsm/trx_interface/trx.h" //#include "grgsm/misc_utils/time_spec.h" #include "grgsm/misc_utils/fn_time.h" #include "grgsm/transmitter/txtime_setter.h" +#include "grgsm/misc_utils/trx_burst_if.h" %} %include "constants.i" @@ -140,6 +140,8 @@ GR_SWIG_BLOCK_MAGIC2(gsm, msg_to_tag); GR_SWIG_BLOCK_MAGIC2(gsm, controlled_fractional_resampler_cc); %include "grgsm/misc_utils/extract_cmc.h" GR_SWIG_BLOCK_MAGIC2(gsm, extract_cmc); +%include "grgsm/misc_utils/trx_burst_if.h" +GR_SWIG_BLOCK_MAGIC2(gsm, trx_burst_if); %include "grgsm/qa_utils/burst_sink.h" @@ -150,8 +152,6 @@ GR_SWIG_BLOCK_MAGIC2(gsm, burst_source); GR_SWIG_BLOCK_MAGIC2(gsm, message_source); %include "grgsm/qa_utils/message_sink.h" GR_SWIG_BLOCK_MAGIC2(gsm, message_sink); -%include "grgsm/trx_interface/trx.h" -GR_SWIG_BLOCK_MAGIC2(gsm, trx); //#pragma SWIG nowarn=319 //%include "grgsm/misc_utils/time_spec.h" -- cgit v1.2.3 From 25916f390845ec8a01339f7ad52e5eccb722e6cd Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 17 Oct 2017 08:46:12 +0700 Subject: Clean up the "TRX Burst Interface" block description --- grc/misc_utils/gsm_trx_burst_if.xml | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/grc/misc_utils/gsm_trx_burst_if.xml b/grc/misc_utils/gsm_trx_burst_if.xml index d3dab5c..252cf6a 100644 --- a/grc/misc_utils/gsm_trx_burst_if.xml +++ b/grc/misc_utils/gsm_trx_burst_if.xml @@ -32,32 +32,15 @@ - OsmoTRX like UDP interface for external applications. + OsmoTRX like UDP burst interface for external applications. - There are three UDP sockets: CLCK, CTRL and DATA. - Give a base port B (5700 by default), the SCH clock - interface is at port P=B. The TRX-side control interface - is on port P=B+100+1 and the data interface is on an odd - numbered port P=B+100+2. + There are two UDP connections, where each message carries + one radio burst with header. Give a base port B (5700 by default). + One connection at port P=B+100+2 is used for sending received bursts + to an external application. Another one at port P=B+2 is used to + obtain to be transmitted bursts. - Indications on the SCH Clock Interface (CLCK) - The SCH clock interface is output only (from the radio). - CLOCK gives the current value of the BTS clock to - be used by external applications. The indications are - sent whenever a transmission packet arrives that is too - late or too early. - - Commands on Control Interface (CTRL) - The control interface uses a command-response protocol. - Commands are NULL-terminated ASCII strings. Each command - has a corresponding response. This interface isn't handled - by this particular block, and should be implemented outside. - - Messages on the Data Interface - Messages on the data interface carry one radio burst per - UDP message. - - Received Data Burst: + Received burst format: 1 byte timeslot index 4 bytes GSM frame number, big endian 1 byte RSSI in -dBm @@ -66,7 +49,7 @@ 148 bytes soft symbol estimates, 0 -> definite "0", 255 -> definite "1" - Transmit Data Burst: + To be transmitted burst format: 1 byte timeslot index 4 bytes GSM frame number, big endian 1 byte transmit level wrt ARFCN max, -dB (attenuation) -- cgit v1.2.3 From 6bac5746867d50cfffb0c2e2dd6498550ccb3fd7 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 17 Oct 2017 08:52:27 +0700 Subject: misc_utils/trx_burst_if: get rid of clock interface Clock indications are only required for BTS operation, while MS can obtain current frame number from the messages on DATA interface. --- lib/misc_utils/trx_burst_if_impl.cc | 24 +----------------------- lib/misc_utils/trx_burst_if_impl.h | 2 -- 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/lib/misc_utils/trx_burst_if_impl.cc b/lib/misc_utils/trx_burst_if_impl.cc index 432ad2f..6d63edf 100644 --- a/lib/misc_utils/trx_burst_if_impl.cc +++ b/lib/misc_utils/trx_burst_if_impl.cc @@ -75,16 +75,12 @@ namespace gr { boost::bind(&trx_burst_if_impl::handle_dl_burst, this, _1)); // Prepare port numbers - std::string clck_src_port = boost::lexical_cast (base_port + 0); - std::string clck_dst_port = boost::lexical_cast (base_port + 100); std::string data_src_port = boost::lexical_cast (base_port + 2); std::string data_dst_port = boost::lexical_cast (base_port + 102); - // Init DATA & CLCK interfaces + // Init DATA interface d_data_sock = new udp_socket(remote_addr, data_src_port, data_dst_port, DATA_IF_MTU); - d_clck_sock = new udp_socket(remote_addr, - clck_src_port, clck_dst_port, DATA_IF_MTU); // Bind DATA interface handler d_data_sock->udp_rx_handler = boost::bind( @@ -101,7 +97,6 @@ namespace gr { { // Release all UDP sockets and free memory delete d_data_sock; - delete d_clck_sock; } /* @@ -137,19 +132,6 @@ namespace gr { return true; } - /* - * Create an UDP payload with clock indication - */ - void - trx_burst_if_impl::clck_ind_send(uint32_t frame_nr) - { - char buf[20]; - size_t n; - - n = snprintf(buf, 20, "IND CLOCK %u", frame_nr); - d_clck_sock->udp_send((uint8_t *) buf, n + 1); - } - /* * Create an UDP payload with burst bits * and some channel data. @@ -169,10 +151,6 @@ namespace gr { // Extract frame number uint32_t frame_nr = be32toh(header->frame_number); - // HACK: send clock indications every 51-th frame - if (frame_nr % 51 == 0) - clck_ind_send(frame_nr); - // Pack frame number buf[1] = (frame_nr >> 24) & 0xff; buf[2] = (frame_nr >> 16) & 0xff; diff --git a/lib/misc_utils/trx_burst_if_impl.h b/lib/misc_utils/trx_burst_if_impl.h index 23d2264..fd5a42d 100644 --- a/lib/misc_utils/trx_burst_if_impl.h +++ b/lib/misc_utils/trx_burst_if_impl.h @@ -35,11 +35,9 @@ namespace gr { { private: udp_socket *d_data_sock; - udp_socket *d_clck_sock; int d_ts_filter_tn; bool detect_rach(uint8_t *burst); - void clck_ind_send(uint32_t frame_nr); void burst_pack(pmt::pmt_t msg, uint8_t *buf); public: -- cgit v1.2.3 From 51a95dfd403f027909cf0f95c98e400db2c8fdfb Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 17 Oct 2017 08:54:18 +0700 Subject: grc/gsm_block_tree: add forgotten gsm_trx_burst_if block --- grc/gsm_block_tree.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/grc/gsm_block_tree.xml b/grc/gsm_block_tree.xml index ae41f4d..479bdb4 100644 --- a/grc/gsm_block_tree.xml +++ b/grc/gsm_block_tree.xml @@ -71,6 +71,7 @@ gsm_clock_offset_corrector_tagged gsm_msg_to_tag.xml gsm_tmsi_dumper + gsm_trx_burst_if -- cgit v1.2.3 From 1a88dec14764f256f71670f23d1bb717225f736d Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 17 Oct 2017 09:00:47 +0700 Subject: trx/radio_if.py: fix: use proper block name Since the 'TRX Burst Interface' block was renamed, the followgraph is broken. Let's fix it. --- python/trx/radio_if.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py index 40fcabb..661025a 100644 --- a/python/trx/radio_if.py +++ b/python/trx/radio_if.py @@ -98,8 +98,8 @@ class radio_if(gr.top_block): self.gsm_clck_ctrl = grgsm.clock_offset_control( shift_fc, self.samp_rate, osr = 4) - self.gsm_trx_if = grgsm.trx(self.trx_remote_addr, - str(self.trx_base_port)) + self.gsm_trx_burst_if = grgsm.trx_burst_if( + self.trx_remote_addr, str(self.trx_base_port)) ################################################## # Connections @@ -115,7 +115,7 @@ class radio_if(gr.top_block): (self.gsm_input, 'ctrl_in')) self.msg_connect((self.gsm_receiver, 'C0'), - (self.gsm_trx_if, 'bursts')) + (self.gsm_trx_burst_if, 'bursts')) def check_available(self): return self.fc_set -- cgit v1.2.3 From 8e9b3075d72f0b6cb09179e68530102e2d4eb28d Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 17 Oct 2017 09:24:26 +0700 Subject: grc/gsm_trx_burst_if.xml: fix prefix of value --- grc/misc_utils/gsm_trx_burst_if.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grc/misc_utils/gsm_trx_burst_if.xml b/grc/misc_utils/gsm_trx_burst_if.xml index 252cf6a..99427b3 100644 --- a/grc/misc_utils/gsm_trx_burst_if.xml +++ b/grc/misc_utils/gsm_trx_burst_if.xml @@ -1,7 +1,7 @@ TRX Burst Interface - grgsm_trx_burst_if + gsm_trx_burst_if import grgsm grgsm.trx_burst_if($remote_addr, $base_port) -- cgit v1.2.3 From 962e2d83bb0eb62e6d1222339977c2f5f23d0dbd Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 17 Oct 2017 09:24:55 +0700 Subject: misc_utils/trx_burst_if: get rid of built-in timeslot filter Since the API of 'Timeslot Filter' block was exposed, we can get rid of built-in timeslot filter and use the proper methods. --- include/grgsm/misc_utils/trx_burst_if.h | 4 ---- lib/misc_utils/trx_burst_if_impl.cc | 22 ---------------------- lib/misc_utils/trx_burst_if_impl.h | 5 ----- python/trx/ctrl_if_bb.py | 19 ++++++++++++------- python/trx/radio_if.py | 6 ++++++ 5 files changed, 18 insertions(+), 38 deletions(-) diff --git a/include/grgsm/misc_utils/trx_burst_if.h b/include/grgsm/misc_utils/trx_burst_if.h index 18ceef1..0e7a35a 100644 --- a/include/grgsm/misc_utils/trx_burst_if.h +++ b/include/grgsm/misc_utils/trx_burst_if.h @@ -50,10 +50,6 @@ namespace gr { static sptr make( const std::string &remote_addr, const std::string &base_port); - - /* Expose internal timeslot filter API */ - virtual void ts_filter_set_tn(int tn) = 0; - virtual int ts_filter_get_tn(void) = 0; }; } // namespace gsm diff --git a/lib/misc_utils/trx_burst_if_impl.cc b/lib/misc_utils/trx_burst_if_impl.cc index 6d63edf..8f458b0 100644 --- a/lib/misc_utils/trx_burst_if_impl.cc +++ b/lib/misc_utils/trx_burst_if_impl.cc @@ -85,9 +85,6 @@ namespace gr { // Bind DATA interface handler d_data_sock->udp_rx_handler = boost::bind( &trx_burst_if_impl::handle_ul_burst, this, _1, _2); - - // Init timeslot filter - d_ts_filter_tn = -1; } /* @@ -99,21 +96,6 @@ namespace gr { delete d_data_sock; } - /* - * Timeslot filter API (getter and setter) - */ - void - trx_burst_if_impl::ts_filter_set_tn(int tn) - { - d_ts_filter_tn = (tn >= 0 && tn <= 7) ? tn : -1; - } - - int - trx_burst_if_impl::ts_filter_get_tn(void) - { - return d_ts_filter_tn; - } - /* * Check if burst is a RACH burst */ @@ -190,10 +172,6 @@ namespace gr { // Compose a new UDP payload with burst burst_pack(msg, buf); - // Timeslot filter - if (d_ts_filter_tn != -1 && buf[0] != d_ts_filter_tn) - return; - // Send a burst d_data_sock->udp_send(buf, 158); } diff --git a/lib/misc_utils/trx_burst_if_impl.h b/lib/misc_utils/trx_burst_if_impl.h index fd5a42d..35f939c 100644 --- a/lib/misc_utils/trx_burst_if_impl.h +++ b/lib/misc_utils/trx_burst_if_impl.h @@ -35,7 +35,6 @@ namespace gr { { private: udp_socket *d_data_sock; - int d_ts_filter_tn; bool detect_rach(uint8_t *burst); void burst_pack(pmt::pmt_t msg, uint8_t *buf); @@ -44,10 +43,6 @@ namespace gr { trx_burst_if_impl(const std::string &remote_addr, int base_port); ~trx_burst_if_impl(); - /* Timeslot filter API */ - void ts_filter_set_tn(int tn); - int ts_filter_get_tn(void); - void handle_dl_burst(pmt::pmt_t msg); void handle_ul_burst(uint8_t *payload, size_t len); }; diff --git a/python/trx/ctrl_if_bb.py b/python/trx/ctrl_if_bb.py index b08f62c..77e02d0 100644 --- a/python/trx/ctrl_if_bb.py +++ b/python/trx/ctrl_if_bb.py @@ -22,6 +22,7 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +import grgsm from ctrl_if import ctrl_if class ctrl_if_bb(ctrl_if): @@ -107,14 +108,18 @@ class ctrl_if_bb(ctrl_if): return -1 # Ignore timeslot type for now - # Value 0 means 'drop all' - config = -1 if int(request[2]) == 0 else tn - + config = int(request[2]) print("[i] Configure timeslot filter to: %s" - % ("drop all" if config == -1 else "TS %d" % tn)) - - # HACK: configure built-in timeslot filter - self.tb.gsm_trx_if.ts_filter_set_tn(config) + % ("drop all" if config == 0 else "TS %d" % tn)) + + if config == 0: + # Value 0 means 'drop all' + self.tb.gsm_ts_filter.set_policy( + grgsm.FILTER_POLICY_DROP_ALL) + else: + self.tb.gsm_ts_filter.set_policy( + grgsm.FILTER_POLICY_DEFAULT) + self.tb.gsm_ts_filter.set_tn(tn) return 0 diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py index 661025a..5791f42 100644 --- a/python/trx/radio_if.py +++ b/python/trx/radio_if.py @@ -98,6 +98,9 @@ class radio_if(gr.top_block): self.gsm_clck_ctrl = grgsm.clock_offset_control( shift_fc, self.samp_rate, osr = 4) + self.gsm_ts_filter = grgsm.burst_timeslot_filter(0) + self.gsm_ts_filter.set_policy(grgsm.FILTER_POLICY_DROP_ALL) + self.gsm_trx_burst_if = grgsm.trx_burst_if( self.trx_remote_addr, str(self.trx_base_port)) @@ -115,6 +118,9 @@ class radio_if(gr.top_block): (self.gsm_input, 'ctrl_in')) self.msg_connect((self.gsm_receiver, 'C0'), + (self.gsm_ts_filter, 'in')) + + self.msg_connect((self.gsm_ts_filter, 'out'), (self.gsm_trx_burst_if, 'bursts')) def check_available(self): -- cgit v1.2.3 From 5d68aa5620666a8ba84ca41eecd8f7987a869119 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 17 Oct 2017 11:14:48 +0700 Subject: apps/grgsm_trx: get rid of unused subdev_spec This could be specified via the device_args, for example: "subdev=B:0". --- apps/grgsm_trx | 13 ++++--------- python/trx/radio_if.py | 7 ++----- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/apps/grgsm_trx b/apps/grgsm_trx index a5cb1ee..7886b12 100755 --- a/apps/grgsm_trx +++ b/apps/grgsm_trx @@ -43,7 +43,6 @@ class Application: # PHY specific phy_sample_rate = 2000000 - phy_subdev_spec = False phy_gain = 30 phy_args = "" phy_ppm = 0 @@ -57,9 +56,8 @@ class Application: def run(self): # Init Radio interface - self.radio = radio_if(self.phy_args, self.phy_subdev_spec, - self.phy_sample_rate, self.phy_gain, self.phy_ppm, - self.remote_addr, self.base_port) + self.radio = radio_if(self.phy_args, self.phy_sample_rate, + self.phy_gain, self.phy_ppm, self.remote_addr, self.base_port) # Power measurement emulation # Noise: -120 .. -105 @@ -99,7 +97,6 @@ class Application: s += " Radio interface specific\n" \ " -a --device-args Set device arguments\n" \ " -s --sample-rate Set PHY sample rate (default 2000000)\n" \ - " -S --subdev-spec Set PHY sub-device specification\n" \ " -g --gain Set PHY gain (default 30)\n" \ " --ppm Set PHY frequency correction (default 0)\n" @@ -108,9 +105,9 @@ class Application: def parse_argv(self): try: opts, args = getopt.getopt(sys.argv[1:], - "a:p:i:s:S:g:h", + "a:p:i:s:g:h", ["help", "remote-addr=", "base-port=", "device-args=", - "gain=", "subdev-spec=", "sample-rate=", "ppm="]) + "gain=", "sample-rate=", "ppm="]) except getopt.GetoptError as err: # Print(help and exit) self.print_help() @@ -137,8 +134,6 @@ class Application: self.phy_args = v elif o in ("-g", "--gain"): self.phy_gain = int(v) - elif o in ("-S", "--subdev-spec"): - self.phy_subdev_spec = v elif o in ("-s", "--sample-rate"): self.phy_sample_rate = int(v) elif o in ("--ppm"): diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py index 5791f42..a6cd23c 100644 --- a/python/trx/radio_if.py +++ b/python/trx/radio_if.py @@ -36,7 +36,6 @@ class radio_if(gr.top_block): # PHY specific variables samp_rate = 2000000 shiftoff = 400e3 - subdev_spec = "" # TODO: use it device_args = "" fc = 941.6e6 # TODO: set ARFCN to 0? gain = 30 @@ -46,9 +45,8 @@ class radio_if(gr.top_block): trx_started = False fc_set = False - def __init__(self, phy_args, phy_subdev_spec, - phy_sample_rate, phy_gain, phy_ppm, - trx_remote_addr, trx_base_port): + def __init__(self, phy_args, phy_sample_rate, phy_gain, phy_ppm, + trx_remote_addr, trx_base_port): print("[i] Init Radio interface") # TRX block specific variables @@ -56,7 +54,6 @@ class radio_if(gr.top_block): self.trx_base_port = trx_base_port # PHY specific variables - self.subdev_spec = phy_subdev_spec self.samp_rate = phy_sample_rate self.device_args = phy_args self.gain = phy_gain -- cgit v1.2.3 From 790b6f0cc10e8d4deea6611b52647ace7c3e2015 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 17 Oct 2017 11:47:36 +0700 Subject: apps/grgsm_trx: add cmd line arguments for TX chain --- apps/grgsm_trx | 35 +++++++++++++++++++++++++---------- python/trx/radio_if.py | 22 ++++++++++------------ 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/apps/grgsm_trx b/apps/grgsm_trx index 7886b12..670d919 100755 --- a/apps/grgsm_trx +++ b/apps/grgsm_trx @@ -43,7 +43,10 @@ class Application: # PHY specific phy_sample_rate = 2000000 - phy_gain = 30 + phy_tx_antenna = "TX/RX" + phy_rx_antenna = "RX2" + phy_rx_gain = 30 + phy_tx_gain = 10 phy_args = "" phy_ppm = 0 @@ -57,7 +60,9 @@ class Application: def run(self): # Init Radio interface self.radio = radio_if(self.phy_args, self.phy_sample_rate, - self.phy_gain, self.phy_ppm, self.remote_addr, self.base_port) + self.phy_rx_gain, self.phy_tx_gain, self.phy_ppm, + self.phy_rx_antenna, self.phy_tx_antenna, + self.remote_addr, self.base_port) # Power measurement emulation # Noise: -120 .. -105 @@ -90,24 +95,28 @@ class Application: # TRX specific s += " TRX interface specific\n" \ - " -s --remote-addr Set remote address (default 127.0.0.1)\n" \ + " -i --remote-addr Set remote address (default 127.0.0.1)\n" \ " -p --base-port Set base port number (default 5700)\n\n" # PHY specific s += " Radio interface specific\n" \ " -a --device-args Set device arguments\n" \ - " -s --sample-rate Set PHY sample rate (default 2000000)\n" \ - " -g --gain Set PHY gain (default 30)\n" \ - " --ppm Set PHY frequency correction (default 0)\n" + " -s --sample-rate Set sample rate (default 2000000)\n" \ + " -g --rx-gain Set RX gain (default 30)\n" \ + " -G --tx-gain Set TX gain (default 10)\n" \ + " --rx-antenna Set RX antenna (default RX2)\n" \ + " --tx-antenna Set TX antenna (default TX/RX)\n" \ + " --ppm Set frequency correction (default 0)\n" print(s) def parse_argv(self): try: opts, args = getopt.getopt(sys.argv[1:], - "a:p:i:s:g:h", + "i:p:a:s:g:G:h", ["help", "remote-addr=", "base-port=", "device-args=", - "gain=", "sample-rate=", "ppm="]) + "sample-rate=", "rx-gain=", "tx-gain=", "ppm=", + "rx-antenna", "tx-antenna"]) except getopt.GetoptError as err: # Print(help and exit) self.print_help() @@ -132,10 +141,16 @@ class Application: # PHY specific elif o in ("-a", "--device-args"): self.phy_args = v - elif o in ("-g", "--gain"): - self.phy_gain = int(v) elif o in ("-s", "--sample-rate"): self.phy_sample_rate = int(v) + elif o in ("-g", "--rx-gain"): + self.phy_rx_gain = int(v) + elif o in ("-G", "--tx-gain"): + self.phy_tx_gain = int(v) + elif o in ("--rx-antenna"): + self.phy_rx_antenna = v + elif o in ("--tx-antenna"): + self.phy_tx_antenna = v elif o in ("--ppm"): self.phy_ppm = int(v) diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py index a6cd23c..0164cde 100644 --- a/python/trx/radio_if.py +++ b/python/trx/radio_if.py @@ -45,18 +45,17 @@ class radio_if(gr.top_block): trx_started = False fc_set = False - def __init__(self, phy_args, phy_sample_rate, phy_gain, phy_ppm, + def __init__(self, phy_args, phy_sample_rate, + phy_rx_gain, phy_tx_gain, phy_ppm, + phy_rx_antenna, phy_tx_antenna, trx_remote_addr, trx_base_port): - print("[i] Init Radio interface") - # TRX block specific variables - self.trx_remote_addr = trx_remote_addr - self.trx_base_port = trx_base_port + print("[i] Init Radio interface") # PHY specific variables self.samp_rate = phy_sample_rate - self.device_args = phy_args - self.gain = phy_gain + self.rx_gain = phy_rx_gain + self.tx_gain = phy_tx_gain self.ppm = phy_ppm gr.top_block.__init__(self, "GR-GSM TRX") @@ -65,8 +64,7 @@ class radio_if(gr.top_block): ################################################## # PHY Definition ################################################## - self.phy = osmosdr.source( - args = "numchan=%d %s" % (1, self.device_args)) + self.phy = osmosdr.source(args = "numchan=%d %s" % (1, phy_args)) self.phy.set_bandwidth(250e3 + abs(self.shiftoff), 0) self.phy.set_center_freq(shift_fc, 0) @@ -75,10 +73,10 @@ class radio_if(gr.top_block): self.phy.set_iq_balance_mode(2, 0) self.phy.set_dc_offset_mode(2, 0) self.phy.set_gain_mode(False, 0) - self.phy.set_gain(self.gain, 0) + self.phy.set_gain(self.rx_gain, 0) self.phy.set_if_gain(20, 0) self.phy.set_bb_gain(20, 0) - self.phy.set_antenna("", 0) + self.phy.set_antenna(phy_rx_antenna, 0) ################################################## # GR-GSM Magic @@ -99,7 +97,7 @@ class radio_if(gr.top_block): self.gsm_ts_filter.set_policy(grgsm.FILTER_POLICY_DROP_ALL) self.gsm_trx_burst_if = grgsm.trx_burst_if( - self.trx_remote_addr, str(self.trx_base_port)) + trx_remote_addr, str(trx_base_port)) ################################################## # Connections -- cgit v1.2.3 From 9baaec24c6d0a1ffeb66000089d1f41a0d29bac9 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 18 Oct 2017 18:15:52 +0700 Subject: trx/radio_if.py: get rid of useless getters / setters We are only going to change the RF frequency and gain at runtime. Other parameters (like sample rate) should remain unchanged. --- python/trx/radio_if.py | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py index 0164cde..97a2160 100644 --- a/python/trx/radio_if.py +++ b/python/trx/radio_if.py @@ -126,51 +126,12 @@ class radio_if(gr.top_block): self.stop() self.wait() - def get_args(self): - return self.args - - def set_args(self, args): - self.args = args - - def get_fc(self): - return self.fc - def set_fc(self, fc): self.phy.set_center_freq(fc - self.shiftoff, 0) self.gsm_input.set_fc(fc) self.fc_set = True self.fc = fc - def get_gain(self): - return self.gain - def set_gain(self, gain): self.phy.set_gain(gain, 0) self.gain = gain - - def get_ppm(self): - return self.ppm - - def set_ppm(self, ppm): - self.rtlsdr_source_0.set_freq_corr(ppm, 0) - self.ppm = ppm - - def get_samp_rate(self): - return self.samp_rate - - def set_samp_rate(self, samp_rate): - self.blocks_rotator.set_phase_inc( - -2 * pi * self.shiftoff / samp_rate) - self.gsm_input.set_samp_rate_in(samp_rate) - self.phy.set_sample_rate(samp_rate) - self.samp_rate = samp_rate - - def get_shiftoff(self): - return self.shiftoff - - def set_shiftoff(self, shiftoff): - self.blocks_rotator.set_phase_inc( - -2 * pi * shiftoff / self.samp_rate) - self.phy.set_bandwidth(250e3 + abs(shiftoff), 0) - self.phy.set_center_freq(self.fc - shiftoff, 0) - self.shiftoff = shiftoff -- cgit v1.2.3 From da5e21f1234b00435834e98e47db7901d98afe91 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 18 Oct 2017 18:24:48 +0700 Subject: trx/radio_if.py: clean up the stored fields Only the fields that are going to be changed / used at runtime should be stored in the radio_if instance. --- python/trx/radio_if.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py index 97a2160..559c309 100644 --- a/python/trx/radio_if.py +++ b/python/trx/radio_if.py @@ -34,12 +34,8 @@ from gnuradio import gr class radio_if(gr.top_block): # PHY specific variables - samp_rate = 2000000 shiftoff = 400e3 - device_args = "" fc = 941.6e6 # TODO: set ARFCN to 0? - gain = 30 - ppm = 0 # Application state flags trx_started = False @@ -53,10 +49,8 @@ class radio_if(gr.top_block): print("[i] Init Radio interface") # PHY specific variables - self.samp_rate = phy_sample_rate self.rx_gain = phy_rx_gain self.tx_gain = phy_tx_gain - self.ppm = phy_ppm gr.top_block.__init__(self, "GR-GSM TRX") shift_fc = self.fc - self.shiftoff @@ -68,8 +62,8 @@ class radio_if(gr.top_block): self.phy.set_bandwidth(250e3 + abs(self.shiftoff), 0) self.phy.set_center_freq(shift_fc, 0) - self.phy.set_sample_rate(self.samp_rate) - self.phy.set_freq_corr(self.ppm, 0) + self.phy.set_sample_rate(phy_sample_rate) + self.phy.set_freq_corr(phy_ppm, 0) self.phy.set_iq_balance_mode(2, 0) self.phy.set_dc_offset_mode(2, 0) self.phy.set_gain_mode(False, 0) @@ -82,16 +76,16 @@ class radio_if(gr.top_block): # GR-GSM Magic ################################################## self.blocks_rotator = blocks.rotator_cc( - -2 * pi * self.shiftoff / self.samp_rate) + -2 * pi * self.shiftoff / phy_sample_rate) self.gsm_input = grgsm.gsm_input( - ppm = self.ppm, osr = 4, fc = self.fc, - samp_rate_in = self.samp_rate) + ppm = phy_ppm, osr = 4, fc = self.fc, + samp_rate_in = phy_sample_rate) self.gsm_receiver = grgsm.receiver(4, ([0]), ([])) self.gsm_clck_ctrl = grgsm.clock_offset_control( - shift_fc, self.samp_rate, osr = 4) + shift_fc, phy_sample_rate, osr = 4) self.gsm_ts_filter = grgsm.burst_timeslot_filter(0) self.gsm_ts_filter.set_policy(grgsm.FILTER_POLICY_DROP_ALL) -- cgit v1.2.3 From 01c6afd49501e53fd5b01f6ee9818811db69f82b Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 19 Oct 2017 01:14:24 +0700 Subject: trx/radio_if.py: fix RX / TX gain control --- python/trx/ctrl_if_bb.py | 12 +++++++++++- python/trx/radio_if.py | 8 ++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/python/trx/ctrl_if_bb.py b/python/trx/ctrl_if_bb.py index 77e02d0..99c0451 100644 --- a/python/trx/ctrl_if_bb.py +++ b/python/trx/ctrl_if_bb.py @@ -72,12 +72,22 @@ class ctrl_if_bb(ctrl_if): return 0 + # Gain control elif self.verify_cmd(request, "SETRXGAIN", 1): print("[i] Recv SETRXGAIN cmd") # TODO: check gain value gain = int(request[1]) - self.tb.set_gain(gain) + self.tb.set_rx_gain(gain) + + return 0 + + elif self.verify_cmd(request, "SETTXGAIN", 1): + print("[i] Recv SETTXGAIN cmd") + + # TODO: check gain value + gain = int(request[1]) + self.tb.set_tx_gain(gain) return 0 diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py index 559c309..d8c0444 100644 --- a/python/trx/radio_if.py +++ b/python/trx/radio_if.py @@ -126,6 +126,10 @@ class radio_if(gr.top_block): self.fc_set = True self.fc = fc - def set_gain(self, gain): + def set_rx_gain(self, gain): self.phy.set_gain(gain, 0) - self.gain = gain + self.rx_gain = gain + + def set_tx_gain(self, gain): + # TODO: TX chain not implemented yet + self.tx_gain = gain -- cgit v1.2.3 From acc365f2f19e2fc6fcc6a76cd4ea69bfd14120ab Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Tue, 7 Nov 2017 19:31:42 +0100 Subject: Added C++ version of burst type filter --- grc/flow_control/CMakeLists.txt | 1 + grc/flow_control/gsm_burst_type_filter.xml | 32 ++++++++ grc/gsm_block_tree.xml | 1 + include/grgsm/flow_control/CMakeLists.txt | 1 + include/grgsm/flow_control/burst_type_filter.h | 63 +++++++++++++++ lib/flow_control/CMakeLists.txt | 1 + lib/flow_control/burst_type_filter_impl.cc | 104 +++++++++++++++++++++++++ lib/flow_control/burst_type_filter_impl.h | 55 +++++++++++++ swig/grgsm_swig.i | 3 + 9 files changed, 261 insertions(+) create mode 100644 grc/flow_control/gsm_burst_type_filter.xml create mode 100644 include/grgsm/flow_control/burst_type_filter.h create mode 100644 lib/flow_control/burst_type_filter_impl.cc create mode 100644 lib/flow_control/burst_type_filter_impl.h diff --git a/grc/flow_control/CMakeLists.txt b/grc/flow_control/CMakeLists.txt index a6a7319..1f98d8f 100644 --- a/grc/flow_control/CMakeLists.txt +++ b/grc/flow_control/CMakeLists.txt @@ -21,6 +21,7 @@ install(FILES gsm_burst_timeslot_splitter.xml gsm_burst_fnr_filter.xml gsm_burst_timeslot_filter.xml + gsm_burst_type_filter.xml gsm_dummy_burst_filter.xml gsm_burst_sdcch_subslot_splitter.xml gsm_burst_sdcch_subslot_filter.xml diff --git a/grc/flow_control/gsm_burst_type_filter.xml b/grc/flow_control/gsm_burst_type_filter.xml new file mode 100644 index 0000000..a615961 --- /dev/null +++ b/grc/flow_control/gsm_burst_type_filter.xml @@ -0,0 +1,32 @@ + + + Burst Type Filter + gsm_burst_type_filter + import grgsm + grgsm.burst_type_filter($selected_burst_types) + + + Selected burst types + selected_burst_types + [0,1,2,3,4,5,6,7] + int_vector + + + + in + message + 1 + + + + out + message + 1 + + + +This block filters bursts based on their type. + +For more information on burst types, see GSM 05.02. + + diff --git a/grc/gsm_block_tree.xml b/grc/gsm_block_tree.xml index 479bdb4..225c28f 100644 --- a/grc/gsm_block_tree.xml +++ b/grc/gsm_block_tree.xml @@ -51,6 +51,7 @@ gsm_burst_timeslot_filter gsm_burst_sdcch_subslot_filter gsm_burst_fnr_filter + gsm_burst_type_filter gsm_dummy_burst_filter gsm_uplink_downlink_splitter diff --git a/include/grgsm/flow_control/CMakeLists.txt b/include/grgsm/flow_control/CMakeLists.txt index 322c8c8..d86f1c7 100644 --- a/include/grgsm/flow_control/CMakeLists.txt +++ b/include/grgsm/flow_control/CMakeLists.txt @@ -27,6 +27,7 @@ install(FILES burst_timeslot_filter.h burst_sdcch_subslot_filter.h burst_fnr_filter.h + burst_type_filter.h dummy_burst_filter.h uplink_downlink_splitter.h DESTINATION include/grgsm/flow_control ) diff --git a/include/grgsm/flow_control/burst_type_filter.h b/include/grgsm/flow_control/burst_type_filter.h new file mode 100644 index 0000000..6430039 --- /dev/null +++ b/include/grgsm/flow_control/burst_type_filter.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* @file + * @author (C) 2017 by Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef INCLUDED_GSM_BURST_TYPE_FILTER_H +#define INCLUDED_GSM_BURST_TYPE_FILTER_H + +#include +#include +#include + +namespace gr { + namespace gsm { + + /*! + * \brief <+description of block+> + * \ingroup gsm + * + */ + class GRGSM_API burst_type_filter : virtual public gr::block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of grgsm::burst_type_filter. + * + * To avoid accidental use of raw pointers, grgsm::burst_type_filter's + * constructor is in a private implementation + * class. grgsm::burst_type_filter::make is the public interface for + * creating new instances. + */ + + static sptr make(const std::vector & selected_burst_types); + + /* External API */ + /* Filtering policy */ + virtual filter_policy get_policy(void) = 0; + virtual filter_policy set_policy(filter_policy policy) = 0; + virtual void set_selected_burst_types(const std::vector & selected_burst_types) = 0; + }; + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GSM_BURST_TYPE_FILTER_H */ diff --git a/lib/flow_control/CMakeLists.txt b/lib/flow_control/CMakeLists.txt index 30a5f50..b8f63f7 100644 --- a/lib/flow_control/CMakeLists.txt +++ b/lib/flow_control/CMakeLists.txt @@ -23,6 +23,7 @@ add_sources( burst_sdcch_subslot_splitter_impl.cc burst_timeslot_filter_impl.cc burst_timeslot_splitter_impl.cc + burst_type_filter_impl.cc dummy_burst_filter_impl.cc uplink_downlink_splitter_impl.cc ) diff --git a/lib/flow_control/burst_type_filter_impl.cc b/lib/flow_control/burst_type_filter_impl.cc new file mode 100644 index 0000000..542a004 --- /dev/null +++ b/lib/flow_control/burst_type_filter_impl.cc @@ -0,0 +1,104 @@ +/* -*- c++ -*- */ +/* @file + * @author (C) 2017 by Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "burst_type_filter_impl.h" +#include +#include +#include + + +namespace gr { + namespace gsm { + + burst_type_filter::sptr + burst_type_filter::make(const std::vector & selected_burst_types) + { + return gnuradio::get_initial_sptr + (new burst_type_filter_impl(selected_burst_types)); + } + + /* + * The private constructor + */ + burst_type_filter_impl::burst_type_filter_impl(const std::vector & selected_burst_types) + : gr::block("burst_type_filter", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), + d_filter_policy(FILTER_POLICY_DEFAULT) + { + set_selected_burst_types(selected_burst_types); + + message_port_register_in(pmt::mp("in")); + message_port_register_out(pmt::mp("out")); + + set_msg_handler(pmt::mp("in"), boost::bind(&burst_type_filter_impl::process_burst, this, _1)); + } + + /* + * Our virtual destructor. + */ + burst_type_filter_impl::~burst_type_filter_impl() {} + + void burst_type_filter_impl::process_burst(pmt::pmt_t msg) + { + if (d_filter_policy == FILTER_POLICY_DROP_ALL) + return; + + if (d_filter_policy == FILTER_POLICY_PASS_ALL) { + message_port_pub(pmt::mp("out"), msg); + return; + } + + gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(pmt::cdr(msg)); +// std::cout << "header->type: " << (int)(header->sub_type) << std::endl; + if (std::find(d_selected_burst_types.begin(), d_selected_burst_types.end(), header->sub_type) != d_selected_burst_types.end()) //check if burst type is listed in burst types to pass + { + message_port_pub(pmt::mp("out"), msg); + } + } + + /* Filtering policy */ + filter_policy + burst_type_filter_impl::get_policy(void) + { + return d_filter_policy; + } + + filter_policy + burst_type_filter_impl::set_policy(filter_policy policy) + { + d_filter_policy = policy; + return d_filter_policy; + } + + void + burst_type_filter_impl::set_selected_burst_types(const std::vector & selected_burst_types) + { + d_selected_burst_types.assign(selected_burst_types.begin(), selected_burst_types.end()); + } + } /* namespace gsm */ +} /* namespace gr */ diff --git a/lib/flow_control/burst_type_filter_impl.h b/lib/flow_control/burst_type_filter_impl.h new file mode 100644 index 0000000..5c6ad14 --- /dev/null +++ b/lib/flow_control/burst_type_filter_impl.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* @file + * @author (C) 2017 by Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef INCLUDED_GSM_BURST_TYPE_FILTER_IMPL_H +#define INCLUDED_GSM_BURST_TYPE_FILTER_IMPL_H + +#define BURST_TYPE_LEN 148 + +#include + +namespace gr { + namespace gsm { + + class burst_type_filter_impl : public burst_type_filter + { + private: + filter_policy d_filter_policy; + std::vector d_selected_burst_types; + public: + burst_type_filter_impl(const std::vector & selected_burst_types); + ~burst_type_filter_impl(); + void process_burst(pmt::pmt_t msg); + + /* External API */ + /* Filtering policy */ + filter_policy get_policy(void); + filter_policy set_policy(filter_policy policy); + + void set_selected_burst_types(const std::vector & selected_burst_types); + }; + + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GSM_BURST_TYPE_FILTER_IMPL_H */ + diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i index 4901b44..26b6a6d 100644 --- a/swig/grgsm_swig.i +++ b/swig/grgsm_swig.i @@ -47,6 +47,7 @@ #include "grgsm/flow_control/burst_timeslot_filter.h" #include "grgsm/flow_control/burst_sdcch_subslot_filter.h" #include "grgsm/flow_control/burst_fnr_filter.h" +#include "grgsm/flow_control/burst_type_filter.h" #include "grgsm/flow_control/dummy_burst_filter.h" #include "grgsm/flow_control/uplink_downlink_splitter.h" #include "grgsm/misc_utils/bursts_printer.h" @@ -106,6 +107,8 @@ GR_SWIG_BLOCK_MAGIC2(gsm, burst_timeslot_filter); GR_SWIG_BLOCK_MAGIC2(gsm, burst_sdcch_subslot_filter); %include "grgsm/flow_control/burst_fnr_filter.h" GR_SWIG_BLOCK_MAGIC2(gsm, burst_fnr_filter); +%include "grgsm/flow_control/burst_type_filter.h" +GR_SWIG_BLOCK_MAGIC2(gsm, burst_type_filter); %include "grgsm/flow_control/dummy_burst_filter.h" GR_SWIG_BLOCK_MAGIC2(gsm, dummy_burst_filter); %include "grgsm/flow_control/uplink_downlink_splitter.h" -- cgit v1.2.3 From d7efc05b7981aa2196a9b8d62ffdae53b5db1069 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Tue, 7 Nov 2017 19:33:22 +0100 Subject: Moved gsm_constants file to include directory --- include/grgsm/CMakeLists.txt | 1 + include/grgsm/gsm_constants.h | 178 ++++++++++++++++++++++++++++++ lib/decoding/sch.c | 2 +- lib/receiver/clock_offset_control_impl.cc | 2 +- lib/receiver/gsm_constants.h | 177 ----------------------------- lib/receiver/receiver_config.h | 2 +- lib/receiver/receiver_impl.h | 2 +- lib/receiver/viterbi_detector.cc | 2 +- 8 files changed, 184 insertions(+), 182 deletions(-) create mode 100644 include/grgsm/gsm_constants.h delete mode 100644 lib/receiver/gsm_constants.h diff --git a/include/grgsm/CMakeLists.txt b/include/grgsm/CMakeLists.txt index 0b58018..2f76929 100644 --- a/include/grgsm/CMakeLists.txt +++ b/include/grgsm/CMakeLists.txt @@ -25,6 +25,7 @@ install(FILES api.h gsmtap.h constants.h + gsm_constants.h DESTINATION include/grgsm ) diff --git a/include/grgsm/gsm_constants.h b/include/grgsm/gsm_constants.h new file mode 100644 index 0000000..fd1d9e7 --- /dev/null +++ b/include/grgsm/gsm_constants.h @@ -0,0 +1,178 @@ +/* -*- c++ -*- */ +/* + * @file + * @author (C) 2014 by Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GSM_CONSTANTS_H +#define INCLUDED_GSM_CONSTANTS_H + +#define GSM_SYMBOL_RATE (1625000.0/6.0) //symbols per second +#define GSM_SYMBOL_PERIOD (1.0/GSM_SYMBOL_RATE) //seconds per symbol + +//Burst timing +#define TAIL_BITS 3 +#define GUARD_BITS 8 +#define GUARD_FRACTIONAL 0.25 //fractional part of guard period +#define GUARD_PERIOD GUARD_BITS + GUARD_FRACTIONAL +#define DATA_BITS 57 //size of 1 data block in normal burst +#define STEALING_BIT 1 +#define N_TRAIN_BITS 26 +#define N_SYNC_BITS 64 +#define USEFUL_BITS 142 //(2*(DATA_BITS+STEALING_BIT) + N_TRAIN_BITS ) +#define FCCH_BITS USEFUL_BITS +#define BURST_SIZE (USEFUL_BITS+2*TAIL_BITS) +#define ACCESS_BURST_SIZE 87 +#define PROCESSED_CHUNK BURST_SIZE+2*GUARD_PERIOD + +#define SCH_DATA_LEN 39 +#define TS_BITS (TAIL_BITS+USEFUL_BITS+TAIL_BITS+GUARD_BITS) //a full TS (156 bits) +#define TS_PER_FRAME 8 +#define FRAME_BITS (TS_PER_FRAME * TS_BITS + 2) // 156.25 * 8 +#define FCCH_POS TAIL_BITS +#define SYNC_POS 39 +#define TRAIN_POS ( TAIL_BITS + (DATA_BITS+STEALING_BIT) + 5) //first 5 bits of a training sequence + //aren't used for channel impulse response estimation +#define TRAIN_BEGINNING 5 +#define SAFETY_MARGIN 6 // + +#define FCCH_HITS_NEEDED (USEFUL_BITS - 4) +#define FCCH_MAX_MISSES 1 +#define FCCH_MAX_FREQ_OFFSET 100 + +#define CHAN_IMP_RESP_LENGTH 5 + +#define MAX_SCH_ERRORS 10 //maximum number of subsequent sch errors after which gsm receiver goes to find_next_fcch state + +typedef enum {empty, fcch_burst, sch_burst, normal_burst, rach_burst, dummy, dummy_or_normal, normal_or_noise} burst_type; +typedef enum {unknown, multiframe_26, multiframe_51} multiframe_type; + +static const unsigned char SYNC_BITS[] = { + 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, + 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1 +}; + +const unsigned FCCH_FRAMES[] = {0, 10, 20, 30, 40}; +const unsigned SCH_FRAMES[] = {1, 11, 21, 31, 41}; + +const unsigned BCCH_FRAMES[] = {2, 3, 4, 5}; //!!the receiver shouldn't care about logical + //!!channels so this will be removed from this header +const unsigned TEST_CCH_FRAMES[] = {2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 17, 18, 19, 22, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 38, 39, 42, 43, 44, 45, 46, 47, 48, 49}; +const unsigned TRAFFIC_CHANNEL_F[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}; +const unsigned TEST51[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50}; + + +#define TSC0 0 +#define TSC1 1 +#define TSC2 2 +#define TSC3 3 +#define TSC4 4 +#define TSC5 5 +#define TSC6 6 +#define TSC7 7 +#define TS_DUMMY 8 + +#define TRAIN_SEQ_NUM 9 + +#define TIMESLOT0 0 +#define TIMESLOT1 1 +#define TIMESLOT2 2 +#define TIMESLOT3 3 +#define TIMESLOT4 4 +#define TIMESLOT5 5 +#define TIMESLOT6 6 +#define TIMESLOT7 7 + + +static const unsigned char train_seq[TRAIN_SEQ_NUM][N_TRAIN_BITS] = { + {0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1}, + {0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1}, + {0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0}, + {0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0}, + {0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1}, + {0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0}, + {1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1}, + {1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0}, + {0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1} // DUMMY +}; + + +//Dummy burst 0xFB 76 0A 4E 09 10 1F 1C 5C 5C 57 4A 33 39 E9 F1 2F A8 +static const unsigned char dummy_burst[] = { + 0, 0, 0, + 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, + 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, + 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, + 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 0, 0, + + 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, + 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, + 0, 0, 0, 1, 0, 1, + + 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, + 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, + 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, + 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, + 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, + 1, 1, 1, 0, 1, 0, 1, 0, + 0, 0, 0 +}; + + +/* + * The frequency correction burst is used for frequency synchronization + * of the mobile. This is broadcast in TS0 together with the SCH and + * BCCH. + * + * Modulating the bits below causes a spike at 62.5kHz above (below for + * COMPACT) the center frequency. One can use this spike with a narrow + * band filter to accurately determine the center of the channel. + */ +static const unsigned char fc_fb[] = { + 0, 0, 0, //I don't use this tables, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //I copied this here from burst_types.h because + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //the description is very informative - p.krysik + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0 +}; + +static const unsigned char fc_compact_fb[] = { + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 +}; + + +#endif /* INCLUDED_GSM_CONSTANTS_H */ diff --git a/lib/decoding/sch.c b/lib/decoding/sch.c index 6d2e3eb..7af136c 100644 --- a/lib/decoding/sch.c +++ b/lib/decoding/sch.c @@ -21,7 +21,7 @@ */ #include -#include "gsm_constants.h" +#include #include "osmocom/coding/gsm0503_coding.h" #include diff --git a/lib/receiver/clock_offset_control_impl.cc b/lib/receiver/clock_offset_control_impl.cc index 868cbc2..d62c801 100644 --- a/lib/receiver/clock_offset_control_impl.cc +++ b/lib/receiver/clock_offset_control_impl.cc @@ -25,7 +25,7 @@ #endif #include -#include +#include #include "clock_offset_control_impl.h" namespace gr diff --git a/lib/receiver/gsm_constants.h b/lib/receiver/gsm_constants.h deleted file mode 100644 index 9052290..0000000 --- a/lib/receiver/gsm_constants.h +++ /dev/null @@ -1,177 +0,0 @@ -/* -*- c++ -*- */ -/* - * @file - * @author (C) 2014 by Piotr Krysik - * @section LICENSE - * - * Gr-gsm is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * Gr-gsm is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with gr-gsm; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GSM_CONSTANTS_H -#define INCLUDED_GSM_CONSTANTS_H - -#define GSM_SYMBOL_RATE (1625000.0/6.0) //symbols per second -#define GSM_SYMBOL_PERIOD (1.0/GSM_SYMBOL_RATE) //seconds per symbol - -//Burst timing -#define TAIL_BITS 3 -#define GUARD_BITS 8 -#define GUARD_FRACTIONAL 0.25 //fractional part of guard period -#define GUARD_PERIOD GUARD_BITS + GUARD_FRACTIONAL -#define DATA_BITS 57 //size of 1 data block in normal burst -#define STEALING_BIT 1 -#define N_TRAIN_BITS 26 -#define N_SYNC_BITS 64 -#define USEFUL_BITS 142 //(2*(DATA_BITS+STEALING_BIT) + N_TRAIN_BITS ) -#define FCCH_BITS USEFUL_BITS -#define BURST_SIZE (USEFUL_BITS+2*TAIL_BITS) -#define PROCESSED_CHUNK BURST_SIZE+2*GUARD_PERIOD - -#define SCH_DATA_LEN 39 -#define TS_BITS (TAIL_BITS+USEFUL_BITS+TAIL_BITS+GUARD_BITS) //a full TS (156 bits) -#define TS_PER_FRAME 8 -#define FRAME_BITS (TS_PER_FRAME * TS_BITS + 2) // 156.25 * 8 -#define FCCH_POS TAIL_BITS -#define SYNC_POS 39 -#define TRAIN_POS ( TAIL_BITS + (DATA_BITS+STEALING_BIT) + 5) //first 5 bits of a training sequence - //aren't used for channel impulse response estimation -#define TRAIN_BEGINNING 5 -#define SAFETY_MARGIN 6 // - -#define FCCH_HITS_NEEDED (USEFUL_BITS - 4) -#define FCCH_MAX_MISSES 1 -#define FCCH_MAX_FREQ_OFFSET 100 - -#define CHAN_IMP_RESP_LENGTH 5 - -#define MAX_SCH_ERRORS 10 //maximum number of subsequent sch errors after which gsm receiver goes to find_next_fcch state - -typedef enum {empty, fcch_burst, sch_burst, normal_burst, rach_burst, dummy, dummy_or_normal, normal_or_noise} burst_type; -typedef enum {unknown, multiframe_26, multiframe_51} multiframe_type; - -static const unsigned char SYNC_BITS[] = { - 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, - 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, - 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1 -}; - -const unsigned FCCH_FRAMES[] = {0, 10, 20, 30, 40}; -const unsigned SCH_FRAMES[] = {1, 11, 21, 31, 41}; - -const unsigned BCCH_FRAMES[] = {2, 3, 4, 5}; //!!the receiver shouldn't care about logical - //!!channels so this will be removed from this header -const unsigned TEST_CCH_FRAMES[] = {2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 17, 18, 19, 22, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 38, 39, 42, 43, 44, 45, 46, 47, 48, 49}; -const unsigned TRAFFIC_CHANNEL_F[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}; -const unsigned TEST51[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50}; - - -#define TSC0 0 -#define TSC1 1 -#define TSC2 2 -#define TSC3 3 -#define TSC4 4 -#define TSC5 5 -#define TSC6 6 -#define TSC7 7 -#define TS_DUMMY 8 - -#define TRAIN_SEQ_NUM 9 - -#define TIMESLOT0 0 -#define TIMESLOT1 1 -#define TIMESLOT2 2 -#define TIMESLOT3 3 -#define TIMESLOT4 4 -#define TIMESLOT5 5 -#define TIMESLOT6 6 -#define TIMESLOT7 7 - - -static const unsigned char train_seq[TRAIN_SEQ_NUM][N_TRAIN_BITS] = { - {0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1}, - {0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1}, - {0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0}, - {0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0}, - {0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1}, - {0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0}, - {1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1}, - {1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0}, - {0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1} // DUMMY -}; - - -//Dummy burst 0xFB 76 0A 4E 09 10 1F 1C 5C 5C 57 4A 33 39 E9 F1 2F A8 -static const unsigned char dummy_burst[] = { - 0, 0, 0, - 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, - 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, - 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, - 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 1, 1, 0, 0, - - 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, - 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, - 0, 0, 0, 1, 0, 1, - - 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, - 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, - 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, - 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, - 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, - 1, 1, 1, 0, 1, 0, 1, 0, - 0, 0, 0 -}; - - -/* - * The frequency correction burst is used for frequency synchronization - * of the mobile. This is broadcast in TS0 together with the SCH and - * BCCH. - * - * Modulating the bits below causes a spike at 62.5kHz above (below for - * COMPACT) the center frequency. One can use this spike with a narrow - * band filter to accurately determine the center of the channel. - */ -static const unsigned char fc_fb[] = { - 0, 0, 0, //I don't use this tables, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //I copied this here from burst_types.h because - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //the description is very informative - p.krysik - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0 -}; - -static const unsigned char fc_compact_fb[] = { - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 -}; - - -#endif /* INCLUDED_GSM_CONSTANTS_H */ diff --git a/lib/receiver/receiver_config.h b/lib/receiver/receiver_config.h index f68e3f6..0fcd68d 100644 --- a/lib/receiver/receiver_config.h +++ b/lib/receiver/receiver_config.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include class multiframe_configuration { diff --git a/lib/receiver/receiver_impl.h b/lib/receiver/receiver_impl.h index d43bb27..c216d90 100644 --- a/lib/receiver/receiver_impl.h +++ b/lib/receiver/receiver_impl.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include #include "time_sample_ref.h" diff --git a/lib/receiver/viterbi_detector.cc b/lib/receiver/viterbi_detector.cc index 4e8fb3a..3dce379 100644 --- a/lib/receiver/viterbi_detector.cc +++ b/lib/receiver/viterbi_detector.cc @@ -56,7 +56,7 @@ */ #include -#include +#include #include #define PATHS_NUM (1 << (CHAN_IMP_RESP_LENGTH-1)) -- cgit v1.2.3 From ccb5e689e1fce642c23ddfb091bee7bedffd0b55 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Tue, 7 Nov 2017 19:34:22 +0100 Subject: Added tx bursts preprocessing block --- grc/gsm_block_tree.xml | 1 + grc/transmitter/CMakeLists.txt | 3 +- grc/transmitter/preprocess_tx_burst.xml | 19 ++++++ include/grgsm/transmitter/CMakeLists.txt | 4 +- include/grgsm/transmitter/preprocess_tx_burst.h | 60 +++++++++++++++++ lib/transmitter/CMakeLists.txt | 1 + lib/transmitter/preprocess_tx_burst_impl.cc | 85 +++++++++++++++++++++++++ lib/transmitter/preprocess_tx_burst_impl.h | 47 ++++++++++++++ swig/grgsm_swig.i | 3 + 9 files changed, 221 insertions(+), 2 deletions(-) create mode 100644 grc/transmitter/preprocess_tx_burst.xml create mode 100644 include/grgsm/transmitter/preprocess_tx_burst.h create mode 100644 lib/transmitter/preprocess_tx_burst_impl.cc create mode 100644 lib/transmitter/preprocess_tx_burst_impl.h diff --git a/grc/gsm_block_tree.xml b/grc/gsm_block_tree.xml index 225c28f..dd971ab 100644 --- a/grc/gsm_block_tree.xml +++ b/grc/gsm_block_tree.xml @@ -26,6 +26,7 @@ gsm_txtime_bursts_tagger gsm_txtime_setter gsm_gmsk_mod + gsm_preprocess_tx_burst Logical channels demapping diff --git a/grc/transmitter/CMakeLists.txt b/grc/transmitter/CMakeLists.txt index e512d10..0905e19 100644 --- a/grc/transmitter/CMakeLists.txt +++ b/grc/transmitter/CMakeLists.txt @@ -20,5 +20,6 @@ install(FILES gsm_gmsk_mod.xml gsm_txtime_bursts_tagger.xml - gsm_txtime_setter.xml DESTINATION share/gnuradio/grc/blocks + gsm_txtime_setter.xml + preprocess_tx_burst.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/transmitter/preprocess_tx_burst.xml b/grc/transmitter/preprocess_tx_burst.xml new file mode 100644 index 0000000..70b447e --- /dev/null +++ b/grc/transmitter/preprocess_tx_burst.xml @@ -0,0 +1,19 @@ + + + Preprocess Tx burst + gsm_preprocess_tx_burst + import grgsm + grgsm.preprocess_tx_burst() + + + bursts_in + message + 1 + + + + bursts_out + message + 1 + + diff --git a/include/grgsm/transmitter/CMakeLists.txt b/include/grgsm/transmitter/CMakeLists.txt index 78aad43..29ccc4b 100644 --- a/include/grgsm/transmitter/CMakeLists.txt +++ b/include/grgsm/transmitter/CMakeLists.txt @@ -21,5 +21,7 @@ # Install public header files ######################################################################## install(FILES - txtime_setter.h DESTINATION include/grgsm/transmitter + txtime_setter.h + preprocess_tx_burst.h + DESTINATION include/grgsm/transmitter ) diff --git a/include/grgsm/transmitter/preprocess_tx_burst.h b/include/grgsm/transmitter/preprocess_tx_burst.h new file mode 100644 index 0000000..2a07dd5 --- /dev/null +++ b/include/grgsm/transmitter/preprocess_tx_burst.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* @file + * @author Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + + +#ifndef INCLUDED_GSM_PREPROCESS_TX_BURST_H +#define INCLUDED_GSM_PREPROCESS_TX_BURST_H + +#include +#include + +namespace gr { + namespace gsm { + + /*! + * \brief A block that does preprocessing tasks before sending bursts to modulator. + * \ingroup gsm + * + * Currently it removes GSMTAP header from a burst and puts it in first part of PDU + * pair and removes tailing zeros from Access Bursts coming from TRX interface. + */ + class GRGSM_API preprocess_tx_burst : virtual public gr::block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of gsm::preprocess_tx_burst. + * + * To avoid accidental use of raw pointers, gsm::preprocess_tx_burst's + * constructor is in a private implementation + * class. gsm::preprocess_tx_burst::make is the public interface for + * creating new instances. + */ + static sptr make(); + }; + + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GSM_PREPROCESS_TX_BURST_H */ + diff --git a/lib/transmitter/CMakeLists.txt b/lib/transmitter/CMakeLists.txt index 31658fd..c61654a 100644 --- a/lib/transmitter/CMakeLists.txt +++ b/lib/transmitter/CMakeLists.txt @@ -19,4 +19,5 @@ add_sources( txtime_setter_impl.cc + preprocess_tx_burst_impl.cc ) diff --git a/lib/transmitter/preprocess_tx_burst_impl.cc b/lib/transmitter/preprocess_tx_burst_impl.cc new file mode 100644 index 0000000..5d3ae9a --- /dev/null +++ b/lib/transmitter/preprocess_tx_burst_impl.cc @@ -0,0 +1,85 @@ +/* -*- c++ -*- */ +/* @file + * @author Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include "preprocess_tx_burst_impl.h" + +namespace gr { + namespace gsm { + + preprocess_tx_burst::sptr + preprocess_tx_burst::make() + { + return gnuradio::get_initial_sptr + (new preprocess_tx_burst_impl()); + } + + /* + * The private constructor + */ + preprocess_tx_burst_impl::preprocess_tx_burst_impl() + : gr::block("preprocess_tx_burst", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)) + { + message_port_register_in(pmt::intern("bursts_in")); + message_port_register_out(pmt::intern("bursts_out")); + + set_msg_handler(pmt::intern("bursts_in"), boost::bind(&preprocess_tx_burst_impl::process_burst, this, _1)); + } + + /* + * Our virtual destructor. + */ + preprocess_tx_burst_impl::~preprocess_tx_burst_impl() + { + } + + void preprocess_tx_burst_impl::process_burst(pmt::pmt_t burst) + { + int8_t * header_bits = (int8_t *)(pmt::blob_data(pmt::cdr(burst))); + int8_t * burst_bits = (int8_t *)(pmt::blob_data(pmt::cdr(burst)))+sizeof(gsmtap_hdr); + + pmt::pmt_t header_bits_pmt = pmt::make_blob(header_bits,sizeof(gsmtap_hdr)); + + size_t burst_size = pmt::blob_length(pmt::cdr(burst))-sizeof(gsmtap_hdr); + if(((gsmtap_hdr*)header_bits)->sub_type == GSMTAP_BURST_ACCESS){ //cut unneeded bits from the end of access bursts + burst_size = ACCESS_BURST_SIZE; + } + pmt::pmt_t burst_bits_pmt = pmt::make_blob(burst_bits, burst_size); + + pmt::pmt_t pdu_first_part = pmt::car(burst); +// pmt::pmt_t new_pdu_first_part = pmt::dict_add( pdu_first_part, pmt::intern("gsmtap_header"), header_bits_pmt ); + pmt::pmt_t new_pdu_first_part = pdu_first_part; + + pmt::pmt_t new_msg = pmt::cons(new_pdu_first_part, burst_bits_pmt); + message_port_pub(pmt::intern("bursts_out"), new_msg); + } + } /* namespace gsm */ +} /* namespace gr */ + diff --git a/lib/transmitter/preprocess_tx_burst_impl.h b/lib/transmitter/preprocess_tx_burst_impl.h new file mode 100644 index 0000000..27fc508 --- /dev/null +++ b/lib/transmitter/preprocess_tx_burst_impl.h @@ -0,0 +1,47 @@ +/* -*- c++ -*- */ +/* @file + * @author Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef INCLUDED_GSM_PREPROCESS_TX_BURST_IMPL_H +#define INCLUDED_GSM_PREPROCESS_TX_BURST_IMPL_H + +#include +#include +#include + +namespace gr { + namespace gsm { + + class preprocess_tx_burst_impl : public preprocess_tx_burst + { + private: + void process_burst(pmt::pmt_t burst); + + public: + preprocess_tx_burst_impl(); + ~preprocess_tx_burst_impl(); + }; + + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GSM_PREPROCESS_TX_BURST_IMPL_H */ + diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i index 26b6a6d..65c48be 100644 --- a/swig/grgsm_swig.i +++ b/swig/grgsm_swig.i @@ -71,6 +71,7 @@ //#include "grgsm/misc_utils/time_spec.h" #include "grgsm/misc_utils/fn_time.h" #include "grgsm/transmitter/txtime_setter.h" +#include "grgsm/transmitter/preprocess_tx_burst.h" #include "grgsm/misc_utils/trx_burst_if.h" %} @@ -182,3 +183,5 @@ GR_SWIG_BLOCK_MAGIC2(gsm, message_sink); %include "grgsm/transmitter/txtime_setter.h" GR_SWIG_BLOCK_MAGIC2(gsm, txtime_setter); +%include "grgsm/transmitter/preprocess_tx_burst.h" +GR_SWIG_BLOCK_MAGIC2(gsm, preprocess_tx_burst); -- cgit v1.2.3 From 52f7416b3f46f49e805a38fd5dda2340e504028e Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Tue, 7 Nov 2017 19:34:45 +0100 Subject: Changed name of trx_interface directory to trx --- include/grgsm/CMakeLists.txt | 1 + include/grgsm/trx/CMakeLists.txt | 25 +++++++++++++++++++++++++ include/grgsm/trx_interface/CMakeLists.txt | 25 ------------------------- 3 files changed, 26 insertions(+), 25 deletions(-) create mode 100644 include/grgsm/trx/CMakeLists.txt delete mode 100644 include/grgsm/trx_interface/CMakeLists.txt diff --git a/include/grgsm/CMakeLists.txt b/include/grgsm/CMakeLists.txt index 2f76929..2982ef1 100644 --- a/include/grgsm/CMakeLists.txt +++ b/include/grgsm/CMakeLists.txt @@ -37,3 +37,4 @@ add_subdirectory(misc_utils) add_subdirectory(qa_utils) add_subdirectory(flow_control) add_subdirectory(transmitter) +add_subdirectory(trx) diff --git a/include/grgsm/trx/CMakeLists.txt b/include/grgsm/trx/CMakeLists.txt new file mode 100644 index 0000000..32e867f --- /dev/null +++ b/include/grgsm/trx/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# Install public header files +######################################################################## +install(FILES +# trx.h DESTINATION include/grgsm/trx_interface +) diff --git a/include/grgsm/trx_interface/CMakeLists.txt b/include/grgsm/trx_interface/CMakeLists.txt deleted file mode 100644 index 8d35ef7..0000000 --- a/include/grgsm/trx_interface/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2011,2012 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -######################################################################## -# Install public header files -######################################################################## -install(FILES - trx.h DESTINATION include/grgsm/trx_interface -) -- cgit v1.2.3 From 8d7b64d109c1b11aaea963092303b13098520c1d Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 8 Nov 2017 14:34:02 +0100 Subject: Added Python version of bursts to fn_time converter --- grc/gsm_block_tree.xml | 1 + grc/misc_utils/CMakeLists.txt | 4 +++- grc/misc_utils/gsm_burst_to_fn_time.xml | 19 +++++++++++++++++++ grc/transmitter/CMakeLists.txt | 2 +- python/misc_utils/CMakeLists.txt | 1 + python/misc_utils/burst_to_fn_time.py | 28 ++++++++++++++++++++++++++++ 6 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 grc/misc_utils/gsm_burst_to_fn_time.xml create mode 100644 python/misc_utils/burst_to_fn_time.py diff --git a/grc/gsm_block_tree.xml b/grc/gsm_block_tree.xml index dd971ab..89319c8 100644 --- a/grc/gsm_block_tree.xml +++ b/grc/gsm_block_tree.xml @@ -74,6 +74,7 @@ gsm_msg_to_tag.xml gsm_tmsi_dumper gsm_trx_burst_if + gsm_burst_to_fn_time diff --git a/grc/misc_utils/CMakeLists.txt b/grc/misc_utils/CMakeLists.txt index 9407caf..3316373 100644 --- a/grc/misc_utils/CMakeLists.txt +++ b/grc/misc_utils/CMakeLists.txt @@ -33,5 +33,7 @@ install(FILES gsm_message_file_source.xml gsm_trx_burst_if.xml gsm_msg_to_tag.xml - gsm_controlled_fractional_resampler_cc.xml DESTINATION share/gnuradio/grc/blocks + gsm_controlled_fractional_resampler_cc.xml + gsm_burst_to_fn_time.xml + DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/misc_utils/gsm_burst_to_fn_time.xml b/grc/misc_utils/gsm_burst_to_fn_time.xml new file mode 100644 index 0000000..dbbfe31 --- /dev/null +++ b/grc/misc_utils/gsm_burst_to_fn_time.xml @@ -0,0 +1,19 @@ + + + Burst to fn_time + gsm_burst_to_fn_time + import grgsm + grgsm.burst_to_fn_time() + + + bursts_in + message + 1 + + + + bursts_out + message + 1 + + diff --git a/grc/transmitter/CMakeLists.txt b/grc/transmitter/CMakeLists.txt index 0905e19..76d079e 100644 --- a/grc/transmitter/CMakeLists.txt +++ b/grc/transmitter/CMakeLists.txt @@ -21,5 +21,5 @@ install(FILES gsm_gmsk_mod.xml gsm_txtime_bursts_tagger.xml gsm_txtime_setter.xml - preprocess_tx_burst.xml DESTINATION share/gnuradio/grc/blocks + gsm_preprocess_tx_burst.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/python/misc_utils/CMakeLists.txt b/python/misc_utils/CMakeLists.txt index ec732a4..8c7c175 100644 --- a/python/misc_utils/CMakeLists.txt +++ b/python/misc_utils/CMakeLists.txt @@ -23,5 +23,6 @@ GR_PYTHON_INSTALL( clock_offset_corrector_tagged.py hier_block.py fn_time.py + burst_to_fn_time.py DESTINATION ${GR_PYTHON_DIR}/grgsm ) diff --git a/python/misc_utils/burst_to_fn_time.py b/python/misc_utils/burst_to_fn_time.py new file mode 100644 index 0000000..e31cf92 --- /dev/null +++ b/python/misc_utils/burst_to_fn_time.py @@ -0,0 +1,28 @@ +""" +Embedded Python Blocks: + +Each this file is saved, GRC will instantiate the first class it finds to get +ports and parameters of your block. The arguments to __init__ will be the +parameters. All of them are required to have default values! +""" +import numpy as np +from gnuradio import gr +import pmt + +class burst_to_fn_time(gr.basic_block): + def __init__(self): # only default arguments here + gr.basic_block.__init__( + self, + name='Burst to fn_time', + in_sig=[], + out_sig=[] + ) + self.message_port_register_in(pmt.intern("bursts_in")) + self.message_port_register_out(pmt.intern("fn_time_out")) + self.set_msg_handler(pmt.intern("bursts_in"), self.convert) + + def convert(self, msg): + fn_time = pmt.dict_ref(pmt.car(msg),pmt.intern("fn_time"),pmt.PMT_NIL) + fn_time_msg = pmt.dict_add(pmt.make_dict(), pmt.intern("fn_time"), fn_time) + if pmt.to_python(fn_time) is not None: + self.message_port_pub(pmt.intern("fn_time_out"), fn_time_msg) -- cgit v1.2.3 From 1243ffaf3eea33ed11296a7308d868658bde104a Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 8 Nov 2017 14:35:03 +0100 Subject: Changed name of of preprocess_tx_burst xml file, and removed 'executable' bit from two xml files --- grc/misc_utils/gsm_collect_system_info.xml | 0 grc/misc_utils/gsm_extract_cmc.xml | 0 grc/transmitter/gsm_preprocess_tx_burst.xml | 19 +++++++++++++++++++ grc/transmitter/preprocess_tx_burst.xml | 19 ------------------- 4 files changed, 19 insertions(+), 19 deletions(-) mode change 100755 => 100644 grc/misc_utils/gsm_collect_system_info.xml mode change 100755 => 100644 grc/misc_utils/gsm_extract_cmc.xml create mode 100644 grc/transmitter/gsm_preprocess_tx_burst.xml delete mode 100644 grc/transmitter/preprocess_tx_burst.xml diff --git a/grc/misc_utils/gsm_collect_system_info.xml b/grc/misc_utils/gsm_collect_system_info.xml old mode 100755 new mode 100644 diff --git a/grc/misc_utils/gsm_extract_cmc.xml b/grc/misc_utils/gsm_extract_cmc.xml old mode 100755 new mode 100644 diff --git a/grc/transmitter/gsm_preprocess_tx_burst.xml b/grc/transmitter/gsm_preprocess_tx_burst.xml new file mode 100644 index 0000000..70b447e --- /dev/null +++ b/grc/transmitter/gsm_preprocess_tx_burst.xml @@ -0,0 +1,19 @@ + + + Preprocess Tx burst + gsm_preprocess_tx_burst + import grgsm + grgsm.preprocess_tx_burst() + + + bursts_in + message + 1 + + + + bursts_out + message + 1 + + diff --git a/grc/transmitter/preprocess_tx_burst.xml b/grc/transmitter/preprocess_tx_burst.xml deleted file mode 100644 index 70b447e..0000000 --- a/grc/transmitter/preprocess_tx_burst.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Preprocess Tx burst - gsm_preprocess_tx_burst - import grgsm - grgsm.preprocess_tx_burst() - - - bursts_in - message - 1 - - - - bursts_out - message - 1 - - -- cgit v1.2.3 From d8617a9064c7a5eed58501607f1d20cefaf074e2 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 8 Nov 2017 14:35:14 +0100 Subject: Updated examples pointer --- examples | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples b/examples index 8bc9414..c59948d 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 8bc9414a06b7e71132ad0c27264e914ea8f05b84 +Subproject commit c59948db3c4e4df4a44235d73f760b7435108d72 -- cgit v1.2.3 From bfb47dca693c10a223dd3465449e00648b1b245f Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Sat, 11 Nov 2017 11:12:02 +0100 Subject: Fix: don't send SCH burst to the output if it wasn't correctly decoded This had very bad effect of incorrect fn_time values coming into txtime_setter block. They, subsequently, might have caused busts with tx_time values in distant future. The result on uhd sink is deadlock. --- lib/receiver/receiver_impl.cc | 15 +++++++-------- lib/receiver/receiver_impl.h | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/receiver/receiver_impl.cc b/lib/receiver/receiver_impl.cc index d57b4a1..cf080cb 100644 --- a/lib/receiver/receiver_impl.cc +++ b/lib/receiver/receiver_impl.cc @@ -209,7 +209,6 @@ namespace gr time_spec_t current_rx_time = time_spec_t(rx_time_full_part, rx_time_frac_part); uint64_t current_start_offset = rx_time_tag.offset; d_time_samp_ref.update(current_rx_time, current_start_offset); - std::cout << "Mam rx_time: " << current_rx_time.get_real_secs() << std::endl; } return d_samples_consumed; @@ -346,7 +345,7 @@ namespace gr case sch_burst: { - int d_ncc, d_bcc; + int ncc, bcc; int t1, t2, t3; int rc; @@ -358,12 +357,8 @@ namespace gr detect_burst(input, &channel_imp_resp[0], d_c0_burst_start, output_binary); - /* Compose a message with GSMTAP header and bits */ - send_burst(d_burst_nr, output_binary, - GSMTAP_BURST_SCH, input_nr, d_c0_burst_start); - /* Attempt to decode SCH burst */ - rc = decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc); + rc = decode_sch(&output_binary[3], &t1, &t2, &t3, &ncc, &bcc); if (rc) { if (++d_failed_sch >= MAX_SCH_ERRORS) { /* We have to resynchronize, change state */ @@ -374,10 +369,13 @@ namespace gr pmt::from_double(0.0),pmt::mp("sync_loss")); message_port_pub(pmt::mp("measurements"), msg); } - break; } + /* Compose a message with GSMTAP header and bits */ + send_burst(d_burst_nr, output_binary, + GSMTAP_BURST_SCH, input_nr, d_c0_burst_start); + /** * Decoding was successful, now * compute offset from burst_start, @@ -1073,6 +1071,7 @@ namespace gr message_port_pub(pmt::mp("C0"), msg); else message_port_pub(pmt::mp("CX"), msg); + } void diff --git a/lib/receiver/receiver_impl.h b/lib/receiver/receiver_impl.h index c216d90..9f69880 100644 --- a/lib/receiver/receiver_impl.h +++ b/lib/receiver/receiver_impl.h @@ -38,7 +38,7 @@ namespace gr { unsigned int d_samples_consumed; bool d_rx_time_received; time_sample_ref d_time_samp_ref; - unsigned int d_c0_burst_start; + int d_c0_burst_start; float d_c0_signal_dbm; /**@name Configuration of the receiver */ -- cgit v1.2.3 From 6ed10a1dfc58eca768ad8cff8862b8c3ab00ac26 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Sat, 11 Nov 2017 11:12:36 +0100 Subject: Missing __init__.py part for burst_to_fn_time --- python/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/__init__.py b/python/__init__.py index ad551ac..b3c9768 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -58,6 +58,7 @@ from gsm_sdcch8_demapper import gsm_sdcch8_demapper from gsm_gmsk_mod import gsm_gmsk_mod from fn_time import * from txtime_bursts_tagger import * +from burst_to_fn_time import * import arfcn -- cgit v1.2.3 From 2c004741d684f252c0b130080d9ea882995916e9 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Sat, 11 Nov 2017 11:13:52 +0100 Subject: Corrected output name for burst_to_fn_time --- grc/misc_utils/gsm_burst_to_fn_time.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grc/misc_utils/gsm_burst_to_fn_time.xml b/grc/misc_utils/gsm_burst_to_fn_time.xml index dbbfe31..0471605 100644 --- a/grc/misc_utils/gsm_burst_to_fn_time.xml +++ b/grc/misc_utils/gsm_burst_to_fn_time.xml @@ -12,7 +12,7 @@ - bursts_out + fn_time_out message 1 -- cgit v1.2.3 From f849fafd92c254a6f3897b08c6655f1cace90398 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Sat, 11 Nov 2017 11:14:26 +0100 Subject: Changed input and output name for burst_type_filter --- grc/flow_control/gsm_burst_type_filter.xml | 4 ++-- lib/flow_control/burst_type_filter_impl.cc | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/grc/flow_control/gsm_burst_type_filter.xml b/grc/flow_control/gsm_burst_type_filter.xml index a615961..d7d86f4 100644 --- a/grc/flow_control/gsm_burst_type_filter.xml +++ b/grc/flow_control/gsm_burst_type_filter.xml @@ -13,13 +13,13 @@ - in + bursts_in message 1 - out + bursts_out message 1 diff --git a/lib/flow_control/burst_type_filter_impl.cc b/lib/flow_control/burst_type_filter_impl.cc index 542a004..c8bbd7e 100644 --- a/lib/flow_control/burst_type_filter_impl.cc +++ b/lib/flow_control/burst_type_filter_impl.cc @@ -52,10 +52,10 @@ namespace gr { { set_selected_burst_types(selected_burst_types); - message_port_register_in(pmt::mp("in")); - message_port_register_out(pmt::mp("out")); + message_port_register_in(pmt::mp("bursts_in")); + message_port_register_out(pmt::mp("bursts_out")); - set_msg_handler(pmt::mp("in"), boost::bind(&burst_type_filter_impl::process_burst, this, _1)); + set_msg_handler(pmt::mp("bursts_in"), boost::bind(&burst_type_filter_impl::process_burst, this, _1)); } /* @@ -69,15 +69,14 @@ namespace gr { return; if (d_filter_policy == FILTER_POLICY_PASS_ALL) { - message_port_pub(pmt::mp("out"), msg); + message_port_pub(pmt::mp("bursts_out"), msg); return; } gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(pmt::cdr(msg)); -// std::cout << "header->type: " << (int)(header->sub_type) << std::endl; if (std::find(d_selected_burst_types.begin(), d_selected_burst_types.end(), header->sub_type) != d_selected_burst_types.end()) //check if burst type is listed in burst types to pass { - message_port_pub(pmt::mp("out"), msg); + message_port_pub(pmt::mp("bursts_out"), msg); } } -- cgit v1.2.3 From ba8b0a95d3824bbef9baec6ed30fcd22691413ae Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Sat, 11 Nov 2017 11:19:26 +0100 Subject: Fix: protections in txtime_setter against late bursts and bursts in too distant future. Fixing bursts in too distant future is a bit problematic and better way than just looking at tx_time difference from current time would be desirable. This way of fixing that issue can still cause that tx part will do nothing for about 10 seconds (after switching frequency from a BTS1 (with fn1) to BTS2 (with fn2) when fn1>fn2). --- lib/transmitter/txtime_setter_impl.cc | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/transmitter/txtime_setter_impl.cc b/lib/transmitter/txtime_setter_impl.cc index 9ff1d8a..91fc4ca 100644 --- a/lib/transmitter/txtime_setter_impl.cc +++ b/lib/transmitter/txtime_setter_impl.cc @@ -103,11 +103,22 @@ namespace gr { txtime_spec = txtime_spec - d_delay_correction; txtime_spec = txtime_spec - d_timing_advance; - pmt::pmt_t tags_dict = pmt::dict_add(pmt::make_dict(), pmt::intern("tx_time"), pmt::make_tuple(pmt::from_uint64(txtime_spec.get_full_secs()),pmt::from_double(txtime_spec.get_frac_secs()))); - tags_dict = pmt::dict_add(tags_dict, pmt::intern("fn"), pmt::from_uint64(frame_nr)); - tags_dict = pmt::dict_add(tags_dict, pmt::intern("ts"), pmt::from_uint64(ts_num)); - pmt::pmt_t new_msg = pmt::cons(tags_dict, pmt::cdr(burst)); - message_port_pub(pmt::intern("bursts_out"), new_msg); + if(txtime_spec <= time_spec_t(d_time_hint.first, d_time_hint.second)) + { + std::cout << "lB" << std::flush; + } + else if(txtime_spec > time_spec_t(d_time_hint.first, d_time_hint.second)+10.0) + { + std::cout << "eB" << std::flush; + } + else + { + pmt::pmt_t tags_dict = pmt::dict_add(pmt::make_dict(), pmt::intern("tx_time"), pmt::make_tuple(pmt::from_uint64(txtime_spec.get_full_secs()),pmt::from_double(txtime_spec.get_frac_secs()))); + tags_dict = pmt::dict_add(tags_dict, pmt::intern("fn"), pmt::from_uint64(frame_nr)); + tags_dict = pmt::dict_add(tags_dict, pmt::intern("ts"), pmt::from_uint64(ts_num)); + pmt::pmt_t new_msg = pmt::cons(tags_dict, pmt::cdr(burst)); + message_port_pub(pmt::intern("bursts_out"), new_msg); + } } } -- cgit v1.2.3 From 2f0406b76daf3df6f8a70b116bb8dd3bf9112e88 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Sat, 11 Nov 2017 11:22:23 +0100 Subject: Updates .gitignore and examples pointer --- .gitignore | 2 +- examples | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 4a4e29c..049eb2a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ build *.pyc *.pyo .unittests -build/ +build*/ debian/tmp/ debian/files .directory diff --git a/examples b/examples index c59948d..a548123 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit c59948db3c4e4df4a44235d73f760b7435108d72 +Subproject commit a5481238c3866808363b7beaf33d1937debe708a -- cgit v1.2.3 From 23444838698302e5dd331cfac44082d71794d7d2 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 29 Nov 2017 16:39:22 +0100 Subject: Added a block for generating Access Bursts --- grc/gsm_block_tree.xml | 1 + grc/transmitter/CMakeLists.txt | 8 ++- grc/transmitter/gsm_gen_test_ab.xml | 19 ++++++ include/grgsm/transmitter/CMakeLists.txt | 1 + include/grgsm/transmitter/gen_test_ab.h | 60 +++++++++++++++++ lib/transmitter/CMakeLists.txt | 1 + lib/transmitter/gen_test_ab_impl.cc | 107 +++++++++++++++++++++++++++++++ lib/transmitter/gen_test_ab_impl.h | 47 ++++++++++++++ swig/grgsm_swig.i | 13 ++-- 9 files changed, 249 insertions(+), 8 deletions(-) create mode 100644 grc/transmitter/gsm_gen_test_ab.xml create mode 100644 include/grgsm/transmitter/gen_test_ab.h create mode 100644 lib/transmitter/gen_test_ab_impl.cc create mode 100644 lib/transmitter/gen_test_ab_impl.h diff --git a/grc/gsm_block_tree.xml b/grc/gsm_block_tree.xml index 89319c8..219702a 100644 --- a/grc/gsm_block_tree.xml +++ b/grc/gsm_block_tree.xml @@ -27,6 +27,7 @@ gsm_txtime_setter gsm_gmsk_mod gsm_preprocess_tx_burst + gsm_gen_test_ab Logical channels demapping diff --git a/grc/transmitter/CMakeLists.txt b/grc/transmitter/CMakeLists.txt index 76d079e..4df2abb 100644 --- a/grc/transmitter/CMakeLists.txt +++ b/grc/transmitter/CMakeLists.txt @@ -19,7 +19,9 @@ install(FILES gsm_gmsk_mod.xml - gsm_txtime_bursts_tagger.xml - gsm_txtime_setter.xml - gsm_preprocess_tx_burst.xml DESTINATION share/gnuradio/grc/blocks + gsm_txtime_bursts_tagger.xml + gsm_txtime_setter.xml + gsm_preprocess_tx_burst.xml + gsm_gen_test_ab.xml + DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/transmitter/gsm_gen_test_ab.xml b/grc/transmitter/gsm_gen_test_ab.xml new file mode 100644 index 0000000..3cb8b11 --- /dev/null +++ b/grc/transmitter/gsm_gen_test_ab.xml @@ -0,0 +1,19 @@ + + + Gen Test AB + gsm_gen_test_ab + import grgsm + grgsm.gen_test_ab() + + + bursts_in + message + 1 + + + + bursts_out + message + 1 + + diff --git a/include/grgsm/transmitter/CMakeLists.txt b/include/grgsm/transmitter/CMakeLists.txt index 29ccc4b..fab6f7c 100644 --- a/include/grgsm/transmitter/CMakeLists.txt +++ b/include/grgsm/transmitter/CMakeLists.txt @@ -23,5 +23,6 @@ install(FILES txtime_setter.h preprocess_tx_burst.h + gen_test_ab.h DESTINATION include/grgsm/transmitter ) diff --git a/include/grgsm/transmitter/gen_test_ab.h b/include/grgsm/transmitter/gen_test_ab.h new file mode 100644 index 0000000..d2756f1 --- /dev/null +++ b/include/grgsm/transmitter/gen_test_ab.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* @file + * @author Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + + +#ifndef INCLUDED_GSM_GEN_TEST_AB_H +#define INCLUDED_GSM_GEN_TEST_AB_H + +#include +#include + +namespace gr { + namespace gsm { + + /*! + * \brief A block that does preprocessing tasks before sending bursts to modulator. + * \ingroup gsm + * + * Currently it removes GSMTAP header from a burst and puts it in first part of PDU + * pair and removes tailing zeros from Access Bursts coming from TRX interface. + */ + class GRGSM_API gen_test_ab : virtual public gr::block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of gsm::gen_test_ab. + * + * To avoid accidental use of raw pointers, gsm::gen_test_ab's + * constructor is in a private implementation + * class. gsm::gen_test_ab::make is the public interface for + * creating new instances. + */ + static sptr make(); + }; + + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GSM_GEN_TEST_AB_H */ + diff --git a/lib/transmitter/CMakeLists.txt b/lib/transmitter/CMakeLists.txt index c61654a..eb53162 100644 --- a/lib/transmitter/CMakeLists.txt +++ b/lib/transmitter/CMakeLists.txt @@ -20,4 +20,5 @@ add_sources( txtime_setter_impl.cc preprocess_tx_burst_impl.cc + gen_test_ab_impl ) diff --git a/lib/transmitter/gen_test_ab_impl.cc b/lib/transmitter/gen_test_ab_impl.cc new file mode 100644 index 0000000..66873db --- /dev/null +++ b/lib/transmitter/gen_test_ab_impl.cc @@ -0,0 +1,107 @@ +/* -*- c++ -*- */ +/* @file + * @author Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include "gen_test_ab_impl.h" + +namespace gr { + namespace gsm { + + static uint8_t rach_synch_seq[] = { + 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0 , + 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, + }; + +// static uint8_t AB[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +// static uint8_t AB[] = {0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1}; +// static uint8_t AB[] = { 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1}; + static uint8_t AB[] = {1,1,1,1,1,1,1,1,1,0,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,0,1,0,1,0,1,1,1,0,0,0,0,1,1,1,0,0,1,0,0,0,1,0,1,0,1,0,0,1,0,1,0,1,1,0,1,1,0,0,1,0,1,0,0,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; + gen_test_ab::sptr + gen_test_ab::make() + { + return gnuradio::get_initial_sptr + (new gen_test_ab_impl()); + } + + /* + * The private constructor + */ + gen_test_ab_impl::gen_test_ab_impl() + : gr::block("gen_test_ab", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)) + { + message_port_register_in(pmt::intern("bursts_in")); + message_port_register_out(pmt::intern("bursts_out")); + + set_msg_handler(pmt::intern("bursts_in"), boost::bind(&gen_test_ab_impl::generate_ab, this, _1)); + } + + /* + * Our virtual destructor. + */ + gen_test_ab_impl::~gen_test_ab_impl() + { + } + + void gen_test_ab_impl::generate_ab(pmt::pmt_t burst) + { + uint8_t buf[sizeof(gsmtap_hdr) + 148]; + struct gsmtap_hdr *tap_header = (struct gsmtap_hdr *) buf; + uint8_t *access_burst = buf + sizeof(gsmtap_hdr); + +// memset(access_burst, 0, 8); /* TB */ +// memcpy(access_burst + 8, rach_synch_seq, 41); /* sync seq */ +// memcpy(access_burst + 49, AB, 36); /* payload */ +// memset(access_burst + 85, 0, 63); /* TB + GP */ + + memcpy(access_burst, AB, 148); + + gsmtap_hdr * header = (gsmtap_hdr *)(pmt::blob_data(pmt::cdr(burst))); + uint32_t frame_nr = be32toh(header->frame_number); + frame_nr = (frame_nr+51)% (26*51*2048); + + tap_header->version = GSMTAP_VERSION; + tap_header->hdr_len = sizeof(gsmtap_hdr) / 4; + tap_header->type = GSMTAP_TYPE_UM_BURST; + tap_header->sub_type = GSMTAP_BURST_ACCESS; + tap_header->frame_number = htobe32(frame_nr); + tap_header->timeslot = header->timeslot; + tap_header->arfcn = 0; + + pmt::pmt_t blob = pmt::make_blob(buf, sizeof(gsmtap_hdr) + BURST_SIZE); + pmt::pmt_t pdu_header = pmt::make_dict(); + + pmt::pmt_t new_msg = pmt::cons(pdu_header, blob); + message_port_pub(pmt::intern("bursts_out"), new_msg); + } + } /* namespace gsm */ +} /* namespace gr */ + diff --git a/lib/transmitter/gen_test_ab_impl.h b/lib/transmitter/gen_test_ab_impl.h new file mode 100644 index 0000000..366481e --- /dev/null +++ b/lib/transmitter/gen_test_ab_impl.h @@ -0,0 +1,47 @@ +/* -*- c++ -*- */ +/* @file + * @author Piotr Krysik + * @section LICENSE + * + * Gr-gsm is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * Gr-gsm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gr-gsm; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef INCLUDED_GSM_GEN_TEST_AB_IMPL_H +#define INCLUDED_GSM_GEN_TEST_AB_IMPL_H + +#include +#include +#include + +namespace gr { + namespace gsm { + + class gen_test_ab_impl : public gen_test_ab + { + private: + void generate_ab(pmt::pmt_t burst); + + public: + gen_test_ab_impl(); + ~gen_test_ab_impl(); + }; + + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GSM_GEN_TEST_AB_IMPL_H */ + diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i index 65c48be..005033f 100644 --- a/swig/grgsm_swig.i +++ b/swig/grgsm_swig.i @@ -1,7 +1,7 @@ /* -*- c++ -*- */ /* * @file - * @author (C) 2014 by Piotr Krysik + * @author (C) 2014-2017 by Piotr Krysik * @section LICENSE * * Gr-gsm is free software; you can redistribute it and/or modify @@ -72,6 +72,7 @@ #include "grgsm/misc_utils/fn_time.h" #include "grgsm/transmitter/txtime_setter.h" #include "grgsm/transmitter/preprocess_tx_burst.h" +#include "grgsm/transmitter/gen_test_ab.h" #include "grgsm/misc_utils/trx_burst_if.h" %} @@ -144,10 +145,6 @@ GR_SWIG_BLOCK_MAGIC2(gsm, msg_to_tag); GR_SWIG_BLOCK_MAGIC2(gsm, controlled_fractional_resampler_cc); %include "grgsm/misc_utils/extract_cmc.h" GR_SWIG_BLOCK_MAGIC2(gsm, extract_cmc); -%include "grgsm/misc_utils/trx_burst_if.h" -GR_SWIG_BLOCK_MAGIC2(gsm, trx_burst_if); - - %include "grgsm/qa_utils/burst_sink.h" GR_SWIG_BLOCK_MAGIC2(gsm, burst_sink); %include "grgsm/qa_utils/burst_source.h" @@ -185,3 +182,9 @@ GR_SWIG_BLOCK_MAGIC2(gsm, message_sink); GR_SWIG_BLOCK_MAGIC2(gsm, txtime_setter); %include "grgsm/transmitter/preprocess_tx_burst.h" GR_SWIG_BLOCK_MAGIC2(gsm, preprocess_tx_burst); + +%include "grgsm/transmitter/gen_test_ab.h" +GR_SWIG_BLOCK_MAGIC2(gsm, gen_test_ab); + +%include "grgsm/misc_utils/trx_burst_if.h" +GR_SWIG_BLOCK_MAGIC2(gsm, trx_burst_if); -- cgit v1.2.3 From 800ac631091a54998adf954b72f005d55366f3b0 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Wed, 29 Nov 2017 16:39:41 +0100 Subject: Corrected wrong lenght of the Access Burst --- include/grgsm/gsm_constants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grgsm/gsm_constants.h b/include/grgsm/gsm_constants.h index fd1d9e7..2fbfd36 100644 --- a/include/grgsm/gsm_constants.h +++ b/include/grgsm/gsm_constants.h @@ -38,7 +38,7 @@ #define USEFUL_BITS 142 //(2*(DATA_BITS+STEALING_BIT) + N_TRAIN_BITS ) #define FCCH_BITS USEFUL_BITS #define BURST_SIZE (USEFUL_BITS+2*TAIL_BITS) -#define ACCESS_BURST_SIZE 87 +#define ACCESS_BURST_SIZE 88 #define PROCESSED_CHUNK BURST_SIZE+2*GUARD_PERIOD #define SCH_DATA_LEN 39 -- cgit v1.2.3 From 4f4e578ffd047cfdc8367a2a5b4a2a6901cc6033 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sun, 5 Nov 2017 23:59:20 +0700 Subject: include/grgsm: remove forgotten 'trx_interface' dir This directory was accidentally kept here during the 'TRX Burst Interface' migration into 'misc_utils'. --- include/grgsm/CMakeLists.txt | 1 - include/grgsm/trx/CMakeLists.txt | 25 ------------------------- 2 files changed, 26 deletions(-) delete mode 100644 include/grgsm/trx/CMakeLists.txt diff --git a/include/grgsm/CMakeLists.txt b/include/grgsm/CMakeLists.txt index 2982ef1..2f76929 100644 --- a/include/grgsm/CMakeLists.txt +++ b/include/grgsm/CMakeLists.txt @@ -37,4 +37,3 @@ add_subdirectory(misc_utils) add_subdirectory(qa_utils) add_subdirectory(flow_control) add_subdirectory(transmitter) -add_subdirectory(trx) diff --git a/include/grgsm/trx/CMakeLists.txt b/include/grgsm/trx/CMakeLists.txt deleted file mode 100644 index 32e867f..0000000 --- a/include/grgsm/trx/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2011,2012 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. - -######################################################################## -# Install public header files -######################################################################## -install(FILES -# trx.h DESTINATION include/grgsm/trx_interface -) -- cgit v1.2.3 From 70bec2039aaa3b1bf3d1f4555d6b1f43c35cc78e Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 29 Nov 2017 22:44:18 +0700 Subject: preprocess_tx_burst: clean up and simplify source code This change formats the block implementation source code according to a mix of GNURadio and the Kernel coding styles. The main changes are: - Limit line length to 80 columns - Preffer the opposite conditions - Do not use curly braces for single line loops / conditions For more details, see: https://wiki.gnuradio.org/index.php/Coding_guide_impl https://www.kernel.org/doc/html/v4.10/process/coding-style.html --- lib/transmitter/preprocess_tx_burst_impl.cc | 61 +++++++++++++++++------------ 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/lib/transmitter/preprocess_tx_burst_impl.cc b/lib/transmitter/preprocess_tx_burst_impl.cc index 5d3ae9a..5a89390 100644 --- a/lib/transmitter/preprocess_tx_burst_impl.cc +++ b/lib/transmitter/preprocess_tx_burst_impl.cc @@ -1,6 +1,7 @@ /* -*- c++ -*- */ /* @file * @author Piotr Krysik + * @author Vadim Yanitskiy * @section LICENSE * * Gr-gsm is free software; you can redistribute it and/or modify @@ -24,9 +25,12 @@ #include "config.h" #endif +#include + #include -#include #include +#include + #include "preprocess_tx_burst_impl.h" namespace gr { @@ -44,13 +48,14 @@ namespace gr { */ preprocess_tx_burst_impl::preprocess_tx_burst_impl() : gr::block("preprocess_tx_burst", - gr::io_signature::make(0, 0, 0), - gr::io_signature::make(0, 0, 0)) + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)) { - message_port_register_in(pmt::intern("bursts_in")); - message_port_register_out(pmt::intern("bursts_out")); + message_port_register_in(pmt::mp("bursts_in")); + message_port_register_out(pmt::mp("bursts_out")); - set_msg_handler(pmt::intern("bursts_in"), boost::bind(&preprocess_tx_burst_impl::process_burst, this, _1)); + set_msg_handler(pmt::mp("bursts_in"), + boost::bind(&preprocess_tx_burst_impl::process_burst, this, _1)); } /* @@ -60,26 +65,32 @@ namespace gr { { } - void preprocess_tx_burst_impl::process_burst(pmt::pmt_t burst) + void preprocess_tx_burst_impl::process_burst(pmt::pmt_t msg_in) { - int8_t * header_bits = (int8_t *)(pmt::blob_data(pmt::cdr(burst))); - int8_t * burst_bits = (int8_t *)(pmt::blob_data(pmt::cdr(burst)))+sizeof(gsmtap_hdr); - - pmt::pmt_t header_bits_pmt = pmt::make_blob(header_bits,sizeof(gsmtap_hdr)); - - size_t burst_size = pmt::blob_length(pmt::cdr(burst))-sizeof(gsmtap_hdr); - if(((gsmtap_hdr*)header_bits)->sub_type == GSMTAP_BURST_ACCESS){ //cut unneeded bits from the end of access bursts - burst_size = ACCESS_BURST_SIZE; - } - pmt::pmt_t burst_bits_pmt = pmt::make_blob(burst_bits, burst_size); - - pmt::pmt_t pdu_first_part = pmt::car(burst); -// pmt::pmt_t new_pdu_first_part = pmt::dict_add( pdu_first_part, pmt::intern("gsmtap_header"), header_bits_pmt ); - pmt::pmt_t new_pdu_first_part = pdu_first_part; - - pmt::pmt_t new_msg = pmt::cons(new_pdu_first_part, burst_bits_pmt); - message_port_pub(pmt::intern("bursts_out"), new_msg); + pmt::pmt_t blob_in = pmt::cdr(msg_in); + + // Extract GSMTAP header from message + gsmtap_hdr *burst_hdr = (gsmtap_hdr *) pmt::blob_data(blob_in); + + // Extract burst bits from message + uint8_t *burst_bits = (uint8_t *) + (pmt::blob_data(blob_in)) + sizeof(gsmtap_hdr); + + // Determine and check burst length + size_t burst_len = pmt::blob_length(blob_in) - sizeof(gsmtap_hdr); + assert(burst_len == BURST_SIZE); + + // The Access Burst last has reduced length + if (burst_hdr->sub_type == GSMTAP_BURST_ACCESS) + burst_len = ACCESS_BURST_SIZE; + + // Prepare an output message + pmt::pmt_t blob_out = pmt::make_blob(burst_bits, burst_len); + pmt::pmt_t msg_out = pmt::cons(pmt::PMT_NIL, blob_out); + + /* Send a message to the output */ + message_port_pub(pmt::mp("bursts_out"), msg_out); } + } /* namespace gsm */ } /* namespace gr */ - -- cgit v1.2.3 From 2ce294219ce06de437ecc677e098a82ca0cb4906 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 29 Nov 2017 23:58:42 +0700 Subject: txtime_setter: clean up and simplify source code This change formats the block implementation source code according to a mix of GNURadio and the Kernel coding styles. The main changes are: - Limit line length to 80 columns - Preffer the opposite conditions - Do not use curly braces for single line loops / conditions For more details, see: https://wiki.gnuradio.org/index.php/Coding_guide_impl https://www.kernel.org/doc/html/v4.10/process/coding-style.html --- lib/transmitter/txtime_setter_impl.cc | 174 +++++++++++++++++++++------------- lib/transmitter/txtime_setter_impl.h | 16 ++-- 2 files changed, 118 insertions(+), 72 deletions(-) diff --git a/lib/transmitter/txtime_setter_impl.cc b/lib/transmitter/txtime_setter_impl.cc index 91fc4ca..f6141f0 100644 --- a/lib/transmitter/txtime_setter_impl.cc +++ b/lib/transmitter/txtime_setter_impl.cc @@ -1,6 +1,7 @@ /* -*- c++ -*- */ /* @file * @author Piotr Krysik + * @author Vadim Yanitskiy * @section LICENSE * * Gr-gsm is free software; you can redistribute it and/or modify @@ -26,38 +27,55 @@ #include #include + #include "txtime_setter_impl.h" namespace gr { namespace gsm { txtime_setter::sptr - txtime_setter::make(uint32_t init_fn, uint64_t init_time_secs, double init_time_fracs, uint64_t time_hint_secs, double time_hint_fracs, double timing_advance, double delay_correction) + txtime_setter::make( + uint32_t init_fn, uint64_t init_time_secs, + double init_time_fracs, uint64_t time_hint_secs, + double time_hint_fracs, double timing_advance, + double delay_correction) { return gnuradio::get_initial_sptr - (new txtime_setter_impl(init_fn, init_time_secs, init_time_fracs, time_hint_secs, time_hint_fracs, timing_advance, delay_correction)); + (new txtime_setter_impl(init_fn, init_time_secs, + init_time_fracs, time_hint_secs, time_hint_fracs, + timing_advance, delay_correction)); } /* * The private constructor */ - txtime_setter_impl::txtime_setter_impl(uint32_t init_fn, uint64_t init_time_secs, double init_time_fracs, uint64_t time_hint_secs, double time_hint_fracs, double timing_advance, double delay_correction) - : gr::block("txtime_setter", - gr::io_signature::make(0, 0, 0), - gr::io_signature::make(0, 0, 0)), - d_fn_ref(init_fn), - d_ts_ref(0), - d_time_ref(init_time_secs,init_time_fracs), + txtime_setter_impl::txtime_setter_impl( + uint32_t init_fn, uint64_t init_time_secs, + double init_time_fracs, uint64_t time_hint_secs, + double time_hint_fracs, double timing_advance, + double delay_correction + ) : gr::block("txtime_setter", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)), d_time_hint(time_hint_secs,time_hint_fracs), + d_time_ref(init_time_secs,init_time_fracs), + d_delay_correction(delay_correction), d_timing_advance(timing_advance), - d_delay_correction(delay_correction) + d_fn_ref(init_fn), + d_ts_ref(0) { - message_port_register_in(pmt::intern("fn_time")); - message_port_register_in(pmt::intern("bursts_in")); - message_port_register_out(pmt::intern("bursts_out")); + // Register I/O ports + message_port_register_in(pmt::mp("fn_time")); + message_port_register_in(pmt::mp("bursts_in")); + message_port_register_out(pmt::mp("bursts_out")); - set_msg_handler(pmt::intern("fn_time"), boost::bind(&txtime_setter_impl::process_fn_time_reference, this, _1)); - set_msg_handler(pmt::intern("bursts_in"), boost::bind(&txtime_setter_impl::process_txtime_of_burst, this, _1)); + // Bind message handlers + set_msg_handler(pmt::mp("fn_time"), + boost::bind(&txtime_setter_impl::process_fn_time_reference, + this, _1)); + set_msg_handler(pmt::mp("bursts_in"), + boost::bind(&txtime_setter_impl::process_txtime_of_burst, + this, _1)); } /* @@ -69,60 +87,84 @@ namespace gr { void txtime_setter_impl::process_fn_time_reference(pmt::pmt_t msg) { -// d_time_hint = pmt::to_python(pmt::dict_ref(msg, pmt::intern("time_hint"), pmt::PMT_NIL)) - pmt::pmt_t not_found = pmt::intern("not_found"); - pmt::pmt_t fn_time = pmt::dict_ref(msg, pmt::intern("fn_time"), not_found); - pmt::pmt_t time_hint = pmt::dict_ref(msg, pmt::intern("fn_time"), not_found); - - if(fn_time != not_found) - { - uint32_t fn_ref = static_cast(pmt::to_uint64(pmt::car(pmt::car(fn_time)))); - uint32_t ts = static_cast(pmt::to_uint64(pmt::cdr(pmt::car(fn_time)))); - uint64_t time_secs = pmt::to_uint64(pmt::car(pmt::cdr(fn_time))); - double time_fracs = pmt::to_double(pmt::cdr(pmt::cdr(fn_time))); - set_fn_time_reference(fn_ref, ts, time_secs, time_fracs); - } else if(time_hint != not_found) { - set_time_hint(pmt::to_uint64(pmt::car(fn_time)), pmt::to_double(pmt::cdr(fn_time))); - } + pmt::pmt_t not_found = pmt::intern("not_found"); + pmt::pmt_t fn_time, time_hint; + fn_time = pmt::dict_ref(msg, + pmt::intern("fn_time"), not_found); + time_hint = pmt::dict_ref(msg, + pmt::intern("fn_time"), not_found); + + if (fn_time != not_found) { + uint32_t fn_ref = static_cast + (pmt::to_uint64(pmt::car(pmt::car(fn_time)))); + uint32_t ts = static_cast + (pmt::to_uint64(pmt::cdr(pmt::car(fn_time)))); + uint64_t time_secs = pmt::to_uint64( + pmt::car(pmt::cdr(fn_time))); + double time_fracs = pmt::to_double( + pmt::cdr(pmt::cdr(fn_time))); + + set_fn_time_reference(fn_ref, ts, time_secs, time_fracs); + } else if (time_hint != not_found) { + set_time_hint(pmt::to_uint64(pmt::car(fn_time)), + pmt::to_double(pmt::cdr(fn_time))); + } } - - void txtime_setter_impl::process_txtime_of_burst(pmt::pmt_t burst) + + void txtime_setter_impl::process_txtime_of_burst(pmt::pmt_t msg_in) { - pmt::pmt_t header_plus_burst = pmt::cdr(burst); - int8_t * burst_int8 = (int8_t *)pmt::blob_data(header_plus_burst); - gsmtap_hdr * header = (gsmtap_hdr *)(burst_int8); - - uint32_t frame_nr = be32toh(header->frame_number); - uint32_t ts_num = header->timeslot; - - if(d_fn_ref != 0xffffffff) - { - time_format txtime = fn_time_delta_cpp(d_fn_ref, d_time_ref, frame_nr, d_time_hint, ts_num, d_ts_ref); - time_spec_t txtime_spec = time_spec_t(txtime.first, txtime.second); - txtime_spec = txtime_spec - d_delay_correction; - txtime_spec = txtime_spec - d_timing_advance; - - if(txtime_spec <= time_spec_t(d_time_hint.first, d_time_hint.second)) - { - std::cout << "lB" << std::flush; - } - else if(txtime_spec > time_spec_t(d_time_hint.first, d_time_hint.second)+10.0) - { - std::cout << "eB" << std::flush; - } - else - { - pmt::pmt_t tags_dict = pmt::dict_add(pmt::make_dict(), pmt::intern("tx_time"), pmt::make_tuple(pmt::from_uint64(txtime_spec.get_full_secs()),pmt::from_double(txtime_spec.get_frac_secs()))); - tags_dict = pmt::dict_add(tags_dict, pmt::intern("fn"), pmt::from_uint64(frame_nr)); - tags_dict = pmt::dict_add(tags_dict, pmt::intern("ts"), pmt::from_uint64(ts_num)); - pmt::pmt_t new_msg = pmt::cons(tags_dict, pmt::cdr(burst)); - message_port_pub(pmt::intern("bursts_out"), new_msg); - } - } + // Nothing to do... + if (d_fn_ref == 0xffffffff) + return; + + pmt::pmt_t blob = pmt::cdr(msg_in); + + // Extract GSMTAP header from message + gsmtap_hdr *header = (gsmtap_hdr *) pmt::blob_data(blob); + uint32_t frame_nr = be32toh(header->frame_number); + uint32_t ts_num = header->timeslot; + + time_format txtime = fn_time_delta_cpp(d_fn_ref, d_time_ref, + frame_nr, d_time_hint, ts_num, d_ts_ref); + + time_spec_t txtime_spec = time_spec_t(txtime.first, txtime.second); + txtime_spec -= d_delay_correction; + txtime_spec -= d_timing_advance; + + // FIXME: better name? + time_spec_t foo = time_spec_t(d_time_hint.first, d_time_hint.second); + + // Drop too late / early bursts + if (txtime_spec <= foo) { + std::cout << "lB" << std::flush; + return; + } else if (txtime_spec > foo + 10.0) { + std::cout << "eB" << std::flush; + return; + } + + pmt::pmt_t tags_dict = pmt::dict_add( + pmt::make_dict(), + pmt::intern("tx_time"), + pmt::make_tuple( + pmt::from_uint64(txtime_spec.get_full_secs()), + pmt::from_double(txtime_spec.get_frac_secs())) + ); + + tags_dict = pmt::dict_add(tags_dict, + pmt::intern("fn"), pmt::from_uint64(frame_nr)); + tags_dict = pmt::dict_add(tags_dict, + pmt::intern("ts"), pmt::from_uint64(ts_num)); + + // Send a message to the output + pmt::pmt_t msg_out = pmt::cons(tags_dict, pmt::cdr(msg_in)); + message_port_pub(pmt::mp("bursts_out"), msg_out); } - void txtime_setter_impl::set_fn_time_reference(uint32_t fn, uint32_t ts, uint64_t time_secs, double time_fracs) + void txtime_setter_impl::set_fn_time_reference( + uint32_t fn, uint32_t ts, uint64_t time_secs, + double time_fracs) { d_fn_ref = fn; d_ts_ref = ts; @@ -130,7 +172,8 @@ namespace gr { set_time_hint(time_secs, time_fracs); } - void txtime_setter_impl::set_time_hint(uint64_t time_hint_secs, double time_hint_fracs) + void txtime_setter_impl::set_time_hint( + uint64_t time_hint_secs, double time_hint_fracs) { d_time_hint = std::make_pair(time_hint_secs, time_hint_fracs); } @@ -147,4 +190,3 @@ namespace gr { } /* namespace gsm */ } /* namespace gr */ - diff --git a/lib/transmitter/txtime_setter_impl.h b/lib/transmitter/txtime_setter_impl.h index e3f195a..62f500a 100644 --- a/lib/transmitter/txtime_setter_impl.h +++ b/lib/transmitter/txtime_setter_impl.h @@ -39,15 +39,20 @@ namespace gr { time_format d_time_hint; double d_timing_advance; double d_delay_correction; - + + void process_fn_time_reference(pmt::pmt_t msg); + void process_txtime_of_burst(pmt::pmt_t msg); + public: - txtime_setter_impl(uint32_t init_fn, uint64_t init_time_secs, double init_time_fracs, uint64_t time_hint_secs, double time_hint_fracs, double timing_advance, double delay_correction); + txtime_setter_impl(uint32_t init_fn, uint64_t init_time_secs, + double init_time_fracs, uint64_t time_hint_secs, + double time_hint_fracs, double timing_advance, + double delay_correction); ~txtime_setter_impl(); // Where all the action really happens - void process_fn_time_reference(pmt::pmt_t msg); - void process_txtime_of_burst(pmt::pmt_t msg); - void set_fn_time_reference(uint32_t fn, uint32_t ts, uint64_t time_secs, double time_fracs); + void set_fn_time_reference(uint32_t fn, uint32_t ts, + uint64_t time_secs, double time_fracs); void set_time_hint(uint64_t time_hint_secs, double time_hint_fracs); void set_delay_correction(double delay_correction); void set_timing_advance(double timing_advance); @@ -57,4 +62,3 @@ namespace gr { } // namespace gr #endif /* INCLUDED_GSM_TXTIME_SETTER_IMPL_H */ - -- cgit v1.2.3 From 0e7c9a80ad4ee3fc31ddfb1dfffdb82278db851e Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 23 Nov 2017 19:53:31 +0700 Subject: apps/grgsm_trx: fix antenna selection options Both '--rx-antenna' and '--tx-antenna' require an argument. --- apps/grgsm_trx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/grgsm_trx b/apps/grgsm_trx index 670d919..507ed87 100755 --- a/apps/grgsm_trx +++ b/apps/grgsm_trx @@ -116,7 +116,7 @@ class Application: "i:p:a:s:g:G:h", ["help", "remote-addr=", "base-port=", "device-args=", "sample-rate=", "rx-gain=", "tx-gain=", "ppm=", - "rx-antenna", "tx-antenna"]) + "rx-antenna=", "tx-antenna="]) except getopt.GetoptError as err: # Print(help and exit) self.print_help() -- cgit v1.2.3 From 89aa469cf395a24e960a0a9fac3decc7e78f1be2 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 14 Nov 2017 00:15:20 +0700 Subject: python/trx: WIP: implement transmission chain --- python/trx/ctrl_if_bb.py | 18 ++-- python/trx/radio_if.py | 223 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 177 insertions(+), 64 deletions(-) diff --git a/python/trx/ctrl_if_bb.py b/python/trx/ctrl_if_bb.py index 99c0451..26ae49a 100644 --- a/python/trx/ctrl_if_bb.py +++ b/python/trx/ctrl_if_bb.py @@ -49,11 +49,6 @@ class ctrl_if_bb(ctrl_if): print("[!] Transceiver already started") return -1 - # Ensure transceiver is ready to start - if not self.tb.check_available(): - print("[!] Transceiver isn't ready to start") - return -1 - print("[i] Starting transceiver...") self.tb.trx_started = True self.tb.start() @@ -97,14 +92,17 @@ class ctrl_if_bb(ctrl_if): # TODO: check freq range freq = int(request[1]) * 1000 - self.tb.set_fc(freq) + self.tb.set_rx_freq(freq) return 0 elif self.verify_cmd(request, "TXTUNE", 1): print("[i] Recv TXTUNE cmd") - # TODO: is not implemented yet + # TODO: check freq range + freq = int(request[1]) * 1000 + self.tb.set_tx_freq(freq) + return 0 # Timeslot management @@ -124,12 +122,12 @@ class ctrl_if_bb(ctrl_if): if config == 0: # Value 0 means 'drop all' - self.tb.gsm_ts_filter.set_policy( + self.tb.ts_filter.set_policy( grgsm.FILTER_POLICY_DROP_ALL) else: - self.tb.gsm_ts_filter.set_policy( + self.tb.ts_filter.set_policy( grgsm.FILTER_POLICY_DEFAULT) - self.tb.gsm_ts_filter.set_tn(tn) + self.tb.ts_filter.set_tn(tn) return 0 diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py index d8c0444..689f074 100644 --- a/python/trx/radio_if.py +++ b/python/trx/radio_if.py @@ -29,17 +29,66 @@ import osmosdr from math import pi +from gnuradio.filter import firdes +from gnuradio import digital from gnuradio import blocks +from gnuradio import uhd from gnuradio import gr + +# HACK: should be implemented in C++! +import numpy as np + +class burst_type_filter(gr.sync_block): + def __init__(self, burst_types=[]): + gr.sync_block.__init__( + self, + name='Burst type filter', + in_sig=[], + out_sig=[] + ) + self.burst_types = burst_types + self.message_port_register_in(pmt.intern("bursts_in")) + self.message_port_register_out(pmt.intern("bursts_out")) + self.set_msg_handler(pmt.intern("bursts_in"), self.filter) + + def filter(self, msg): + burst_with_header = pmt.to_python(pmt.cdr(msg)) + burst = burst_with_header[-148:] + header = np.ndarray.tolist(burst_with_header[0:-148]) + burst_type = header[12] + if burst_type in self.burst_types: + self.message_port_pub(pmt.intern("bursts_out"), msg) + +class burst_to_fn_time(gr.basic_block): + def __init__(self): # only default arguments here + gr.basic_block.__init__( + self, + name='Burst to fn_time', + in_sig=[], + out_sig=[] + ) + self.message_port_register_in(pmt.intern("bursts_in")) + self.message_port_register_out(pmt.intern("fn_time_out")) + self.set_msg_handler(pmt.intern("bursts_in"), self.convert) + + def convert(self, msg): + fn_time = pmt.dict_ref(pmt.car(msg),pmt.intern("fn_time"),pmt.PMT_NIL) + fn_time_msg = pmt.dict_add(pmt.make_dict(), pmt.intern("fn_time"), fn_time) + if pmt.to_python(fn_time) is not None: + self.message_port_pub(pmt.intern("fn_time_out"), fn_time_msg) + class radio_if(gr.top_block): # PHY specific variables - shiftoff = 400e3 - fc = 941.6e6 # TODO: set ARFCN to 0? + rx_freq = 935e6 + tx_freq = 890e6 # Application state flags trx_started = False - fc_set = False + + # GSM timings + delay_correction = 285.616e-6 + ul_dl_shift = -(6.0/1625000*(156.25)*3) def __init__(self, phy_args, phy_sample_rate, phy_rx_gain, phy_tx_gain, phy_ppm, @@ -53,83 +102,149 @@ class radio_if(gr.top_block): self.tx_gain = phy_tx_gain gr.top_block.__init__(self, "GR-GSM TRX") - shift_fc = self.fc - self.shiftoff - - ################################################## - # PHY Definition - ################################################## - self.phy = osmosdr.source(args = "numchan=%d %s" % (1, phy_args)) - - self.phy.set_bandwidth(250e3 + abs(self.shiftoff), 0) - self.phy.set_center_freq(shift_fc, 0) - self.phy.set_sample_rate(phy_sample_rate) - self.phy.set_freq_corr(phy_ppm, 0) - self.phy.set_iq_balance_mode(2, 0) - self.phy.set_dc_offset_mode(2, 0) - self.phy.set_gain_mode(False, 0) - self.phy.set_gain(self.rx_gain, 0) - self.phy.set_if_gain(20, 0) - self.phy.set_bb_gain(20, 0) - self.phy.set_antenna(phy_rx_antenna, 0) - - ################################################## - # GR-GSM Magic - ################################################## - self.blocks_rotator = blocks.rotator_cc( - -2 * pi * self.shiftoff / phy_sample_rate) + + # TRX Burst Interface + self.trx_burst_if = grgsm.trx_burst_if( + trx_remote_addr, str(trx_base_port)) + + + # RX path definition + self.phy_src = uhd.usrp_source(phy_args, + uhd.stream_args(cpu_format="fc32", + channels=range(1))) + + self.phy_src.set_center_freq(self.rx_freq, 0) + self.phy_src.set_antenna(phy_rx_antenna, 0) + self.phy_src.set_samp_rate(phy_sample_rate) + self.phy_src.set_bandwidth(650e3, 0) + self.phy_src.set_gain(phy_rx_gain) self.gsm_input = grgsm.gsm_input( - ppm = phy_ppm, osr = 4, fc = self.fc, - samp_rate_in = phy_sample_rate) + ppm = phy_ppm - int(phy_ppm), osr = 4, + fc = self.rx_freq, samp_rate_in = phy_sample_rate) self.gsm_receiver = grgsm.receiver(4, ([0]), ([])) self.gsm_clck_ctrl = grgsm.clock_offset_control( - shift_fc, phy_sample_rate, osr = 4) + self.rx_freq, phy_sample_rate, osr = 4) - self.gsm_ts_filter = grgsm.burst_timeslot_filter(0) - self.gsm_ts_filter.set_policy(grgsm.FILTER_POLICY_DROP_ALL) + self.ts_filter = grgsm.burst_timeslot_filter(0) + self.ts_filter.set_policy(grgsm.FILTER_POLICY_DROP_ALL) - self.gsm_trx_burst_if = grgsm.trx_burst_if( - trx_remote_addr, str(trx_base_port)) - - ################################################## # Connections - ################################################## - self.connect((self.phy, 0), (self.blocks_rotator, 0)) - self.connect((self.blocks_rotator, 0), (self.gsm_input, 0)) - self.connect((self.gsm_input, 0), (self.gsm_receiver, 0)) + self.connect( + (self.phy_src, 0), + (self.gsm_input, 0)) + + self.connect( + (self.gsm_input, 0), + (self.gsm_receiver, 0)) + + self.msg_connect( + (self.gsm_receiver, 'C0'), + (self.ts_filter, 'in')) - self.msg_connect((self.gsm_receiver, 'measurements'), + self.msg_connect( + (self.ts_filter, 'out'), + (self.trx_burst_if, 'bursts')) + + self.msg_connect( + (self.gsm_receiver, 'measurements'), (self.gsm_clck_ctrl, 'measurements')) - self.msg_connect((self.gsm_clck_ctrl, 'ctrl'), + self.msg_connect( + (self.gsm_clck_ctrl, 'ctrl'), (self.gsm_input, 'ctrl_in')) - self.msg_connect((self.gsm_receiver, 'C0'), - (self.gsm_ts_filter, 'in')) - self.msg_connect((self.gsm_ts_filter, 'out'), - (self.gsm_trx_burst_if, 'bursts')) + # TX Path Definition + self.phy_sink = uhd.usrp_sink(phy_args, + uhd.stream_args(cpu_format="fc32", + channels=range(1)), "packet_len") + + self.phy_sink.set_antenna(phy_tx_antenna, 0) + self.phy_sink.set_samp_rate(phy_sample_rate) + self.phy_sink.set_center_freq(self.tx_freq, 0) + self.phy_sink.set_gain(self.tx_gain) + + self.tx_time_setter = grgsm.txtime_setter( + 0xffffffff, 0, 0, 0, 0, 0, + self.delay_correction + self.ul_dl_shift) + + self.tx_burst_proc = grgsm.preprocess_tx_burst() - def check_available(self): - return self.fc_set + self.pdu_to_tagged_stream = blocks.pdu_to_tagged_stream( + blocks.byte_t, 'packet_len') + + self.gmsk_mod = grgsm.gsm_gmsk_mod( + BT = 4, pulse_duration = 4, sps = 4) + + self.burst_shaper = digital.burst_shaper_cc( + (firdes.window(firdes.WIN_HANN, 16, 0)), + 0, 20, False, "packet_len") + + # Connections + self.msg_connect( + (self.trx_burst_if, 'bursts'), + (self.tx_time_setter, 'bursts_in')) + + self.msg_connect( + (self.tx_time_setter, 'bursts_out'), + (self.tx_burst_proc, 'bursts_in')) + + self.msg_connect( + (self.tx_burst_proc, 'bursts_out'), + (self.pdu_to_tagged_stream, 'pdus')) + + self.connect( + (self.pdu_to_tagged_stream, 0), + (self.gmsk_mod, 0)) + + self.connect( + (self.gmsk_mod, 0), + (self.burst_shaper, 0)) + + self.connect( + (self.burst_shaper, 0), + (self.phy_sink, 0)) + + + # RX & TX synchronization + self.bt_filter = burst_type_filter([3]) + self.burst_to_fn_time = burst_to_fn_time() + + # Connections + self.msg_connect( + (self.gsm_receiver, 'C0'), + (self.bt_filter, 'bursts_in')) + + self.msg_connect( + (self.bt_filter, 'bursts_out'), + (self.burst_to_fn_time, 'bursts_in')) + + self.msg_connect( + (self.burst_to_fn_time, 'fn_time_out'), + (self.tx_time_setter, 'fn_time')) def shutdown(self): print("[i] Shutdown Radio interface") self.stop() self.wait() - def set_fc(self, fc): - self.phy.set_center_freq(fc - self.shiftoff, 0) + def set_rx_freq(self, fc): + self.phy_src.set_center_freq(fc, 0) + self.gsm_clck_ctrl.set_fc(fc) self.gsm_input.set_fc(fc) - self.fc_set = True - self.fc = fc + self.rx_freq = fc + + def set_tx_freq(self, fc): + self.phy_sink.set_center_freq(fc, 0) + self.tx_freq = fc def set_rx_gain(self, gain): - self.phy.set_gain(gain, 0) + self.phy_src.set_gain(gain, 0) self.rx_gain = gain def set_tx_gain(self, gain): - # TODO: TX chain not implemented yet + self.phy_sink.set_gain(gain, 0) self.tx_gain = gain -- cgit v1.2.3 From ccd9ed9cab560590f2ec4af41abdbf2d28c094f7 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Thu, 30 Nov 2017 12:48:01 +0100 Subject: Going back to previous coding style - without returns --- lib/transmitter/txtime_setter_impl.cc | 94 ++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/lib/transmitter/txtime_setter_impl.cc b/lib/transmitter/txtime_setter_impl.cc index f6141f0..33bc994 100644 --- a/lib/transmitter/txtime_setter_impl.cc +++ b/lib/transmitter/txtime_setter_impl.cc @@ -30,6 +30,9 @@ #include "txtime_setter_impl.h" +#define UNKNOWN_FN 0xffffffff +#define MAX_EARLY_TIME_DIFF 10.0 + namespace gr { namespace gsm { @@ -114,52 +117,53 @@ namespace gr { void txtime_setter_impl::process_txtime_of_burst(pmt::pmt_t msg_in) { - // Nothing to do... - if (d_fn_ref == 0xffffffff) - return; - - pmt::pmt_t blob = pmt::cdr(msg_in); - - // Extract GSMTAP header from message - gsmtap_hdr *header = (gsmtap_hdr *) pmt::blob_data(blob); - uint32_t frame_nr = be32toh(header->frame_number); - uint32_t ts_num = header->timeslot; - - time_format txtime = fn_time_delta_cpp(d_fn_ref, d_time_ref, - frame_nr, d_time_hint, ts_num, d_ts_ref); - - time_spec_t txtime_spec = time_spec_t(txtime.first, txtime.second); - txtime_spec -= d_delay_correction; - txtime_spec -= d_timing_advance; - - // FIXME: better name? - time_spec_t foo = time_spec_t(d_time_hint.first, d_time_hint.second); - - // Drop too late / early bursts - if (txtime_spec <= foo) { - std::cout << "lB" << std::flush; - return; - } else if (txtime_spec > foo + 10.0) { - std::cout << "eB" << std::flush; - return; + if (d_fn_ref != UNKNOWN_FN) + { + pmt::pmt_t blob = pmt::cdr(msg_in); + + // Extract GSMTAP header from message + gsmtap_hdr *header = (gsmtap_hdr *) pmt::blob_data(blob); + uint32_t frame_nr = be32toh(header->frame_number); + uint32_t ts_num = header->timeslot; + + time_format txtime = fn_time_delta_cpp(d_fn_ref, d_time_ref, + frame_nr, d_time_hint, ts_num, d_ts_ref); + + time_spec_t txtime_spec = time_spec_t(txtime.first, txtime.second); + txtime_spec -= d_delay_correction; + txtime_spec -= d_timing_advance; + + time_spec_t current_time_estimate = time_spec_t(d_time_hint.first, d_time_hint.second); + + if (txtime_spec <= current_time_estimate) { // Drop too late bursts + std::cout << "lB" << std::flush; + } else if (txtime_spec > current_time_estimate + MAX_EARLY_TIME_DIFF) { // Drop too early bursts + std::cout << "eB" << std::flush; //TODO: too early condition might happen when changing BTSes. + //Wrong fn_time is applied to new or old bursts in such situation. + //This solution is not perfect as MS might be blocked upto + //MAX_EARLY_TIME_DIFF seconds. + //Better solution would be to indentify fn_time and burst coming + //from given BTS (i.e. based on ARFCN) and dropping bursts for which + //the bts_id doesn't match with bts_id of fn_time. + } else { //process bursts that are in the right time-frame + pmt::pmt_t tags_dict = pmt::dict_add( + pmt::make_dict(), + pmt::intern("tx_time"), + pmt::make_tuple( + pmt::from_uint64(txtime_spec.get_full_secs()), + pmt::from_double(txtime_spec.get_frac_secs())) + ); + + tags_dict = pmt::dict_add(tags_dict, + pmt::intern("fn"), pmt::from_uint64(frame_nr)); + tags_dict = pmt::dict_add(tags_dict, + pmt::intern("ts"), pmt::from_uint64(ts_num)); + + // Send a message to the output + pmt::pmt_t msg_out = pmt::cons(tags_dict, pmt::cdr(msg_in)); + message_port_pub(pmt::mp("bursts_out"), msg_out); + } } - - pmt::pmt_t tags_dict = pmt::dict_add( - pmt::make_dict(), - pmt::intern("tx_time"), - pmt::make_tuple( - pmt::from_uint64(txtime_spec.get_full_secs()), - pmt::from_double(txtime_spec.get_frac_secs())) - ); - - tags_dict = pmt::dict_add(tags_dict, - pmt::intern("fn"), pmt::from_uint64(frame_nr)); - tags_dict = pmt::dict_add(tags_dict, - pmt::intern("ts"), pmt::from_uint64(ts_num)); - - // Send a message to the output - pmt::pmt_t msg_out = pmt::cons(tags_dict, pmt::cdr(msg_in)); - message_port_pub(pmt::mp("bursts_out"), msg_out); } void txtime_setter_impl::set_fn_time_reference( -- cgit v1.2.3 From d2f162fa5eab5cfdf4332101b4a55aaac6d96290 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Thu, 30 Nov 2017 12:50:00 +0100 Subject: trx: Changes in the redio_if -added a part generated by GRC (radio_if_grc) form trx_radio_if example, -radio_if now only adds things that are missing in radio_if_grc --- python/trx/CMakeLists.txt | 4 +- python/trx/__init__.py | 1 + python/trx/radio_if.py | 231 ++++------------------------------------ python/trx/radio_if_grc.py | 259 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 283 insertions(+), 212 deletions(-) create mode 100755 python/trx/radio_if_grc.py diff --git a/python/trx/CMakeLists.txt b/python/trx/CMakeLists.txt index d8e9164..4049e54 100644 --- a/python/trx/CMakeLists.txt +++ b/python/trx/CMakeLists.txt @@ -24,5 +24,7 @@ GR_PYTHON_INSTALL( ctrl_if.py ctrl_if_bb.py fake_pm.py - radio_if.py DESTINATION ${GR_PYTHON_DIR}/grgsm/trx + radio_if.py + radio_if_grc.py + DESTINATION ${GR_PYTHON_DIR}/grgsm/trx ) diff --git a/python/trx/__init__.py b/python/trx/__init__.py index 81e569c..5d193b5 100644 --- a/python/trx/__init__.py +++ b/python/trx/__init__.py @@ -24,4 +24,5 @@ from udp_link import udp_link from ctrl_if import ctrl_if from ctrl_if_bb import ctrl_if_bb from fake_pm import fake_pm +from radio_if_grc import radio_if_grc from radio_if import radio_if diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py index 689f074..9e97277 100644 --- a/python/trx/radio_if.py +++ b/python/trx/radio_if.py @@ -2,9 +2,10 @@ # -*- coding: utf-8 -*- # GR-GSM based transceiver -# Follow graph implementation +# Extending a GRC flowgraph gr-gsm/examples/trx_radio_if/radio_if_grc.grc # # (C) 2016-2017 by Vadim Yanitskiy +# (C) 2017 by Piotr Krysik # # All Rights Reserved # @@ -22,229 +23,37 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -import pmt -import time -import grgsm -import osmosdr - -from math import pi - -from gnuradio.filter import firdes -from gnuradio import digital -from gnuradio import blocks -from gnuradio import uhd -from gnuradio import gr - - -# HACK: should be implemented in C++! -import numpy as np - -class burst_type_filter(gr.sync_block): - def __init__(self, burst_types=[]): - gr.sync_block.__init__( - self, - name='Burst type filter', - in_sig=[], - out_sig=[] - ) - self.burst_types = burst_types - self.message_port_register_in(pmt.intern("bursts_in")) - self.message_port_register_out(pmt.intern("bursts_out")) - self.set_msg_handler(pmt.intern("bursts_in"), self.filter) - - def filter(self, msg): - burst_with_header = pmt.to_python(pmt.cdr(msg)) - burst = burst_with_header[-148:] - header = np.ndarray.tolist(burst_with_header[0:-148]) - burst_type = header[12] - if burst_type in self.burst_types: - self.message_port_pub(pmt.intern("bursts_out"), msg) - -class burst_to_fn_time(gr.basic_block): - def __init__(self): # only default arguments here - gr.basic_block.__init__( - self, - name='Burst to fn_time', - in_sig=[], - out_sig=[] - ) - self.message_port_register_in(pmt.intern("bursts_in")) - self.message_port_register_out(pmt.intern("fn_time_out")) - self.set_msg_handler(pmt.intern("bursts_in"), self.convert) - - def convert(self, msg): - fn_time = pmt.dict_ref(pmt.car(msg),pmt.intern("fn_time"),pmt.PMT_NIL) - fn_time_msg = pmt.dict_add(pmt.make_dict(), pmt.intern("fn_time"), fn_time) - if pmt.to_python(fn_time) is not None: - self.message_port_pub(pmt.intern("fn_time_out"), fn_time_msg) - -class radio_if(gr.top_block): - # PHY specific variables - rx_freq = 935e6 - tx_freq = 890e6 +from grgsm.trx import radio_if_grc +class radio_if(radio_if_grc): # Application state flags trx_started = False - # GSM timings - delay_correction = 285.616e-6 - ul_dl_shift = -(6.0/1625000*(156.25)*3) - def __init__(self, phy_args, phy_sample_rate, phy_rx_gain, phy_tx_gain, phy_ppm, phy_rx_antenna, phy_tx_antenna, - trx_remote_addr, trx_base_port): + trx_remote_addr, trx_base_port, + phy_tx_freq=938900000, + phy_rx_freq=938900000-45e6, + delay_correction=285.616e-6, + uplink_shift=-(6.0/1625000*(156.25)*3), + timing_advance=0): print("[i] Init Radio interface") - # PHY specific variables - self.rx_gain = phy_rx_gain - self.tx_gain = phy_tx_gain - - gr.top_block.__init__(self, "GR-GSM TRX") - - # TRX Burst Interface - self.trx_burst_if = grgsm.trx_burst_if( - trx_remote_addr, str(trx_base_port)) - - - # RX path definition - self.phy_src = uhd.usrp_source(phy_args, - uhd.stream_args(cpu_format="fc32", - channels=range(1))) - - self.phy_src.set_center_freq(self.rx_freq, 0) - self.phy_src.set_antenna(phy_rx_antenna, 0) - self.phy_src.set_samp_rate(phy_sample_rate) - self.phy_src.set_bandwidth(650e3, 0) - self.phy_src.set_gain(phy_rx_gain) - - self.gsm_input = grgsm.gsm_input( - ppm = phy_ppm - int(phy_ppm), osr = 4, - fc = self.rx_freq, samp_rate_in = phy_sample_rate) - - self.gsm_receiver = grgsm.receiver(4, ([0]), ([])) - - self.gsm_clck_ctrl = grgsm.clock_offset_control( - self.rx_freq, phy_sample_rate, osr = 4) - - self.ts_filter = grgsm.burst_timeslot_filter(0) - self.ts_filter.set_policy(grgsm.FILTER_POLICY_DROP_ALL) - - # Connections - self.connect( - (self.phy_src, 0), - (self.gsm_input, 0)) - - self.connect( - (self.gsm_input, 0), - (self.gsm_receiver, 0)) - - self.msg_connect( - (self.gsm_receiver, 'C0'), - (self.ts_filter, 'in')) - - self.msg_connect( - (self.ts_filter, 'out'), - (self.trx_burst_if, 'bursts')) - - self.msg_connect( - (self.gsm_receiver, 'measurements'), - (self.gsm_clck_ctrl, 'measurements')) - - self.msg_connect( - (self.gsm_clck_ctrl, 'ctrl'), - (self.gsm_input, 'ctrl_in')) - - - # TX Path Definition - self.phy_sink = uhd.usrp_sink(phy_args, - uhd.stream_args(cpu_format="fc32", - channels=range(1)), "packet_len") - - self.phy_sink.set_antenna(phy_tx_antenna, 0) - self.phy_sink.set_samp_rate(phy_sample_rate) - self.phy_sink.set_center_freq(self.tx_freq, 0) - self.phy_sink.set_gain(self.tx_gain) - - self.tx_time_setter = grgsm.txtime_setter( - 0xffffffff, 0, 0, 0, 0, 0, - self.delay_correction + self.ul_dl_shift) - - self.tx_burst_proc = grgsm.preprocess_tx_burst() - - self.pdu_to_tagged_stream = blocks.pdu_to_tagged_stream( - blocks.byte_t, 'packet_len') - - self.gmsk_mod = grgsm.gsm_gmsk_mod( - BT = 4, pulse_duration = 4, sps = 4) - - self.burst_shaper = digital.burst_shaper_cc( - (firdes.window(firdes.WIN_HANN, 16, 0)), - 0, 20, False, "packet_len") - - # Connections - self.msg_connect( - (self.trx_burst_if, 'bursts'), - (self.tx_time_setter, 'bursts_in')) - - self.msg_connect( - (self.tx_time_setter, 'bursts_out'), - (self.tx_burst_proc, 'bursts_in')) - - self.msg_connect( - (self.tx_burst_proc, 'bursts_out'), - (self.pdu_to_tagged_stream, 'pdus')) - - self.connect( - (self.pdu_to_tagged_stream, 0), - (self.gmsk_mod, 0)) - - self.connect( - (self.gmsk_mod, 0), - (self.burst_shaper, 0)) - - self.connect( - (self.burst_shaper, 0), - (self.phy_sink, 0)) - - - # RX & TX synchronization - self.bt_filter = burst_type_filter([3]) - self.burst_to_fn_time = burst_to_fn_time() - - # Connections - self.msg_connect( - (self.gsm_receiver, 'C0'), - (self.bt_filter, 'bursts_in')) - - self.msg_connect( - (self.bt_filter, 'bursts_out'), - (self.burst_to_fn_time, 'bursts_in')) - - self.msg_connect( - (self.burst_to_fn_time, 'fn_time_out'), - (self.tx_time_setter, 'fn_time')) + radio_if_grc.__init__(self, + samp_rate=phy_sample_rate, + tx_gain=phy_tx_gain, rx_gain=phy_rx_gain, + tx_freq=phy_tx_freq, rx_freq=phy_rx_freq, + osr=4, ppm=phy_ppm, + trx_base_port=str(trx_base_port), + trx_remote_addr=trx_remote_addr, + delay_correction=delay_correction, + uplink_shift=uplink_shift, + timing_advance=timing_advance) def shutdown(self): print("[i] Shutdown Radio interface") self.stop() self.wait() - def set_rx_freq(self, fc): - self.phy_src.set_center_freq(fc, 0) - self.gsm_clck_ctrl.set_fc(fc) - self.gsm_input.set_fc(fc) - self.rx_freq = fc - - def set_tx_freq(self, fc): - self.phy_sink.set_center_freq(fc, 0) - self.tx_freq = fc - - def set_rx_gain(self, gain): - self.phy_src.set_gain(gain, 0) - self.rx_gain = gain - - def set_tx_gain(self, gain): - self.phy_sink.set_gain(gain, 0) - self.tx_gain = gain diff --git a/python/trx/radio_if_grc.py b/python/trx/radio_if_grc.py new file mode 100755 index 0000000..26c1f22 --- /dev/null +++ b/python/trx/radio_if_grc.py @@ -0,0 +1,259 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- +################################################## +# GNU Radio Python Flow Graph +# Title: Trx radio interface +# Author: (C) Piotr Krysik 2017 +# Description: Alpha version of trx radio interface +# Generated: Thu Nov 30 12:45:52 2017 +################################################## + +from gnuradio import blocks +from gnuradio import digital +from gnuradio import eng_notation +from gnuradio import filter +from gnuradio import gr +from gnuradio import uhd +from gnuradio.eng_option import eng_option +from gnuradio.filter import firdes +from grgsm import gsm_gmsk_mod +from optparse import OptionParser +import grgsm +import math +import time + + +class radio_if_grc(gr.top_block): + + def __init__(self, delay_correction=285.616e-6, osr=4, ppm=-1, rx_freq=938600000, rx_gain=40, samp_rate=13e6/12.0, timing_advance=0, trx_base_port="5700", trx_remote_addr="127.0.0.1", tx_freq=938900000, tx_gain=30, uplink_shift=-(6.0/1625000*(156.25)*3)): + gr.top_block.__init__(self, "Trx radio interface") + + ################################################## + # Parameters + ################################################## + self.delay_correction = delay_correction + self.osr = osr + self.ppm = ppm + self.rx_freq = rx_freq + self.rx_gain = rx_gain + self.samp_rate = samp_rate + self.timing_advance = timing_advance + self.trx_base_port = trx_base_port + self.trx_remote_addr = trx_remote_addr + self.tx_freq = tx_freq + self.tx_gain = tx_gain + self.uplink_shift = uplink_shift + + ################################################## + # Blocks + ################################################## + self.uhd_usrp_source_0 = uhd.usrp_source( + ",".join(("", "")), + uhd.stream_args( + cpu_format="fc32", + channels=range(1), + ), + ) + self.uhd_usrp_source_0.set_clock_rate(26e6, uhd.ALL_MBOARDS) + self.uhd_usrp_source_0.set_samp_rate(samp_rate) + self.uhd_usrp_source_0.set_center_freq(rx_freq, 0) + self.uhd_usrp_source_0.set_gain(rx_gain, 0) + self.uhd_usrp_source_0.set_antenna("RX2", 0) + self.uhd_usrp_sink_0 = uhd.usrp_sink( + ",".join(("", "")), + uhd.stream_args( + cpu_format="fc32", + channels=range(1), + ), + "packet_len", + ) + self.uhd_usrp_sink_0.set_clock_rate(26e6, uhd.ALL_MBOARDS) + self.uhd_usrp_sink_0.set_subdev_spec("A:B", 0) + self.uhd_usrp_sink_0.set_samp_rate(samp_rate) + self.uhd_usrp_sink_0.set_center_freq(tx_freq, 0) + self.uhd_usrp_sink_0.set_gain(tx_gain, 0) + self.uhd_usrp_sink_0.set_antenna("TX/RX", 0) + self.low_pass_filter_0_0 = filter.fir_filter_ccf(1, firdes.low_pass( + 1, samp_rate, 125e3, 5e3, firdes.WIN_HAMMING, 6.76)) + self.gsm_txtime_setter_0 = grgsm.txtime_setter(None if (None is not None) else 0xffffffff, 0, 0, 0, 0, timing_advance, delay_correction+uplink_shift) + self.gsm_trx_burst_if_0 = grgsm.trx_burst_if(trx_remote_addr, trx_base_port) + self.gsm_receiver_0 = grgsm.receiver(4, ([0]), ([4]), False) + self.gsm_preprocess_tx_burst_0 = grgsm.preprocess_tx_burst() + self.gsm_msg_to_tag_0_0 = grgsm.msg_to_tag() + self.gsm_msg_to_tag_0 = grgsm.msg_to_tag() + self.gsm_gmsk_mod_0 = gsm_gmsk_mod( + BT=0.3, + pulse_duration=4, + sps=osr, + ) + self.gsm_controlled_rotator_cc_0_0 = grgsm.controlled_rotator_cc(-ppm/1.0e6*2*math.pi*tx_freq/samp_rate) + self.gsm_controlled_rotator_cc_0 = grgsm.controlled_rotator_cc(ppm/1.0e6*2*math.pi*rx_freq/samp_rate) + self.gsm_burst_type_filter_0 = grgsm.burst_type_filter(([3])) + self.gsm_burst_to_fn_time_0 = grgsm.burst_to_fn_time() + self.digital_burst_shaper_xx_0 = digital.burst_shaper_cc((firdes.window(firdes.WIN_HANN, 16, 0)), 0, 20, False, "packet_len") + self.blocks_pdu_to_tagged_stream_0_0 = blocks.pdu_to_tagged_stream(blocks.byte_t, "packet_len") + + ################################################## + # Connections + ################################################## + self.msg_connect((self.gsm_burst_to_fn_time_0, 'fn_time_out'), (self.gsm_txtime_setter_0, 'fn_time')) + self.msg_connect((self.gsm_burst_type_filter_0, 'bursts_out'), (self.gsm_burst_to_fn_time_0, 'bursts_in')) + self.msg_connect((self.gsm_preprocess_tx_burst_0, 'bursts_out'), (self.blocks_pdu_to_tagged_stream_0_0, 'pdus')) + self.msg_connect((self.gsm_receiver_0, 'C0'), (self.gsm_burst_type_filter_0, 'bursts_in')) + self.msg_connect((self.gsm_receiver_0, 'C0'), (self.gsm_trx_burst_if_0, 'bursts')) + self.msg_connect((self.gsm_trx_burst_if_0, 'bursts'), (self.gsm_txtime_setter_0, 'bursts_in')) + self.msg_connect((self.gsm_txtime_setter_0, 'bursts_out'), (self.gsm_preprocess_tx_burst_0, 'bursts_in')) + self.connect((self.blocks_pdu_to_tagged_stream_0_0, 0), (self.gsm_gmsk_mod_0, 0)) + self.connect((self.digital_burst_shaper_xx_0, 0), (self.gsm_msg_to_tag_0_0, 0)) + self.connect((self.gsm_controlled_rotator_cc_0, 0), (self.low_pass_filter_0_0, 0)) + self.connect((self.gsm_controlled_rotator_cc_0_0, 0), (self.uhd_usrp_sink_0, 0)) + self.connect((self.gsm_gmsk_mod_0, 0), (self.digital_burst_shaper_xx_0, 0)) + self.connect((self.gsm_msg_to_tag_0, 0), (self.gsm_controlled_rotator_cc_0, 0)) + self.connect((self.gsm_msg_to_tag_0_0, 0), (self.gsm_controlled_rotator_cc_0_0, 0)) + self.connect((self.low_pass_filter_0_0, 0), (self.gsm_receiver_0, 0)) + self.connect((self.uhd_usrp_source_0, 0), (self.gsm_msg_to_tag_0, 0)) + + def get_delay_correction(self): + return self.delay_correction + + def set_delay_correction(self, delay_correction): + self.delay_correction = delay_correction + self.gsm_txtime_setter_0.set_delay_correction(self.delay_correction+self.uplink_shift) + + def get_osr(self): + return self.osr + + def set_osr(self, osr): + self.osr = osr + self.gsm_gmsk_mod_0.set_sps(self.osr) + + def get_ppm(self): + return self.ppm + + def set_ppm(self, ppm): + self.ppm = ppm + self.gsm_controlled_rotator_cc_0.set_phase_inc(self.ppm/1.0e6*2*math.pi*self.rx_freq/self.samp_rate) + self.gsm_controlled_rotator_cc_0_0.set_phase_inc(-self.ppm/1.0e6*2*math.pi*self.tx_freq/self.samp_rate) + + def get_rx_freq(self): + return self.rx_freq + + def set_rx_freq(self, rx_freq): + self.rx_freq = rx_freq + self.gsm_controlled_rotator_cc_0.set_phase_inc(self.ppm/1.0e6*2*math.pi*self.rx_freq/self.samp_rate) + self.uhd_usrp_source_0.set_center_freq(self.rx_freq, 0) + + def get_rx_gain(self): + return self.rx_gain + + def set_rx_gain(self, rx_gain): + self.rx_gain = rx_gain + self.uhd_usrp_source_0.set_gain(self.rx_gain, 0) + + + def get_samp_rate(self): + return self.samp_rate + + def set_samp_rate(self, samp_rate): + self.samp_rate = samp_rate + self.gsm_controlled_rotator_cc_0.set_phase_inc(self.ppm/1.0e6*2*math.pi*self.rx_freq/self.samp_rate) + self.gsm_controlled_rotator_cc_0_0.set_phase_inc(-self.ppm/1.0e6*2*math.pi*self.tx_freq/self.samp_rate) + self.low_pass_filter_0_0.set_taps(firdes.low_pass(1, self.samp_rate, 125e3, 5e3, firdes.WIN_HAMMING, 6.76)) + self.uhd_usrp_sink_0.set_samp_rate(self.samp_rate) + self.uhd_usrp_source_0.set_samp_rate(self.samp_rate) + + def get_timing_advance(self): + return self.timing_advance + + def set_timing_advance(self, timing_advance): + self.timing_advance = timing_advance + self.gsm_txtime_setter_0.set_timing_advance(self.timing_advance) + + def get_trx_base_port(self): + return self.trx_base_port + + def set_trx_base_port(self, trx_base_port): + self.trx_base_port = trx_base_port + + def get_trx_remote_addr(self): + return self.trx_remote_addr + + def set_trx_remote_addr(self, trx_remote_addr): + self.trx_remote_addr = trx_remote_addr + + def get_tx_freq(self): + return self.tx_freq + + def set_tx_freq(self, tx_freq): + self.tx_freq = tx_freq + self.gsm_controlled_rotator_cc_0_0.set_phase_inc(-self.ppm/1.0e6*2*math.pi*self.tx_freq/self.samp_rate) + self.uhd_usrp_sink_0.set_center_freq(self.tx_freq, 0) + + def get_tx_gain(self): + return self.tx_gain + + def set_tx_gain(self, tx_gain): + self.tx_gain = tx_gain + self.uhd_usrp_sink_0.set_gain(self.tx_gain, 0) + + + def get_uplink_shift(self): + return self.uplink_shift + + def set_uplink_shift(self, uplink_shift): + self.uplink_shift = uplink_shift + self.gsm_txtime_setter_0.set_delay_correction(self.delay_correction+self.uplink_shift) + + +def argument_parser(): + parser = OptionParser(option_class=eng_option, usage="%prog: [options]") + parser.add_option( + "", "--delay-correction", dest="delay_correction", type="eng_float", default=eng_notation.num_to_str(285.616e-6), + help="Set delay_correction [default=%default]") + parser.add_option( + "", "--osr", dest="osr", type="intx", default=4, + help="Set OSR [default=%default]") + parser.add_option( + "", "--ppm", dest="ppm", type="eng_float", default=eng_notation.num_to_str(-1), + help="Set Clock offset correction [default=%default]") + parser.add_option( + "-d", "--rx-freq", dest="rx_freq", type="eng_float", default=eng_notation.num_to_str(938600000), + help="Set rx_freq [default=%default]") + parser.add_option( + "-g", "--rx-gain", dest="rx_gain", type="eng_float", default=eng_notation.num_to_str(40), + help="Set rx_gain [default=%default]") + parser.add_option( + "", "--samp-rate", dest="samp_rate", type="eng_float", default=eng_notation.num_to_str(13e6/12.0), + help="Set samp_rate [default=%default]") + parser.add_option( + "", "--timing-advance", dest="timing_advance", type="eng_float", default=eng_notation.num_to_str(0), + help="Set timing_advance [default=%default]") + parser.add_option( + "", "--trx-base-port", dest="trx_base_port", type="string", default="5700", + help="Set 5700 [default=%default]") + parser.add_option( + "", "--trx-remote-addr", dest="trx_remote_addr", type="string", default="127.0.0.1", + help="Set 127.0.0.1 [default=%default]") + parser.add_option( + "-u", "--tx-freq", dest="tx_freq", type="eng_float", default=eng_notation.num_to_str(938900000), + help="Set tx_freq [default=%default]") + parser.add_option( + "-r", "--tx-gain", dest="tx_gain", type="eng_float", default=eng_notation.num_to_str(30), + help="Set tx_gain [default=%default]") + parser.add_option( + "", "--uplink-shift", dest="uplink_shift", type="eng_float", default=eng_notation.num_to_str(-(6.0/1625000*(156.25)*3)), + help="Set uplink_shift [default=%default]") + return parser + + +def main(top_block_cls=radio_if_grc, options=None): + if options is None: + options, _ = argument_parser().parse_args() + + tb = top_block_cls(delay_correction=options.delay_correction, osr=options.osr, ppm=options.ppm, rx_freq=options.rx_freq, rx_gain=options.rx_gain, samp_rate=options.samp_rate, timing_advance=options.timing_advance, trx_base_port=options.trx_base_port, trx_remote_addr=options.trx_remote_addr, tx_freq=options.tx_freq, tx_gain=options.tx_gain, uplink_shift=options.uplink_shift) + tb.start() + tb.wait() + + +if __name__ == '__main__': + main() -- cgit v1.2.3 From e3f34d9bca7ee762b98a6e0f5d9fb541d231be7d Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Thu, 30 Nov 2017 12:50:37 +0100 Subject: test_ab: Changed to non-inverted AB --- lib/transmitter/gen_test_ab_impl.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/transmitter/gen_test_ab_impl.cc b/lib/transmitter/gen_test_ab_impl.cc index 66873db..bb9c9f6 100644 --- a/lib/transmitter/gen_test_ab_impl.cc +++ b/lib/transmitter/gen_test_ab_impl.cc @@ -38,11 +38,11 @@ namespace gr { 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, }; -// static uint8_t AB[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + static uint8_t AB[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // static uint8_t AB[] = {0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1}; // static uint8_t AB[] = { 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1}; - static uint8_t AB[] = {1,1,1,1,1,1,1,1,1,0,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,0,1,0,1,0,1,1,1,0,0,0,0,1,1,1,0,0,1,0,0,0,1,0,1,0,1,0,0,1,0,1,0,1,1,0,1,1,0,0,1,0,1,0,0,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 - ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; +// static uint8_t AB[] = {1,1,1,1,1,1,1,1,1,0,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,0,1,0,1,0,1,1,1,0,0,0,0,1,1,1,0,0,1,0,0,0,1,0,1,0,1,0,0,1,0,1,0,1,1,0,1,1,0,0,1,0,1,0,0,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +// ,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; gen_test_ab::sptr gen_test_ab::make() { -- cgit v1.2.3 From 2ef8fe1e63bebab8d34ff648e29e8f113761cb51 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Thu, 30 Nov 2017 12:53:41 +0100 Subject: Updated the examples pointer --- examples | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples b/examples index a548123..de98b24 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit a5481238c3866808363b7beaf33d1937debe708a +Subproject commit de98b247d4d60ece9f07275b471fe3e24edad9b4 -- cgit v1.2.3 From 294138d277f138c802aa5ad084c91d6325284491 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Thu, 30 Nov 2017 13:06:31 +0100 Subject: trx: Added missing timeslot filter --- python/trx/radio_if_grc.py | 147 ++++++++++++++++++++++++--------------------- 1 file changed, 78 insertions(+), 69 deletions(-) diff --git a/python/trx/radio_if_grc.py b/python/trx/radio_if_grc.py index 26c1f22..8b53fe7 100755 --- a/python/trx/radio_if_grc.py +++ b/python/trx/radio_if_grc.py @@ -5,7 +5,7 @@ # Title: Trx radio interface # Author: (C) Piotr Krysik 2017 # Description: Alpha version of trx radio interface -# Generated: Thu Nov 30 12:45:52 2017 +# Generated: Thu Nov 30 13:02:31 2017 ################################################## from gnuradio import blocks @@ -25,24 +25,24 @@ import time class radio_if_grc(gr.top_block): - def __init__(self, delay_correction=285.616e-6, osr=4, ppm=-1, rx_freq=938600000, rx_gain=40, samp_rate=13e6/12.0, timing_advance=0, trx_base_port="5700", trx_remote_addr="127.0.0.1", tx_freq=938900000, tx_gain=30, uplink_shift=-(6.0/1625000*(156.25)*3)): + def __init__(self, samp_rate=13e6/12.0, tx_gain=30, tx_freq=938900000, rx_freq=938600000, rx_gain=40, osr=4, ppm=-1, trx_base_port="5700", trx_remote_addr="127.0.0.1", delay_correction=285.616e-6, uplink_shift=-(6.0/1625000*(156.25)*3), timing_advance=0): gr.top_block.__init__(self, "Trx radio interface") ################################################## # Parameters ################################################## - self.delay_correction = delay_correction - self.osr = osr - self.ppm = ppm + self.samp_rate = samp_rate + self.tx_gain = tx_gain + self.tx_freq = tx_freq self.rx_freq = rx_freq self.rx_gain = rx_gain - self.samp_rate = samp_rate - self.timing_advance = timing_advance + self.osr = osr + self.ppm = ppm self.trx_base_port = trx_base_port self.trx_remote_addr = trx_remote_addr - self.tx_freq = tx_freq - self.tx_gain = tx_gain + self.delay_correction = delay_correction self.uplink_shift = uplink_shift + self.timing_advance = timing_advance ################################################## # Blocks @@ -73,6 +73,7 @@ class radio_if_grc(gr.top_block): self.uhd_usrp_sink_0.set_center_freq(tx_freq, 0) self.uhd_usrp_sink_0.set_gain(tx_gain, 0) self.uhd_usrp_sink_0.set_antenna("TX/RX", 0) + self.ts_filter = grgsm.burst_timeslot_filter(0) self.low_pass_filter_0_0 = filter.fir_filter_ccf(1, firdes.low_pass( 1, samp_rate, 125e3, 5e3, firdes.WIN_HAMMING, 6.76)) self.gsm_txtime_setter_0 = grgsm.txtime_setter(None if (None is not None) else 0xffffffff, 0, 0, 0, 0, timing_advance, delay_correction+uplink_shift) @@ -86,23 +87,31 @@ class radio_if_grc(gr.top_block): pulse_duration=4, sps=osr, ) + self.gsm_gen_test_ab_0 = grgsm.gen_test_ab() self.gsm_controlled_rotator_cc_0_0 = grgsm.controlled_rotator_cc(-ppm/1.0e6*2*math.pi*tx_freq/samp_rate) self.gsm_controlled_rotator_cc_0 = grgsm.controlled_rotator_cc(ppm/1.0e6*2*math.pi*rx_freq/samp_rate) + self.gsm_burst_type_filter_0_0 = grgsm.burst_type_filter(([1,3])) self.gsm_burst_type_filter_0 = grgsm.burst_type_filter(([3])) self.gsm_burst_to_fn_time_0 = grgsm.burst_to_fn_time() + self.gsm_burst_timeslot_filter_0 = grgsm.burst_timeslot_filter(0) self.digital_burst_shaper_xx_0 = digital.burst_shaper_cc((firdes.window(firdes.WIN_HANN, 16, 0)), 0, 20, False, "packet_len") self.blocks_pdu_to_tagged_stream_0_0 = blocks.pdu_to_tagged_stream(blocks.byte_t, "packet_len") ################################################## # Connections ################################################## + self.msg_connect((self.gsm_burst_timeslot_filter_0, 'out'), (self.gsm_gen_test_ab_0, 'bursts_in')) self.msg_connect((self.gsm_burst_to_fn_time_0, 'fn_time_out'), (self.gsm_txtime_setter_0, 'fn_time')) self.msg_connect((self.gsm_burst_type_filter_0, 'bursts_out'), (self.gsm_burst_to_fn_time_0, 'bursts_in')) + self.msg_connect((self.gsm_burst_type_filter_0_0, 'bursts_out'), (self.gsm_burst_timeslot_filter_0, 'in')) + self.msg_connect((self.gsm_gen_test_ab_0, 'bursts_out'), (self.gsm_txtime_setter_0, 'bursts_in')) self.msg_connect((self.gsm_preprocess_tx_burst_0, 'bursts_out'), (self.blocks_pdu_to_tagged_stream_0_0, 'pdus')) self.msg_connect((self.gsm_receiver_0, 'C0'), (self.gsm_burst_type_filter_0, 'bursts_in')) - self.msg_connect((self.gsm_receiver_0, 'C0'), (self.gsm_trx_burst_if_0, 'bursts')) + self.msg_connect((self.gsm_receiver_0, 'C0'), (self.gsm_burst_type_filter_0_0, 'bursts_in')) + self.msg_connect((self.gsm_receiver_0, 'C0'), (self.ts_filter, 'in')) self.msg_connect((self.gsm_trx_burst_if_0, 'bursts'), (self.gsm_txtime_setter_0, 'bursts_in')) self.msg_connect((self.gsm_txtime_setter_0, 'bursts_out'), (self.gsm_preprocess_tx_burst_0, 'bursts_in')) + self.msg_connect((self.ts_filter, 'out'), (self.gsm_trx_burst_if_0, 'bursts')) self.connect((self.blocks_pdu_to_tagged_stream_0_0, 0), (self.gsm_gmsk_mod_0, 0)) self.connect((self.digital_burst_shaper_xx_0, 0), (self.gsm_msg_to_tag_0_0, 0)) self.connect((self.gsm_controlled_rotator_cc_0, 0), (self.low_pass_filter_0_0, 0)) @@ -113,27 +122,32 @@ class radio_if_grc(gr.top_block): self.connect((self.low_pass_filter_0_0, 0), (self.gsm_receiver_0, 0)) self.connect((self.uhd_usrp_source_0, 0), (self.gsm_msg_to_tag_0, 0)) - def get_delay_correction(self): - return self.delay_correction + def get_samp_rate(self): + return self.samp_rate - def set_delay_correction(self, delay_correction): - self.delay_correction = delay_correction - self.gsm_txtime_setter_0.set_delay_correction(self.delay_correction+self.uplink_shift) + def set_samp_rate(self, samp_rate): + self.samp_rate = samp_rate + self.low_pass_filter_0_0.set_taps(firdes.low_pass(1, self.samp_rate, 125e3, 5e3, firdes.WIN_HAMMING, 6.76)) + self.gsm_controlled_rotator_cc_0.set_phase_inc(self.ppm/1.0e6*2*math.pi*self.rx_freq/self.samp_rate) + self.gsm_controlled_rotator_cc_0_0.set_phase_inc(-self.ppm/1.0e6*2*math.pi*self.tx_freq/self.samp_rate) + self.uhd_usrp_sink_0.set_samp_rate(self.samp_rate) + self.uhd_usrp_source_0.set_samp_rate(self.samp_rate) - def get_osr(self): - return self.osr + def get_tx_gain(self): + return self.tx_gain - def set_osr(self, osr): - self.osr = osr - self.gsm_gmsk_mod_0.set_sps(self.osr) + def set_tx_gain(self, tx_gain): + self.tx_gain = tx_gain + self.uhd_usrp_sink_0.set_gain(self.tx_gain, 0) + - def get_ppm(self): - return self.ppm + def get_tx_freq(self): + return self.tx_freq - def set_ppm(self, ppm): - self.ppm = ppm - self.gsm_controlled_rotator_cc_0.set_phase_inc(self.ppm/1.0e6*2*math.pi*self.rx_freq/self.samp_rate) + def set_tx_freq(self, tx_freq): + self.tx_freq = tx_freq self.gsm_controlled_rotator_cc_0_0.set_phase_inc(-self.ppm/1.0e6*2*math.pi*self.tx_freq/self.samp_rate) + self.uhd_usrp_sink_0.set_center_freq(self.tx_freq, 0) def get_rx_freq(self): return self.rx_freq @@ -151,23 +165,20 @@ class radio_if_grc(gr.top_block): self.uhd_usrp_source_0.set_gain(self.rx_gain, 0) - def get_samp_rate(self): - return self.samp_rate + def get_osr(self): + return self.osr - def set_samp_rate(self, samp_rate): - self.samp_rate = samp_rate - self.gsm_controlled_rotator_cc_0.set_phase_inc(self.ppm/1.0e6*2*math.pi*self.rx_freq/self.samp_rate) - self.gsm_controlled_rotator_cc_0_0.set_phase_inc(-self.ppm/1.0e6*2*math.pi*self.tx_freq/self.samp_rate) - self.low_pass_filter_0_0.set_taps(firdes.low_pass(1, self.samp_rate, 125e3, 5e3, firdes.WIN_HAMMING, 6.76)) - self.uhd_usrp_sink_0.set_samp_rate(self.samp_rate) - self.uhd_usrp_source_0.set_samp_rate(self.samp_rate) + def set_osr(self, osr): + self.osr = osr + self.gsm_gmsk_mod_0.set_sps(self.osr) - def get_timing_advance(self): - return self.timing_advance + def get_ppm(self): + return self.ppm - def set_timing_advance(self, timing_advance): - self.timing_advance = timing_advance - self.gsm_txtime_setter_0.set_timing_advance(self.timing_advance) + def set_ppm(self, ppm): + self.ppm = ppm + self.gsm_controlled_rotator_cc_0.set_phase_inc(self.ppm/1.0e6*2*math.pi*self.rx_freq/self.samp_rate) + self.gsm_controlled_rotator_cc_0_0.set_phase_inc(-self.ppm/1.0e6*2*math.pi*self.tx_freq/self.samp_rate) def get_trx_base_port(self): return self.trx_base_port @@ -181,21 +192,12 @@ class radio_if_grc(gr.top_block): def set_trx_remote_addr(self, trx_remote_addr): self.trx_remote_addr = trx_remote_addr - def get_tx_freq(self): - return self.tx_freq - - def set_tx_freq(self, tx_freq): - self.tx_freq = tx_freq - self.gsm_controlled_rotator_cc_0_0.set_phase_inc(-self.ppm/1.0e6*2*math.pi*self.tx_freq/self.samp_rate) - self.uhd_usrp_sink_0.set_center_freq(self.tx_freq, 0) - - def get_tx_gain(self): - return self.tx_gain + def get_delay_correction(self): + return self.delay_correction - def set_tx_gain(self, tx_gain): - self.tx_gain = tx_gain - self.uhd_usrp_sink_0.set_gain(self.tx_gain, 0) - + def set_delay_correction(self, delay_correction): + self.delay_correction = delay_correction + self.gsm_txtime_setter_0.set_delay_correction(self.delay_correction+self.uplink_shift) def get_uplink_shift(self): return self.uplink_shift @@ -204,18 +206,25 @@ class radio_if_grc(gr.top_block): self.uplink_shift = uplink_shift self.gsm_txtime_setter_0.set_delay_correction(self.delay_correction+self.uplink_shift) + def get_timing_advance(self): + return self.timing_advance + + def set_timing_advance(self, timing_advance): + self.timing_advance = timing_advance + self.gsm_txtime_setter_0.set_timing_advance(self.timing_advance) + def argument_parser(): parser = OptionParser(option_class=eng_option, usage="%prog: [options]") parser.add_option( - "", "--delay-correction", dest="delay_correction", type="eng_float", default=eng_notation.num_to_str(285.616e-6), - help="Set delay_correction [default=%default]") + "", "--samp-rate", dest="samp_rate", type="eng_float", default=eng_notation.num_to_str(13e6/12.0), + help="Set samp_rate [default=%default]") parser.add_option( - "", "--osr", dest="osr", type="intx", default=4, - help="Set OSR [default=%default]") + "-r", "--tx-gain", dest="tx_gain", type="eng_float", default=eng_notation.num_to_str(30), + help="Set tx_gain [default=%default]") parser.add_option( - "", "--ppm", dest="ppm", type="eng_float", default=eng_notation.num_to_str(-1), - help="Set Clock offset correction [default=%default]") + "-u", "--tx-freq", dest="tx_freq", type="eng_float", default=eng_notation.num_to_str(938900000), + help="Set tx_freq [default=%default]") parser.add_option( "-d", "--rx-freq", dest="rx_freq", type="eng_float", default=eng_notation.num_to_str(938600000), help="Set rx_freq [default=%default]") @@ -223,11 +232,11 @@ def argument_parser(): "-g", "--rx-gain", dest="rx_gain", type="eng_float", default=eng_notation.num_to_str(40), help="Set rx_gain [default=%default]") parser.add_option( - "", "--samp-rate", dest="samp_rate", type="eng_float", default=eng_notation.num_to_str(13e6/12.0), - help="Set samp_rate [default=%default]") + "", "--osr", dest="osr", type="intx", default=4, + help="Set OSR [default=%default]") parser.add_option( - "", "--timing-advance", dest="timing_advance", type="eng_float", default=eng_notation.num_to_str(0), - help="Set timing_advance [default=%default]") + "", "--ppm", dest="ppm", type="eng_float", default=eng_notation.num_to_str(-1), + help="Set Clock offset correction [default=%default]") parser.add_option( "", "--trx-base-port", dest="trx_base_port", type="string", default="5700", help="Set 5700 [default=%default]") @@ -235,14 +244,14 @@ def argument_parser(): "", "--trx-remote-addr", dest="trx_remote_addr", type="string", default="127.0.0.1", help="Set 127.0.0.1 [default=%default]") parser.add_option( - "-u", "--tx-freq", dest="tx_freq", type="eng_float", default=eng_notation.num_to_str(938900000), - help="Set tx_freq [default=%default]") - parser.add_option( - "-r", "--tx-gain", dest="tx_gain", type="eng_float", default=eng_notation.num_to_str(30), - help="Set tx_gain [default=%default]") + "", "--delay-correction", dest="delay_correction", type="eng_float", default=eng_notation.num_to_str(285.616e-6), + help="Set delay_correction [default=%default]") parser.add_option( "", "--uplink-shift", dest="uplink_shift", type="eng_float", default=eng_notation.num_to_str(-(6.0/1625000*(156.25)*3)), help="Set uplink_shift [default=%default]") + parser.add_option( + "", "--timing-advance", dest="timing_advance", type="eng_float", default=eng_notation.num_to_str(0), + help="Set timing_advance [default=%default]") return parser @@ -250,7 +259,7 @@ def main(top_block_cls=radio_if_grc, options=None): if options is None: options, _ = argument_parser().parse_args() - tb = top_block_cls(delay_correction=options.delay_correction, osr=options.osr, ppm=options.ppm, rx_freq=options.rx_freq, rx_gain=options.rx_gain, samp_rate=options.samp_rate, timing_advance=options.timing_advance, trx_base_port=options.trx_base_port, trx_remote_addr=options.trx_remote_addr, tx_freq=options.tx_freq, tx_gain=options.tx_gain, uplink_shift=options.uplink_shift) + tb = top_block_cls(samp_rate=options.samp_rate, tx_gain=options.tx_gain, tx_freq=options.tx_freq, rx_freq=options.rx_freq, rx_gain=options.rx_gain, osr=options.osr, ppm=options.ppm, trx_base_port=options.trx_base_port, trx_remote_addr=options.trx_remote_addr, delay_correction=options.delay_correction, uplink_shift=options.uplink_shift, timing_advance=options.timing_advance) tb.start() tb.wait() -- cgit v1.2.3 From 0be5e5bcc83c2aa2613d86e0a52c6afbec7a50d7 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 30 Nov 2017 06:15:58 +0700 Subject: preprocess_tx_burst: fix the output message During the code refactoring (4bd990b), the first part of the output message was accidently dropped. Let's fix this. --- lib/transmitter/preprocess_tx_burst_impl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/transmitter/preprocess_tx_burst_impl.cc b/lib/transmitter/preprocess_tx_burst_impl.cc index 5a89390..5fbac98 100644 --- a/lib/transmitter/preprocess_tx_burst_impl.cc +++ b/lib/transmitter/preprocess_tx_burst_impl.cc @@ -86,7 +86,7 @@ namespace gr { // Prepare an output message pmt::pmt_t blob_out = pmt::make_blob(burst_bits, burst_len); - pmt::pmt_t msg_out = pmt::cons(pmt::PMT_NIL, blob_out); + pmt::pmt_t msg_out = pmt::cons(pmt::car(msg_in), blob_out); /* Send a message to the output */ message_port_pub(pmt::mp("bursts_out"), msg_out); -- cgit v1.2.3 From be1da4a2335e1b1e6b020fc48f9f4a17d72fb0a5 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Thu, 30 Nov 2017 13:44:54 +0100 Subject: trc: Changed sample rate to 4 times GSM symbol rate --- apps/grgsm_trx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/grgsm_trx b/apps/grgsm_trx index 507ed87..5174b5c 100755 --- a/apps/grgsm_trx +++ b/apps/grgsm_trx @@ -42,7 +42,7 @@ class Application: base_port = 5700 # PHY specific - phy_sample_rate = 2000000 + phy_sample_rate = 4*1625000/6 phy_tx_antenna = "TX/RX" phy_rx_antenna = "RX2" phy_rx_gain = 30 -- cgit v1.2.3 From 0101ae282964d2f48cf4db91877878dea2b18312 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Thu, 30 Nov 2017 13:45:37 +0100 Subject: Removed AB test from radio_if_grc --- python/trx/radio_if_grc.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/python/trx/radio_if_grc.py b/python/trx/radio_if_grc.py index 8b53fe7..3cfa931 100755 --- a/python/trx/radio_if_grc.py +++ b/python/trx/radio_if_grc.py @@ -5,7 +5,7 @@ # Title: Trx radio interface # Author: (C) Piotr Krysik 2017 # Description: Alpha version of trx radio interface -# Generated: Thu Nov 30 13:02:31 2017 +# Generated: Thu Nov 30 13:41:21 2017 ################################################## from gnuradio import blocks @@ -87,27 +87,20 @@ class radio_if_grc(gr.top_block): pulse_duration=4, sps=osr, ) - self.gsm_gen_test_ab_0 = grgsm.gen_test_ab() self.gsm_controlled_rotator_cc_0_0 = grgsm.controlled_rotator_cc(-ppm/1.0e6*2*math.pi*tx_freq/samp_rate) self.gsm_controlled_rotator_cc_0 = grgsm.controlled_rotator_cc(ppm/1.0e6*2*math.pi*rx_freq/samp_rate) - self.gsm_burst_type_filter_0_0 = grgsm.burst_type_filter(([1,3])) self.gsm_burst_type_filter_0 = grgsm.burst_type_filter(([3])) self.gsm_burst_to_fn_time_0 = grgsm.burst_to_fn_time() - self.gsm_burst_timeslot_filter_0 = grgsm.burst_timeslot_filter(0) self.digital_burst_shaper_xx_0 = digital.burst_shaper_cc((firdes.window(firdes.WIN_HANN, 16, 0)), 0, 20, False, "packet_len") self.blocks_pdu_to_tagged_stream_0_0 = blocks.pdu_to_tagged_stream(blocks.byte_t, "packet_len") ################################################## # Connections ################################################## - self.msg_connect((self.gsm_burst_timeslot_filter_0, 'out'), (self.gsm_gen_test_ab_0, 'bursts_in')) self.msg_connect((self.gsm_burst_to_fn_time_0, 'fn_time_out'), (self.gsm_txtime_setter_0, 'fn_time')) self.msg_connect((self.gsm_burst_type_filter_0, 'bursts_out'), (self.gsm_burst_to_fn_time_0, 'bursts_in')) - self.msg_connect((self.gsm_burst_type_filter_0_0, 'bursts_out'), (self.gsm_burst_timeslot_filter_0, 'in')) - self.msg_connect((self.gsm_gen_test_ab_0, 'bursts_out'), (self.gsm_txtime_setter_0, 'bursts_in')) self.msg_connect((self.gsm_preprocess_tx_burst_0, 'bursts_out'), (self.blocks_pdu_to_tagged_stream_0_0, 'pdus')) self.msg_connect((self.gsm_receiver_0, 'C0'), (self.gsm_burst_type_filter_0, 'bursts_in')) - self.msg_connect((self.gsm_receiver_0, 'C0'), (self.gsm_burst_type_filter_0_0, 'bursts_in')) self.msg_connect((self.gsm_receiver_0, 'C0'), (self.ts_filter, 'in')) self.msg_connect((self.gsm_trx_burst_if_0, 'bursts'), (self.gsm_txtime_setter_0, 'bursts_in')) self.msg_connect((self.gsm_txtime_setter_0, 'bursts_out'), (self.gsm_preprocess_tx_burst_0, 'bursts_in')) -- cgit v1.2.3 From 66c56e7803e8cf65193e472f00740ad7a7f229de Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Fri, 1 Dec 2017 11:58:53 +0100 Subject: trx: Changed default gain to 40 --- apps/grgsm_trx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/grgsm_trx b/apps/grgsm_trx index 5174b5c..228be5d 100755 --- a/apps/grgsm_trx +++ b/apps/grgsm_trx @@ -46,7 +46,7 @@ class Application: phy_tx_antenna = "TX/RX" phy_rx_antenna = "RX2" phy_rx_gain = 30 - phy_tx_gain = 10 + phy_tx_gain = 40 phy_args = "" phy_ppm = 0 -- cgit v1.2.3 From 3dd981c779040ca71e194852e1b36151484c9ea2 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Fri, 1 Dec 2017 11:59:32 +0100 Subject: trx: passing remote addr to bind --- python/trx/udp_link.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/trx/udp_link.py b/python/trx/udp_link.py index 584a6ac..675ef5c 100644 --- a/python/trx/udp_link.py +++ b/python/trx/udp_link.py @@ -28,7 +28,7 @@ import select class udp_link: def __init__(self, remote_addr, remote_port, bind_port): self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - self.sock.bind(('0.0.0.0', bind_port)) + self.sock.bind((remote_addr, bind_port)) self.sock.setblocking(0) # Save remote info -- cgit v1.2.3 From c36224502349c8a700580da57d7988d689930bb8 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Fri, 1 Dec 2017 12:02:55 +0100 Subject: Added carrier frequency offset correction to radio_if --- python/trx/CMakeLists.txt | 1 + python/trx/__init__.py | 1 + python/trx/change_sign_of_dict_elements.py | 30 ++++++ python/trx/radio_if_grc.py | 149 +++++++++++++++-------------- 4 files changed, 110 insertions(+), 71 deletions(-) create mode 100644 python/trx/change_sign_of_dict_elements.py diff --git a/python/trx/CMakeLists.txt b/python/trx/CMakeLists.txt index 4049e54..c6e3010 100644 --- a/python/trx/CMakeLists.txt +++ b/python/trx/CMakeLists.txt @@ -26,5 +26,6 @@ GR_PYTHON_INSTALL( fake_pm.py radio_if.py radio_if_grc.py + change_sign_of_dict_elements.py DESTINATION ${GR_PYTHON_DIR}/grgsm/trx ) diff --git a/python/trx/__init__.py b/python/trx/__init__.py index 5d193b5..13b5a52 100644 --- a/python/trx/__init__.py +++ b/python/trx/__init__.py @@ -26,3 +26,4 @@ from ctrl_if_bb import ctrl_if_bb from fake_pm import fake_pm from radio_if_grc import radio_if_grc from radio_if import radio_if +from change_sign_of_dict_elements import change_sign_of_dict_elements \ No newline at end of file diff --git a/python/trx/change_sign_of_dict_elements.py b/python/trx/change_sign_of_dict_elements.py new file mode 100644 index 0000000..fd7c585 --- /dev/null +++ b/python/trx/change_sign_of_dict_elements.py @@ -0,0 +1,30 @@ +""" +Embedded Python Blocks: + +Each this file is saved, GRC will instantiate the first class it finds to get +ports and parameters of your block. The arguments to __init__ will be the +parameters. All of them are required to have default values! +""" + +from gnuradio import gr +from pmt import * + +class change_sign_of_dict_elements(gr.basic_block): + def __init__(self): # only default arguments here + gr.basic_block.__init__( + self, + name='Change sign of elts in dict', + in_sig=[], + out_sig=[] + ) + self.message_port_register_in(intern("dict_in")) + self.message_port_register_out(intern("dict_out")) + self.set_msg_handler(intern("dict_in"), self.change_sign) + + def change_sign(self, msg): + if is_dict(msg): + d = to_python(msg) + #print d + for key, value in d.items(): + d[key] *= -1 + self.message_port_pub(intern("dict_out"), to_pmt(d)) diff --git a/python/trx/radio_if_grc.py b/python/trx/radio_if_grc.py index 3cfa931..920b0c5 100755 --- a/python/trx/radio_if_grc.py +++ b/python/trx/radio_if_grc.py @@ -5,9 +5,10 @@ # Title: Trx radio interface # Author: (C) Piotr Krysik 2017 # Description: Alpha version of trx radio interface -# Generated: Thu Nov 30 13:41:21 2017 +# Generated: Fri Dec 1 10:49:25 2017 ################################################## +from change_sign_of_dict_elements import change_sign_of_dict_elements from gnuradio import blocks from gnuradio import digital from gnuradio import eng_notation @@ -25,24 +26,24 @@ import time class radio_if_grc(gr.top_block): - def __init__(self, samp_rate=13e6/12.0, tx_gain=30, tx_freq=938900000, rx_freq=938600000, rx_gain=40, osr=4, ppm=-1, trx_base_port="5700", trx_remote_addr="127.0.0.1", delay_correction=285.616e-6, uplink_shift=-(6.0/1625000*(156.25)*3), timing_advance=0): + def __init__(self, delay_correction=285.616e-6, osr=4, ppm=-0.799427, rx_freq=935e6+36*0.2e6, rx_gain=40, samp_rate=13e6/12.0, timing_advance=0, trx_base_port="5710", trx_remote_addr="127.0.0.1", tx_freq=935e6+36*0.2e6-45e6, tx_gain=40, uplink_shift=-(6.0/1625000*(156.25)*3)): gr.top_block.__init__(self, "Trx radio interface") ################################################## # Parameters ################################################## - self.samp_rate = samp_rate - self.tx_gain = tx_gain - self.tx_freq = tx_freq - self.rx_freq = rx_freq - self.rx_gain = rx_gain + self.delay_correction = delay_correction self.osr = osr self.ppm = ppm + self.rx_freq = rx_freq + self.rx_gain = rx_gain + self.samp_rate = samp_rate + self.timing_advance = timing_advance self.trx_base_port = trx_base_port self.trx_remote_addr = trx_remote_addr - self.delay_correction = delay_correction + self.tx_freq = tx_freq + self.tx_gain = tx_gain self.uplink_shift = uplink_shift - self.timing_advance = timing_advance ################################################## # Blocks @@ -89,18 +90,24 @@ class radio_if_grc(gr.top_block): ) self.gsm_controlled_rotator_cc_0_0 = grgsm.controlled_rotator_cc(-ppm/1.0e6*2*math.pi*tx_freq/samp_rate) self.gsm_controlled_rotator_cc_0 = grgsm.controlled_rotator_cc(ppm/1.0e6*2*math.pi*rx_freq/samp_rate) + self.gsm_clock_offset_control_0 = grgsm.clock_offset_control(rx_freq, samp_rate, osr) self.gsm_burst_type_filter_0 = grgsm.burst_type_filter(([3])) self.gsm_burst_to_fn_time_0 = grgsm.burst_to_fn_time() self.digital_burst_shaper_xx_0 = digital.burst_shaper_cc((firdes.window(firdes.WIN_HANN, 16, 0)), 0, 20, False, "packet_len") + self.change_sign_of_dict_elements = change_sign_of_dict_elements() self.blocks_pdu_to_tagged_stream_0_0 = blocks.pdu_to_tagged_stream(blocks.byte_t, "packet_len") ################################################## # Connections ################################################## + self.msg_connect((self.change_sign_of_dict_elements, 'dict_out'), (self.gsm_msg_to_tag_0_0, 'msg')) self.msg_connect((self.gsm_burst_to_fn_time_0, 'fn_time_out'), (self.gsm_txtime_setter_0, 'fn_time')) self.msg_connect((self.gsm_burst_type_filter_0, 'bursts_out'), (self.gsm_burst_to_fn_time_0, 'bursts_in')) + self.msg_connect((self.gsm_clock_offset_control_0, 'ctrl'), (self.change_sign_of_dict_elements, 'dict_in')) + self.msg_connect((self.gsm_clock_offset_control_0, 'ctrl'), (self.gsm_msg_to_tag_0, 'msg')) self.msg_connect((self.gsm_preprocess_tx_burst_0, 'bursts_out'), (self.blocks_pdu_to_tagged_stream_0_0, 'pdus')) self.msg_connect((self.gsm_receiver_0, 'C0'), (self.gsm_burst_type_filter_0, 'bursts_in')) + self.msg_connect((self.gsm_receiver_0, 'measurements'), (self.gsm_clock_offset_control_0, 'measurements')) self.msg_connect((self.gsm_receiver_0, 'C0'), (self.ts_filter, 'in')) self.msg_connect((self.gsm_trx_burst_if_0, 'bursts'), (self.gsm_txtime_setter_0, 'bursts_in')) self.msg_connect((self.gsm_txtime_setter_0, 'bursts_out'), (self.gsm_preprocess_tx_burst_0, 'bursts_in')) @@ -115,32 +122,27 @@ class radio_if_grc(gr.top_block): self.connect((self.low_pass_filter_0_0, 0), (self.gsm_receiver_0, 0)) self.connect((self.uhd_usrp_source_0, 0), (self.gsm_msg_to_tag_0, 0)) - def get_samp_rate(self): - return self.samp_rate + def get_delay_correction(self): + return self.delay_correction - def set_samp_rate(self, samp_rate): - self.samp_rate = samp_rate - self.low_pass_filter_0_0.set_taps(firdes.low_pass(1, self.samp_rate, 125e3, 5e3, firdes.WIN_HAMMING, 6.76)) - self.gsm_controlled_rotator_cc_0.set_phase_inc(self.ppm/1.0e6*2*math.pi*self.rx_freq/self.samp_rate) - self.gsm_controlled_rotator_cc_0_0.set_phase_inc(-self.ppm/1.0e6*2*math.pi*self.tx_freq/self.samp_rate) - self.uhd_usrp_sink_0.set_samp_rate(self.samp_rate) - self.uhd_usrp_source_0.set_samp_rate(self.samp_rate) + def set_delay_correction(self, delay_correction): + self.delay_correction = delay_correction + self.gsm_txtime_setter_0.set_delay_correction(self.delay_correction+self.uplink_shift) - def get_tx_gain(self): - return self.tx_gain + def get_osr(self): + return self.osr - def set_tx_gain(self, tx_gain): - self.tx_gain = tx_gain - self.uhd_usrp_sink_0.set_gain(self.tx_gain, 0) - + def set_osr(self, osr): + self.osr = osr + self.gsm_gmsk_mod_0.set_sps(self.osr) - def get_tx_freq(self): - return self.tx_freq + def get_ppm(self): + return self.ppm - def set_tx_freq(self, tx_freq): - self.tx_freq = tx_freq + def set_ppm(self, ppm): + self.ppm = ppm + self.gsm_controlled_rotator_cc_0.set_phase_inc(self.ppm/1.0e6*2*math.pi*self.rx_freq/self.samp_rate) self.gsm_controlled_rotator_cc_0_0.set_phase_inc(-self.ppm/1.0e6*2*math.pi*self.tx_freq/self.samp_rate) - self.uhd_usrp_sink_0.set_center_freq(self.tx_freq, 0) def get_rx_freq(self): return self.rx_freq @@ -158,20 +160,23 @@ class radio_if_grc(gr.top_block): self.uhd_usrp_source_0.set_gain(self.rx_gain, 0) - def get_osr(self): - return self.osr - - def set_osr(self, osr): - self.osr = osr - self.gsm_gmsk_mod_0.set_sps(self.osr) - - def get_ppm(self): - return self.ppm + def get_samp_rate(self): + return self.samp_rate - def set_ppm(self, ppm): - self.ppm = ppm + def set_samp_rate(self, samp_rate): + self.samp_rate = samp_rate self.gsm_controlled_rotator_cc_0.set_phase_inc(self.ppm/1.0e6*2*math.pi*self.rx_freq/self.samp_rate) self.gsm_controlled_rotator_cc_0_0.set_phase_inc(-self.ppm/1.0e6*2*math.pi*self.tx_freq/self.samp_rate) + self.low_pass_filter_0_0.set_taps(firdes.low_pass(1, self.samp_rate, 125e3, 5e3, firdes.WIN_HAMMING, 6.76)) + self.uhd_usrp_sink_0.set_samp_rate(self.samp_rate) + self.uhd_usrp_source_0.set_samp_rate(self.samp_rate) + + def get_timing_advance(self): + return self.timing_advance + + def set_timing_advance(self, timing_advance): + self.timing_advance = timing_advance + self.gsm_txtime_setter_0.set_timing_advance(self.timing_advance) def get_trx_base_port(self): return self.trx_base_port @@ -185,12 +190,21 @@ class radio_if_grc(gr.top_block): def set_trx_remote_addr(self, trx_remote_addr): self.trx_remote_addr = trx_remote_addr - def get_delay_correction(self): - return self.delay_correction + def get_tx_freq(self): + return self.tx_freq - def set_delay_correction(self, delay_correction): - self.delay_correction = delay_correction - self.gsm_txtime_setter_0.set_delay_correction(self.delay_correction+self.uplink_shift) + def set_tx_freq(self, tx_freq): + self.tx_freq = tx_freq + self.gsm_controlled_rotator_cc_0_0.set_phase_inc(-self.ppm/1.0e6*2*math.pi*self.tx_freq/self.samp_rate) + self.uhd_usrp_sink_0.set_center_freq(self.tx_freq, 0) + + def get_tx_gain(self): + return self.tx_gain + + def set_tx_gain(self, tx_gain): + self.tx_gain = tx_gain + self.uhd_usrp_sink_0.set_gain(self.tx_gain, 0) + def get_uplink_shift(self): return self.uplink_shift @@ -199,52 +213,45 @@ class radio_if_grc(gr.top_block): self.uplink_shift = uplink_shift self.gsm_txtime_setter_0.set_delay_correction(self.delay_correction+self.uplink_shift) - def get_timing_advance(self): - return self.timing_advance - - def set_timing_advance(self, timing_advance): - self.timing_advance = timing_advance - self.gsm_txtime_setter_0.set_timing_advance(self.timing_advance) - def argument_parser(): parser = OptionParser(option_class=eng_option, usage="%prog: [options]") parser.add_option( - "", "--samp-rate", dest="samp_rate", type="eng_float", default=eng_notation.num_to_str(13e6/12.0), - help="Set samp_rate [default=%default]") + "", "--delay-correction", dest="delay_correction", type="eng_float", default=eng_notation.num_to_str(285.616e-6), + help="Set delay_correction [default=%default]") parser.add_option( - "-r", "--tx-gain", dest="tx_gain", type="eng_float", default=eng_notation.num_to_str(30), - help="Set tx_gain [default=%default]") + "", "--osr", dest="osr", type="intx", default=4, + help="Set OSR [default=%default]") parser.add_option( - "-u", "--tx-freq", dest="tx_freq", type="eng_float", default=eng_notation.num_to_str(938900000), - help="Set tx_freq [default=%default]") + "", "--ppm", dest="ppm", type="eng_float", default=eng_notation.num_to_str(-0.799427), + help="Set Clock offset correction [default=%default]") parser.add_option( - "-d", "--rx-freq", dest="rx_freq", type="eng_float", default=eng_notation.num_to_str(938600000), + "-d", "--rx-freq", dest="rx_freq", type="eng_float", default=eng_notation.num_to_str(935e6+36*0.2e6), help="Set rx_freq [default=%default]") parser.add_option( "-g", "--rx-gain", dest="rx_gain", type="eng_float", default=eng_notation.num_to_str(40), help="Set rx_gain [default=%default]") parser.add_option( - "", "--osr", dest="osr", type="intx", default=4, - help="Set OSR [default=%default]") + "", "--samp-rate", dest="samp_rate", type="eng_float", default=eng_notation.num_to_str(13e6/12.0), + help="Set samp_rate [default=%default]") parser.add_option( - "", "--ppm", dest="ppm", type="eng_float", default=eng_notation.num_to_str(-1), - help="Set Clock offset correction [default=%default]") + "", "--timing-advance", dest="timing_advance", type="eng_float", default=eng_notation.num_to_str(0), + help="Set timing_advance [default=%default]") parser.add_option( - "", "--trx-base-port", dest="trx_base_port", type="string", default="5700", - help="Set 5700 [default=%default]") + "", "--trx-base-port", dest="trx_base_port", type="string", default="5710", + help="Set 5710 [default=%default]") parser.add_option( "", "--trx-remote-addr", dest="trx_remote_addr", type="string", default="127.0.0.1", help="Set 127.0.0.1 [default=%default]") parser.add_option( - "", "--delay-correction", dest="delay_correction", type="eng_float", default=eng_notation.num_to_str(285.616e-6), - help="Set delay_correction [default=%default]") + "-u", "--tx-freq", dest="tx_freq", type="eng_float", default=eng_notation.num_to_str(935e6+36*0.2e6-45e6), + help="Set tx_freq [default=%default]") + parser.add_option( + "-r", "--tx-gain", dest="tx_gain", type="eng_float", default=eng_notation.num_to_str(40), + help="Set tx_gain [default=%default]") parser.add_option( "", "--uplink-shift", dest="uplink_shift", type="eng_float", default=eng_notation.num_to_str(-(6.0/1625000*(156.25)*3)), help="Set uplink_shift [default=%default]") - parser.add_option( - "", "--timing-advance", dest="timing_advance", type="eng_float", default=eng_notation.num_to_str(0), - help="Set timing_advance [default=%default]") return parser @@ -252,7 +259,7 @@ def main(top_block_cls=radio_if_grc, options=None): if options is None: options, _ = argument_parser().parse_args() - tb = top_block_cls(samp_rate=options.samp_rate, tx_gain=options.tx_gain, tx_freq=options.tx_freq, rx_freq=options.rx_freq, rx_gain=options.rx_gain, osr=options.osr, ppm=options.ppm, trx_base_port=options.trx_base_port, trx_remote_addr=options.trx_remote_addr, delay_correction=options.delay_correction, uplink_shift=options.uplink_shift, timing_advance=options.timing_advance) + tb = top_block_cls(delay_correction=options.delay_correction, osr=options.osr, ppm=options.ppm, rx_freq=options.rx_freq, rx_gain=options.rx_gain, samp_rate=options.samp_rate, timing_advance=options.timing_advance, trx_base_port=options.trx_base_port, trx_remote_addr=options.trx_remote_addr, tx_freq=options.tx_freq, tx_gain=options.tx_gain, uplink_shift=options.uplink_shift) tb.start() tb.wait() -- cgit v1.2.3 From fe4db93e6d03e92a958664bfffcd0e2923f20e34 Mon Sep 17 00:00:00 2001 From: Piotr Krysik Date: Fri, 1 Dec 2017 12:04:39 +0100 Subject: Updated examples pointer --- examples | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples b/examples index de98b24..32727fc 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit de98b247d4d60ece9f07275b471fe3e24edad9b4 +Subproject commit 32727fc905c78b151cbb1794db05383220d7e61b -- cgit v1.2.3