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/apps/CMakeLists.txt b/apps/CMakeLists.txt index 3e36430..d8bf435 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -77,6 +77,7 @@ GR_PYTHON_INSTALL( ${CMAKE_CURRENT_BINARY_DIR}/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..228be5d --- /dev/null +++ b/apps/grgsm_trx @@ -0,0 +1,165 @@ +#!/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 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" \ + "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 = 4*1625000/6 + phy_tx_antenna = "TX/RX" + phy_rx_antenna = "RX2" + phy_rx_gain = 30 + phy_tx_gain = 40 + 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 = radio_if(self.phy_args, self.phy_sample_rate, + 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 + # BTS: -75 .. -50 + self.pm = fake_pm(-120, -105, -75, -50) + + # Init TRX CTRL interface + self.server = ctrl_if_bb(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" \ + " -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 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:], + "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="]) + 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 ("-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) + + 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/examples b/examples index e4e387d..32727fc 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit e4e387dddc3d9b860ae0938902fd59c1a569138c +Subproject commit 32727fc905c78b151cbb1794db05383220d7e61b diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 2b94539..c3646a2 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(transmitter) install(FILES gsm_block_tree.xml DESTINATION share/gnuradio/grc/blocks ) 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..d7d86f4 --- /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 + + + + bursts_in + message + 1 + + + + bursts_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 c418fab..29a1a43 100644 --- a/grc/gsm_block_tree.xml +++ b/grc/gsm_block_tree.xml @@ -21,6 +21,14 @@ gsm_clock_offset_control gsm_input + + Transmitter + gsm_txtime_bursts_tagger + gsm_txtime_setter + gsm_gmsk_mod + gsm_preprocess_tx_burst + gsm_gen_test_ab + Logical channels demapping gsm_universal_ctrl_chans_demapper @@ -45,6 +53,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 @@ -66,6 +75,8 @@ gsm_clock_offset_corrector_tagged 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 da41d6c..78f66c9 100644 --- a/grc/misc_utils/CMakeLists.txt +++ b/grc/misc_utils/CMakeLists.txt @@ -32,6 +32,9 @@ 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 + 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..0471605 --- /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 + + + + fn_time_out + message + 1 + + 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..99427b3 --- /dev/null +++ b/grc/misc_utils/gsm_trx_burst_if.xml @@ -0,0 +1,58 @@ + + + TRX Burst Interface + gsm_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 burst interface for external applications. + + 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. + + Received burst format: + 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" + + 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) + 148 bytes output symbol values, 0 & 1 + + diff --git a/grc/transmitter/CMakeLists.txt b/grc/transmitter/CMakeLists.txt new file mode 100644 index 0000000..4df2abb --- /dev/null +++ b/grc/transmitter/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. + +install(FILES + gsm_gmsk_mod.xml + 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/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/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/gsm_txtime_bursts_tagger.xml b/grc/transmitter/gsm_txtime_bursts_tagger.xml new file mode 100644 index 0000000..4e42886 --- /dev/null +++ b/grc/transmitter/gsm_txtime_bursts_tagger.xml @@ -0,0 +1,69 @@ + + + txtime_bursts_tagger + gsm_txtime_bursts_tagger + import grgsm + 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 + init_fn + None + raw + part + + + + init_time + init_time + 0 + float + part + + + + time_hint + time_hint + 0 + float + part + + + + timing_advance + timing_advance + 0 + float + part + + + + delay_correction + delay_correction + 0 + float + part + + + + fn_time + message + 1 + + + + bursts + message + 1 + + + + bursts + message + 1 + + 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/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 + + diff --git a/include/grgsm/CMakeLists.txt b/include/grgsm/CMakeLists.txt index d9b032d..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 ) @@ -35,3 +36,4 @@ add_subdirectory(receiver) add_subdirectory(misc_utils) add_subdirectory(qa_utils) add_subdirectory(flow_control) +add_subdirectory(transmitter) 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/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/lib/receiver/gsm_constants.h b/include/grgsm/gsm_constants.h similarity index 99% rename from lib/receiver/gsm_constants.h rename to include/grgsm/gsm_constants.h index 9052290..2fbfd36 100644 --- a/lib/receiver/gsm_constants.h +++ b/include/grgsm/gsm_constants.h @@ -38,6 +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 88 #define PROCESSED_CHUNK BURST_SIZE+2*GUARD_PERIOD #define SCH_DATA_LEN 39 diff --git a/include/grgsm/misc_utils/CMakeLists.txt b/include/grgsm/misc_utils/CMakeLists.txt index 2f7f4c3..0ec706c 100644 --- a/include/grgsm/misc_utils/CMakeLists.txt +++ b/include/grgsm/misc_utils/CMakeLists.txt @@ -35,5 +35,8 @@ install(FILES message_printer.h tmsi_dumper.h msg_to_tag.h - controlled_fractional_resampler_cc.h DESTINATION include/grgsm/misc_utils + 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/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/fn_time.h b/include/grgsm/misc_utils/fn_time.h new file mode 100644 index 0000000..b26c21b --- /dev/null +++ b/include/grgsm/misc_utils/fn_time.h @@ -0,0 +1,55 @@ +/* -*- 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. + * + */ + + +#ifndef INCLUDED_GRGSM_FN_TIME_H +#define INCLUDED_GRGSM_FN_TIME_H + +#include +#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 + */ + 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 gsm +} // namespace gr + +#endif /* INCLUDED_GRGSM_FN_TIME_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/misc_utils/time_spec.h b/include/grgsm/misc_utils/time_spec.h new file mode 100644 index 0000000..6ae5963 --- /dev/null +++ b/include/grgsm/misc_utils/time_spec.h @@ -0,0 +1,141 @@ +// +// 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 +#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 GRGSM_API time_spec_t : boost::additive, boost::totally_ordered{ + public: + + /*! + * 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/include/grgsm/misc_utils/trx_burst_if.h b/include/grgsm/misc_utils/trx_burst_if.h new file mode 100644 index 0000000..0e7a35a --- /dev/null +++ b/include/grgsm/misc_utils/trx_burst_if.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_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); + }; + + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GRGSM_TRX_BURST_IF_H */ + 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/include/grgsm/transmitter/CMakeLists.txt b/include/grgsm/transmitter/CMakeLists.txt new file mode 100644 index 0000000..fab6f7c --- /dev/null +++ b/include/grgsm/transmitter/CMakeLists.txt @@ -0,0 +1,28 @@ +# 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 + 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/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/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 db440e4..923de48 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) ######################################################################## # Setup library diff --git a/lib/decoding/sch.c b/lib/decoding/sch.c index 9cf6ac4..fff82ea 100644 --- a/lib/decoding/sch.c +++ b/lib/decoding/sch.c @@ -21,7 +21,7 @@ */ #include -#include "gsm_constants.h" +#include #include #include 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..c8bbd7e --- /dev/null +++ b/lib/flow_control/burst_type_filter_impl.cc @@ -0,0 +1,103 @@ +/* -*- 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("bursts_in")); + message_port_register_out(pmt::mp("bursts_out")); + + set_msg_handler(pmt::mp("bursts_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("bursts_out"), msg); + return; + } + + gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(pmt::cdr(msg)); + 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("bursts_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/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/CMakeLists.txt b/lib/misc_utils/CMakeLists.txt index 720eee3..e0fc818 100644 --- a/lib/misc_utils/CMakeLists.txt +++ b/lib/misc_utils/CMakeLists.txt @@ -33,5 +33,9 @@ add_sources( message_printer_impl.cc msg_to_tag_impl.cc tmsi_dumper_impl.cc + time_spec.cc + fn_time.cc + udp_socket.cc + trx_burst_if_impl.cc ) 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/fn_time.cc b/lib/misc_utils/fn_time.cc new file mode 100644 index 0000000..2773f33 --- /dev/null +++ b/lib/misc_utils/fn_time.cc @@ -0,0 +1,94 @@ +/* -*- 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 { + /** + * 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) + { + 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 if(delta < -h2) { + 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_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_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()); + } + + } /* namespace gsm */ +} /* namespace gr */ + 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/misc_utils/time_spec.cc b/lib/misc_utils/time_spec.cc new file mode 100644 index 0000000..5293da2 --- /dev/null +++ b/lib/misc_utils/time_spec.cc @@ -0,0 +1,122 @@ +// +// 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 + +namespace gr { + namespace gsm { + + /*********************************************************************** + * 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/misc_utils/trx_burst_if_impl.cc b/lib/misc_utils/trx_burst_if_impl.cc new file mode 100644 index 0000000..8f458b0 --- /dev/null +++ b/lib/misc_utils/trx_burst_if_impl.cc @@ -0,0 +1,231 @@ +/* -*- 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 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, 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); + } + + /* + * Our virtual destructor. + */ + trx_burst_if_impl::~trx_burst_if_impl() + { + // Release all UDP sockets and free memory + delete d_data_sock; + } + + /* + * 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 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); + + // 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); + + // 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..35f939c --- /dev/null +++ b/lib/misc_utils/trx_burst_if_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_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; + + bool detect_rach(uint8_t *burst); + 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(); + + 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/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 diff --git a/lib/receiver/CMakeLists.txt b/lib/receiver/CMakeLists.txt index 343d2f8..123eba5 100644 --- a/lib/receiver/CMakeLists.txt +++ b/lib/receiver/CMakeLists.txt @@ -23,4 +23,5 @@ add_sources( receiver_config.cc receiver_impl.cc viterbi_detector.cc + time_sample_ref.cc ) 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/receiver_config.h b/lib/receiver/receiver_config.h index 6ad43a1..b3c0f49 100644 --- a/lib/receiver/receiver_config.h +++ b/lib/receiver/receiver_config.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include class multiframe_configuration { diff --git a/lib/receiver/receiver_impl.cc b/lib/receiver/receiver_impl.cc index c7626b5..ffaf9ee 100644 --- a/lib/receiver/receiver_impl.cc +++ b/lib/receiver/receiver_impl.cc @@ -73,10 +73,13 @@ 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), 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), @@ -174,8 +177,13 @@ 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; /* Main state machine */ + d_samples_consumed = 0; switch (d_state) { case fcch_search: fcch_search_handler(input, noutput_items); @@ -188,7 +196,20 @@ 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); + } + + return d_samples_consumed; } void @@ -248,7 +269,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; @@ -320,7 +343,7 @@ namespace gr case sch_burst: { - int d_ncc, d_bcc; + int ncc, bcc; int t1, t2, t3; int rc; @@ -332,12 +355,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); - /* 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 */ @@ -352,6 +371,10 @@ namespace gr 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, @@ -380,7 +403,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; } @@ -404,13 +427,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; @@ -462,7 +485,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; } @@ -483,7 +506,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; } } } @@ -674,7 +698,8 @@ namespace gr } d_counter += to_consume; - consume_each(to_consume); +// consume_each(to_consume); + d_samples_consumed += to_consume; return result; } @@ -725,7 +750,8 @@ namespace gr } d_counter += to_consume; - consume_each(to_consume); +// consume_each(to_consume); + d_samples_consumed += to_consume; return result; } @@ -979,7 +1005,7 @@ namespace gr void receiver_impl::send_burst(burst_counter burst_nr, const unsigned char * burst_binary, uint8_t burst_type, - size_t input_nr) + size_t input_nr, unsigned int burst_start) { /* Buffer for GSMTAP header and burst */ uint8_t buf[sizeof(gsmtap_hdr) + BURST_SIZE]; @@ -1018,12 +1044,26 @@ 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::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 */ memcpy(burst, burst_binary, BURST_SIZE); /* 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) @@ -1092,6 +1132,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 0b032db..b880837 100644 --- a/lib/receiver/receiver_impl.h +++ b/lib/receiver/receiver_impl.h @@ -25,16 +25,20 @@ #include #include -#include +#include #include #include +#include "time_sample_ref.h" namespace gr { namespace gsm { class receiver_impl : public receiver { private: - unsigned int d_c0_burst_start; + unsigned int d_samples_consumed; + bool d_rx_time_received; + time_sample_ref d_time_samp_ref; + int d_c0_burst_start; float d_c0_signal_dbm; /**@name Configuration of the receiver */ @@ -195,7 +199,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, size_t input_nr); + void send_burst(burst_counter burst_nr, const unsigned char * burst_binary, uint8_t burst_type, size_t input_nr, unsigned int burst_start=-1); /** * Configures burst types in different channels @@ -209,13 +213,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..793944d --- /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 + +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/viterbi_detector.cc b/lib/receiver/viterbi_detector.cc index 6a64a2c..3dce379 100644 --- a/lib/receiver/viterbi_detector.cc +++ b/lib/receiver/viterbi_detector.cc @@ -56,7 +56,8 @@ */ #include -#include +#include +#include #define PATHS_NUM (1 << (CHAN_IMP_RESP_LENGTH-1)) diff --git a/lib/transmitter/CMakeLists.txt b/lib/transmitter/CMakeLists.txt new file mode 100644 index 0000000..eb53162 --- /dev/null +++ b/lib/transmitter/CMakeLists.txt @@ -0,0 +1,24 @@ +# 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 + 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..bb9c9f6 --- /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/lib/transmitter/preprocess_tx_burst_impl.cc b/lib/transmitter/preprocess_tx_burst_impl.cc new file mode 100644 index 0000000..5fbac98 --- /dev/null +++ b/lib/transmitter/preprocess_tx_burst_impl.cc @@ -0,0 +1,96 @@ +/* -*- 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. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#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::mp("bursts_in")); + message_port_register_out(pmt::mp("bursts_out")); + + set_msg_handler(pmt::mp("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 msg_in) + { + 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::car(msg_in), blob_out); + + /* Send a message to the output */ + message_port_pub(pmt::mp("bursts_out"), msg_out); + } + + } /* 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/lib/transmitter/txtime_setter_impl.cc b/lib/transmitter/txtime_setter_impl.cc new file mode 100644 index 0000000..33bc994 --- /dev/null +++ b/lib/transmitter/txtime_setter_impl.cc @@ -0,0 +1,196 @@ +/* -*- 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. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "txtime_setter_impl.h" + +#define UNKNOWN_FN 0xffffffff +#define MAX_EARLY_TIME_DIFF 10.0 + +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_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_fn_ref(init_fn), + d_ts_ref(0) + { + // 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")); + + // 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)); + } + + /* + * Our virtual destructor. + */ + txtime_setter_impl::~txtime_setter_impl() + { + } + + void txtime_setter_impl::process_fn_time_reference(pmt::pmt_t msg) + { + 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 msg_in) + { + 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); + } + } + } + + 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..62f500a --- /dev/null +++ b/lib/transmitter/txtime_setter_impl.h @@ -0,0 +1,64 @@ +/* -*- 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; + + 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(); + + // Where all the action really happens + 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 564ec3b..6f49e71 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -31,6 +31,8 @@ endif() add_subdirectory(misc_utils) add_subdirectory(receiver) add_subdirectory(demapping) +add_subdirectory(transmitter) +add_subdirectory(trx) GR_PYTHON_INSTALL( FILES @@ -58,3 +60,4 @@ GR_ADD_TEST(qa_tch_f_decoder ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa #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/__init__.py b/python/__init__.py index c2c016b..826b45f 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -55,7 +55,10 @@ 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 burst_to_fn_time import * import arfcn diff --git a/python/misc_utils/CMakeLists.txt b/python/misc_utils/CMakeLists.txt index 1accda9..8c7c175 100644 --- a/python/misc_utils/CMakeLists.txt +++ b/python/misc_utils/CMakeLists.txt @@ -22,5 +22,7 @@ GR_PYTHON_INSTALL( arfcn.py clock_offset_corrector_tagged.py hier_block.py - fn_time.py DESTINATION ${GR_PYTHON_DIR}/grgsm + 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) diff --git a/python/misc_utils/fn_time.py b/python/misc_utils/fn_time.py index 71e93db..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,14 +38,21 @@ __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: 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 @@ -52,33 +60,33 @@ def fnmod_delta(fn1, fn2): #* 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 = 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_ref)*__ts_period - return fn_delta, time2_precise + return fn_delta, time_x_precise if __name__ == "__main__": fn1 = 10000 - 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_ref = 4 + 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_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) + 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 "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" + 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 + 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/python/qa_txtime_bursts_tagger.py b/python/qa_txtime_bursts_tagger.py new file mode 100755 index 0000000..bdbf1af --- /dev/null +++ b/python/qa_txtime_bursts_tagger.py @@ -0,0 +1,106 @@ +#!/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 +#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): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_t (self): + 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__': + gr_unittest.run(qa_txtime_bursts_tagger, "qa_txtime_bursts_tagger.xml") 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/python/transmitter/CMakeLists.txt b/python/transmitter/CMakeLists.txt new file mode 100644 index 0000000..c32d6e1 --- /dev/null +++ b/python/transmitter/CMakeLists.txt @@ -0,0 +1,24 @@ +# 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 + txtime_bursts_tagger.py + gsm_gmsk_mod.py DESTINATION ${GR_PYTHON_DIR}/grgsm +) 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) diff --git a/python/transmitter/txtime_bursts_tagger.py b/python/transmitter/txtime_bursts_tagger.py new file mode 100644 index 0000000..de42f65 --- /dev/null +++ b/python/transmitter/txtime_bursts_tagger.py @@ -0,0 +1,97 @@ +#!/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 +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, 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=[], + out_sig=[]) + self.set_fn_time_reference(init_fn, init_time) + 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")) + + 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 process_fn_time_reference(self, msg): + 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 time_hint is not None: + self.time_hint = time_hint + elif fn_time is not None: + 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] + 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_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)) + 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 + self.time_ref = init_time + self.set_time_hint(init_time) + + 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 + diff --git a/python/trx/CMakeLists.txt b/python/trx/CMakeLists.txt new file mode 100644 index 0000000..c6e3010 --- /dev/null +++ b/python/trx/CMakeLists.txt @@ -0,0 +1,31 @@ +# 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 + __init__.py + udp_link.py + ctrl_if.py + ctrl_if_bb.py + 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 new file mode 100644 index 0000000..13b5a52 --- /dev/null +++ b/python/trx/__init__.py @@ -0,0 +1,29 @@ +# +# 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_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/ctrl_if.py b/python/trx/ctrl_if.py new file mode 100644 index 0000000..7dee0f8 --- /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.trx import udp_link + +class ctrl_if(udp_link): + 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..26ae49a --- /dev/null +++ b/python/trx/ctrl_if_bb.py @@ -0,0 +1,155 @@ +#!/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. + +import grgsm +from ctrl_if import ctrl_if + +class ctrl_if_bb(ctrl_if): + def __init__(self, remote_addr, remote_port, bind_port, tb, pm): + print("[i] Init CTRL interface") + ctrl_if.__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") + ctrl_if.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 + + 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 + + # 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_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 + + # 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_rx_freq(freq) + + return 0 + + elif self.verify_cmd(request, "TXTUNE", 1): + print("[i] Recv TXTUNE cmd") + + # TODO: check freq range + freq = int(request[1]) * 1000 + self.tb.set_tx_freq(freq) + + 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 + config = int(request[2]) + print("[i] Configure timeslot filter to: %s" + % ("drop all" if config == 0 else "TS %d" % tn)) + + if config == 0: + # Value 0 means 'drop all' + self.tb.ts_filter.set_policy( + grgsm.FILTER_POLICY_DROP_ALL) + else: + self.tb.ts_filter.set_policy( + grgsm.FILTER_POLICY_DEFAULT) + self.tb.ts_filter.set_tn(tn) + + 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..72cf771 --- /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 fake_pm: + # 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..9e97277 --- /dev/null +++ b/python/trx/radio_if.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- + +# GR-GSM based transceiver +# 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 +# +# 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.trx import radio_if_grc + +class radio_if(radio_if_grc): + # Application state flags + trx_started = False + + 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, + 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") + + 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() + diff --git a/python/trx/radio_if_grc.py b/python/trx/radio_if_grc.py new file mode 100755 index 0000000..920b0c5 --- /dev/null +++ b/python/trx/radio_if_grc.py @@ -0,0 +1,268 @@ +#!/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: 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 +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=-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.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.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) + 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_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')) + 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)) + 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(-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(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( + "", "--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="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( + "-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]") + 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() diff --git a/python/trx/udp_link.py b/python/trx/udp_link.py new file mode 100644 index 0000000..675ef5c --- /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 udp_link: + def __init__(self, remote_addr, remote_port, bind_port): + self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self.sock.bind((remote_addr, 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 b/swig/grgsm_swig.i index 60779a6..3665108 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 @@ -44,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" @@ -65,6 +69,12 @@ #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/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/transmitter/gen_test_ab.h" +#include "grgsm/misc_utils/trx_burst_if.h" %} %include "constants.i" @@ -100,10 +110,12 @@ 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" -GR_SWIG_BLOCK_MAGIC2(grgsm, uplink_downlink_splitter); +GR_SWIG_BLOCK_MAGIC2(gsm, uplink_downlink_splitter); %include "grgsm/misc_utils/bursts_printer.h" @@ -145,3 +157,38 @@ 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); + +//#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" + +%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); + +%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);