From 73857235f0651293eb9396c9ef81058b6935c0db Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 30 Nov 2017 06:15:58 +0700 Subject: [PATCH 01/11] preprocess_tx_burst: fix the output message During the code refactoring (4bd990b), the first part of the output message was accidently dropped. Let's fix this. --- lib/transmitter/preprocess_tx_burst_impl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/transmitter/preprocess_tx_burst_impl.cc b/lib/transmitter/preprocess_tx_burst_impl.cc index 5a89390..5fbac98 100644 --- a/lib/transmitter/preprocess_tx_burst_impl.cc +++ b/lib/transmitter/preprocess_tx_burst_impl.cc @@ -86,7 +86,7 @@ namespace gr { // Prepare an output message pmt::pmt_t blob_out = pmt::make_blob(burst_bits, burst_len); - pmt::pmt_t msg_out = pmt::cons(pmt::PMT_NIL, blob_out); + pmt::pmt_t msg_out = pmt::cons(pmt::car(msg_in), blob_out); /* Send a message to the output */ message_port_pub(pmt::mp("bursts_out"), msg_out); From 4650fad7cb3acf103775a1f14beb131650b09ebf Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 1 Dec 2017 05:08:35 +0700 Subject: [PATCH 02/11] trx/radio_if.py: use native burst_type_filter block --- python/trx/radio_if.py | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py index 689f074..9c26ec6 100644 --- a/python/trx/radio_if.py +++ b/python/trx/radio_if.py @@ -37,29 +37,6 @@ from gnuradio import gr # HACK: should be implemented in C++! -import numpy as np - -class burst_type_filter(gr.sync_block): - def __init__(self, burst_types=[]): - gr.sync_block.__init__( - self, - name='Burst type filter', - in_sig=[], - out_sig=[] - ) - self.burst_types = burst_types - self.message_port_register_in(pmt.intern("bursts_in")) - self.message_port_register_out(pmt.intern("bursts_out")) - self.set_msg_handler(pmt.intern("bursts_in"), self.filter) - - def filter(self, msg): - burst_with_header = pmt.to_python(pmt.cdr(msg)) - burst = burst_with_header[-148:] - header = np.ndarray.tolist(burst_with_header[0:-148]) - burst_type = header[12] - if burst_type in self.burst_types: - self.message_port_pub(pmt.intern("bursts_out"), msg) - class burst_to_fn_time(gr.basic_block): def __init__(self): # only default arguments here gr.basic_block.__init__( @@ -210,7 +187,7 @@ class radio_if(gr.top_block): # RX & TX synchronization - self.bt_filter = burst_type_filter([3]) + self.bt_filter = grgsm.burst_type_filter([3]) self.burst_to_fn_time = burst_to_fn_time() # Connections From 14b8e854c254f9d6872a4fbe925fb8ab66712169 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sun, 3 Dec 2017 23:13:08 +0700 Subject: [PATCH 03/11] apps/grgsm_trx: use 4 * GSM_SYM_RATE as default sample rate With this sample rate it's easier to synchronize training sequence with the signal. --- apps/grgsm_trx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/grgsm_trx b/apps/grgsm_trx index 507ed87..128adab 100755 --- a/apps/grgsm_trx +++ b/apps/grgsm_trx @@ -42,7 +42,7 @@ class Application: base_port = 5700 # PHY specific - phy_sample_rate = 2000000 + phy_sample_rate = 4 * 1625000 / 6 phy_tx_antenna = "TX/RX" phy_rx_antenna = "RX2" phy_rx_gain = 30 @@ -101,7 +101,7 @@ class Application: # PHY specific s += " Radio interface specific\n" \ " -a --device-args Set device arguments\n" \ - " -s --sample-rate Set sample rate (default 2000000)\n" \ + " -s --sample-rate Set sample rate\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" \ From 63703bb1ff93d024a175983e57d1045dba997b3b Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sun, 3 Dec 2017 23:40:21 +0700 Subject: [PATCH 04/11] trx/radio_if.py: explicilty set device clock rate The device timings are depend on the current clock rate, so let's explicilty set 26e6 as it's value, which is usable for USRP B2X0. --- python/trx/radio_if.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py index 9c26ec6..dbccae7 100644 --- a/python/trx/radio_if.py +++ b/python/trx/radio_if.py @@ -90,6 +90,7 @@ class radio_if(gr.top_block): uhd.stream_args(cpu_format="fc32", channels=range(1))) + self.phy_src.set_clock_rate(26e6, uhd.ALL_MBOARDS) self.phy_src.set_center_freq(self.rx_freq, 0) self.phy_src.set_antenna(phy_rx_antenna, 0) self.phy_src.set_samp_rate(phy_sample_rate) @@ -139,6 +140,7 @@ class radio_if(gr.top_block): uhd.stream_args(cpu_format="fc32", channels=range(1)), "packet_len") + self.phy_sink.set_clock_rate(26e6, uhd.ALL_MBOARDS) self.phy_sink.set_antenna(phy_tx_antenna, 0) self.phy_sink.set_samp_rate(phy_sample_rate) self.phy_sink.set_center_freq(self.tx_freq, 0) From d222ee58bbc260ea70cc995c70d797768f00f895 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sun, 3 Dec 2017 23:49:09 +0700 Subject: [PATCH 05/11] trx/radio_if.py: implement AFC for both RX and TX paths AFC (Automatic Frequency Control) was previously only utilized in the receive path of the radio interface. Now we also need to keep the transmitter frequency as accurate as possible. --- python/trx/radio_if.py | 104 +++++++++++++++++++++++++++++++++-------- 1 file changed, 84 insertions(+), 20 deletions(-) diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py index dbccae7..1ded337 100644 --- a/python/trx/radio_if.py +++ b/python/trx/radio_if.py @@ -29,12 +29,14 @@ import osmosdr from math import pi -from gnuradio.filter import firdes from gnuradio import digital from gnuradio import blocks from gnuradio import uhd from gnuradio import gr +from gnuradio import filter +from gnuradio.filter import firdes + # HACK: should be implemented in C++! class burst_to_fn_time(gr.basic_block): @@ -55,10 +57,29 @@ class burst_to_fn_time(gr.basic_block): if pmt.to_python(fn_time) is not None: self.message_port_pub(pmt.intern("fn_time_out"), fn_time_msg) +class dict_toggle_sign(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(pmt.intern("dict_in")) + self.message_port_register_out(pmt.intern("dict_out")) + self.set_msg_handler(pmt.intern("dict_in"), self.change_sign) + + def change_sign(self, msg): + if pmt.is_dict(msg): + d = pmt.to_python(msg) + for key, value in d.items(): + d[key] *= -1 + self.message_port_pub(pmt.intern("dict_out"), pmt.to_pmt(d)) + class radio_if(gr.top_block): # PHY specific variables rx_freq = 935e6 tx_freq = 890e6 + osr = 4 # Application state flags trx_started = False @@ -75,8 +96,10 @@ class radio_if(gr.top_block): print("[i] Init Radio interface") # PHY specific variables + self.sample_rate = phy_sample_rate self.rx_gain = phy_rx_gain self.tx_gain = phy_tx_gain + self.ppm = phy_ppm gr.top_block.__init__(self, "GR-GSM TRX") @@ -97,14 +120,15 @@ class radio_if(gr.top_block): self.phy_src.set_bandwidth(650e3, 0) self.phy_src.set_gain(phy_rx_gain) - self.gsm_input = grgsm.gsm_input( - ppm = phy_ppm - int(phy_ppm), osr = 4, - fc = self.rx_freq, samp_rate_in = phy_sample_rate) + self.msg_to_tag_src = grgsm.msg_to_tag() - self.gsm_receiver = grgsm.receiver(4, ([0]), ([])) + self.rotator_src = grgsm.controlled_rotator_cc( + self.calc_phase_inc(self.rx_freq)) - self.gsm_clck_ctrl = grgsm.clock_offset_control( - self.rx_freq, phy_sample_rate, osr = 4) + self.lpf = filter.fir_filter_ccf(1, firdes.low_pass( + 1, phy_sample_rate, 125e3, 5e3, firdes.WIN_HAMMING, 6.76)) + + self.gsm_receiver = grgsm.receiver(self.osr, ([0]), ([])) self.ts_filter = grgsm.burst_timeslot_filter(0) self.ts_filter.set_policy(grgsm.FILTER_POLICY_DROP_ALL) @@ -112,10 +136,18 @@ class radio_if(gr.top_block): # Connections self.connect( (self.phy_src, 0), - (self.gsm_input, 0)) + (self.msg_to_tag_src, 0)) self.connect( - (self.gsm_input, 0), + (self.msg_to_tag_src, 0), + (self.rotator_src, 0)) + + self.connect( + (self.rotator_src, 0), + (self.lpf, 0)) + + self.connect( + (self.lpf, 0), (self.gsm_receiver, 0)) self.msg_connect( @@ -126,14 +158,6 @@ class radio_if(gr.top_block): (self.ts_filter, 'out'), (self.trx_burst_if, 'bursts')) - self.msg_connect( - (self.gsm_receiver, 'measurements'), - (self.gsm_clck_ctrl, 'measurements')) - - self.msg_connect( - (self.gsm_clck_ctrl, 'ctrl'), - (self.gsm_input, 'ctrl_in')) - # TX Path Definition self.phy_sink = uhd.usrp_sink(phy_args, @@ -156,12 +180,17 @@ class radio_if(gr.top_block): blocks.byte_t, 'packet_len') self.gmsk_mod = grgsm.gsm_gmsk_mod( - BT = 4, pulse_duration = 4, sps = 4) + BT = 0.3, pulse_duration = 4, sps = self.osr) self.burst_shaper = digital.burst_shaper_cc( (firdes.window(firdes.WIN_HANN, 16, 0)), 0, 20, False, "packet_len") + self.msg_to_tag_sink = grgsm.msg_to_tag() + + self.rotator_sink = grgsm.controlled_rotator_cc( + -self.calc_phase_inc(self.tx_freq)) + # Connections self.msg_connect( (self.trx_burst_if, 'bursts'), @@ -185,6 +214,14 @@ class radio_if(gr.top_block): self.connect( (self.burst_shaper, 0), + (self.msg_to_tag_sink, 0)) + + self.connect( + (self.msg_to_tag_sink, 0), + (self.rotator_sink, 0)) + + self.connect( + (self.rotator_sink, 0), (self.phy_sink, 0)) @@ -205,19 +242,46 @@ class radio_if(gr.top_block): (self.burst_to_fn_time, 'fn_time_out'), (self.tx_time_setter, 'fn_time')) + + # AFC (Automatic Frequency Correction) + self.gsm_clck_ctrl = grgsm.clock_offset_control( + self.rx_freq, phy_sample_rate, osr = self.osr) + + self.dict_toggle_sign = dict_toggle_sign() + + # Connections + self.msg_connect( + (self.gsm_receiver, 'measurements'), + (self.gsm_clck_ctrl, 'measurements')) + + self.msg_connect( + (self.gsm_clck_ctrl, 'ctrl'), + (self.msg_to_tag_src, 'msg')) + + self.msg_connect( + (self.gsm_clck_ctrl, 'ctrl'), + (self.dict_toggle_sign, 'dict_in')) + + self.msg_connect( + (self.dict_toggle_sign, 'dict_out'), + (self.msg_to_tag_sink, 'msg')) + def shutdown(self): print("[i] Shutdown Radio interface") self.stop() self.wait() + def calc_phase_inc(self, fc): + return self.ppm / 1.0e6 * 2 * pi * fc / self.sample_rate + def set_rx_freq(self, fc): self.phy_src.set_center_freq(fc, 0) - self.gsm_clck_ctrl.set_fc(fc) - self.gsm_input.set_fc(fc) + self.rotator_src.set_phase_inc(self.calc_phase_inc(fc)) self.rx_freq = fc def set_tx_freq(self, fc): self.phy_sink.set_center_freq(fc, 0) + self.rotator_sink.set_phase_inc(-self.calc_phase_inc(fc)) self.tx_freq = fc def set_rx_gain(self, gain): From 0aafe2856de2286e5b88e43f81785a1aa5284f3f Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 1 Dec 2017 19:24:14 +0700 Subject: [PATCH 06/11] Implement the 'burst_to_fn_time' block in C++ --- grc/misc_utils/gsm_burst_to_fn_time.xml | 6 +- include/grgsm/misc_utils/CMakeLists.txt | 1 + include/grgsm/misc_utils/burst_to_fn_time.h | 57 ++++++++++++++ lib/misc_utils/CMakeLists.txt | 1 + lib/misc_utils/burst_to_fn_time_impl.cc | 84 +++++++++++++++++++++ lib/misc_utils/burst_to_fn_time_impl.h | 45 +++++++++++ python/__init__.py | 1 - python/misc_utils/CMakeLists.txt | 1 - python/misc_utils/burst_to_fn_time.py | 28 ------- swig/grgsm_swig.i | 5 +- 10 files changed, 193 insertions(+), 36 deletions(-) create mode 100644 include/grgsm/misc_utils/burst_to_fn_time.h create mode 100644 lib/misc_utils/burst_to_fn_time_impl.cc create mode 100644 lib/misc_utils/burst_to_fn_time_impl.h delete mode 100644 python/misc_utils/burst_to_fn_time.py diff --git a/grc/misc_utils/gsm_burst_to_fn_time.xml b/grc/misc_utils/gsm_burst_to_fn_time.xml index 0471605..fb98db6 100644 --- a/grc/misc_utils/gsm_burst_to_fn_time.xml +++ b/grc/misc_utils/gsm_burst_to_fn_time.xml @@ -1,19 +1,17 @@ - Burst to fn_time + Burst to FN time gsm_burst_to_fn_time import grgsm - grgsm.burst_to_fn_time() + grgsm.gsm_burst_to_fn_time() bursts_in message - 1 fn_time_out message - 1 diff --git a/include/grgsm/misc_utils/CMakeLists.txt b/include/grgsm/misc_utils/CMakeLists.txt index 8ac1f52..5ff1960 100644 --- a/include/grgsm/misc_utils/CMakeLists.txt +++ b/include/grgsm/misc_utils/CMakeLists.txt @@ -35,6 +35,7 @@ install(FILES tmsi_dumper.h msg_to_tag.h trx_burst_if.h + burst_to_fn_time.h controlled_fractional_resampler_cc.h time_spec.h fn_time.h DESTINATION include/grgsm/misc_utils diff --git a/include/grgsm/misc_utils/burst_to_fn_time.h b/include/grgsm/misc_utils/burst_to_fn_time.h new file mode 100644 index 0000000..870bd83 --- /dev/null +++ b/include/grgsm/misc_utils/burst_to_fn_time.h @@ -0,0 +1,57 @@ +/* -*- 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_BURST_TO_FN_TIME_H +#define INCLUDED_GRGSM_BURST_TO_FN_TIME_H + +#include +#include + +namespace gr { + namespace gsm { + + /*! + * \brief <+description of block+> + * \ingroup gsm + * + */ + class GRGSM_API burst_to_fn_time : virtual public gr::block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of grgsm::burst_to_fn_time. + * + * To avoid accidental use of raw pointers, grgsm::burst_to_fn_time's + * constructor is in a private implementation + * class. grgsm::burst_to_fn_time::make is the public interface for + * creating new instances. + */ + static sptr make(); + }; + + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GRGSM_BURST_TO_FN_TIME_H */ diff --git a/lib/misc_utils/CMakeLists.txt b/lib/misc_utils/CMakeLists.txt index 370f11c..c3edde5 100644 --- a/lib/misc_utils/CMakeLists.txt +++ b/lib/misc_utils/CMakeLists.txt @@ -36,5 +36,6 @@ add_sources( fn_time.cc udp_socket.cc trx_burst_if_impl.cc + burst_to_fn_time_impl.cc ) diff --git a/lib/misc_utils/burst_to_fn_time_impl.cc b/lib/misc_utils/burst_to_fn_time_impl.cc new file mode 100644 index 0000000..3e587f0 --- /dev/null +++ b/lib/misc_utils/burst_to_fn_time_impl.cc @@ -0,0 +1,84 @@ +/* -*- 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 "burst_to_fn_time_impl.h" + +namespace gr { + namespace gsm { + + burst_to_fn_time::sptr + burst_to_fn_time::make(void) + { + return gnuradio::get_initial_sptr + (new burst_to_fn_time_impl()); + } + + /* + * The private constructor + */ + burst_to_fn_time_impl::burst_to_fn_time_impl(void) + : gr::block("burst_to_fn_time", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)) + { + // Register I/O ports + message_port_register_in(pmt::mp("bursts_in")); + message_port_register_out(pmt::mp("fn_time_out")); + + // Bind a port handler + set_msg_handler(pmt::mp("bursts_in"), + boost::bind(&burst_to_fn_time_impl::handle_burst, this, _1)); + } + + /* + * Our virtual destructor. + */ + burst_to_fn_time_impl::~burst_to_fn_time_impl() + { + } + + void + burst_to_fn_time_impl::handle_burst(pmt::pmt_t msg_in) + { + // Obtain fn_time tag from message + pmt::pmt_t blob = pmt::car(msg_in); + pmt::pmt_t fn_time = pmt::dict_ref(blob, + pmt::intern("fn_time"), pmt::PMT_NIL); + + // Drop messages without required tag + if (fn_time == pmt::PMT_NIL) + return; + + // Compose and send a new message + pmt::pmt_t msg_out = pmt::dict_add(pmt::make_dict(), + pmt::intern("fn_time"), fn_time); + message_port_pub(pmt::mp("fn_time_out"), msg_out); + } + + } /* namespace gsm */ +} /* namespace gr */ diff --git a/lib/misc_utils/burst_to_fn_time_impl.h b/lib/misc_utils/burst_to_fn_time_impl.h new file mode 100644 index 0000000..e96c2bb --- /dev/null +++ b/lib/misc_utils/burst_to_fn_time_impl.h @@ -0,0 +1,45 @@ +/* -*- 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_BURST_TO_FN_TIME_IMPL_H +#define INCLUDED_GRGSM_BURST_TO_FN_TIME_IMPL_H + +#include + +namespace gr { + namespace gsm { + + class burst_to_fn_time_impl : public burst_to_fn_time + { + private: + void handle_burst(pmt::pmt_t msg_in); + + public: + burst_to_fn_time_impl(void); + ~burst_to_fn_time_impl(void); + }; + + } // namespace gsm +} // namespace gr + +#endif /* INCLUDED_GRGSM_BURST_TO_FN_TIME_IMPL_H */ diff --git a/python/__init__.py b/python/__init__.py index b3c9768..ad551ac 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -58,7 +58,6 @@ from gsm_sdcch8_demapper import gsm_sdcch8_demapper from gsm_gmsk_mod import gsm_gmsk_mod from fn_time import * from txtime_bursts_tagger import * -from burst_to_fn_time import * import arfcn diff --git a/python/misc_utils/CMakeLists.txt b/python/misc_utils/CMakeLists.txt index 8c7c175..ec732a4 100644 --- a/python/misc_utils/CMakeLists.txt +++ b/python/misc_utils/CMakeLists.txt @@ -23,6 +23,5 @@ GR_PYTHON_INSTALL( clock_offset_corrector_tagged.py hier_block.py fn_time.py - burst_to_fn_time.py DESTINATION ${GR_PYTHON_DIR}/grgsm ) diff --git a/python/misc_utils/burst_to_fn_time.py b/python/misc_utils/burst_to_fn_time.py deleted file mode 100644 index e31cf92..0000000 --- a/python/misc_utils/burst_to_fn_time.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -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/swig/grgsm_swig.i b/swig/grgsm_swig.i index 005033f..17ed130 100644 --- a/swig/grgsm_swig.i +++ b/swig/grgsm_swig.i @@ -74,6 +74,7 @@ #include "grgsm/transmitter/preprocess_tx_burst.h" #include "grgsm/transmitter/gen_test_ab.h" #include "grgsm/misc_utils/trx_burst_if.h" +#include "grgsm/misc_utils/burst_to_fn_time.h" %} %include "constants.i" @@ -177,14 +178,14 @@ GR_SWIG_BLOCK_MAGIC2(gsm, message_sink); //}; %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); +%include "grgsm/misc_utils/burst_to_fn_time.h" +GR_SWIG_BLOCK_MAGIC2(gsm, burst_to_fn_time); From 5cba704319a7f31a64ff1600af39c701061a9b2a Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Mon, 4 Dec 2017 01:51:00 +0700 Subject: [PATCH 07/11] trx/radio_if.py: use native burst_to_fn_time block --- python/trx/radio_if.py | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py index 1ded337..f84a710 100644 --- a/python/trx/radio_if.py +++ b/python/trx/radio_if.py @@ -39,24 +39,6 @@ from gnuradio.filter import firdes # HACK: should be implemented in C++! -class burst_to_fn_time(gr.basic_block): - def __init__(self): # only default arguments here - gr.basic_block.__init__( - self, - name='Burst to fn_time', - in_sig=[], - out_sig=[] - ) - self.message_port_register_in(pmt.intern("bursts_in")) - self.message_port_register_out(pmt.intern("fn_time_out")) - self.set_msg_handler(pmt.intern("bursts_in"), self.convert) - - def convert(self, msg): - fn_time = pmt.dict_ref(pmt.car(msg),pmt.intern("fn_time"),pmt.PMT_NIL) - fn_time_msg = pmt.dict_add(pmt.make_dict(), pmt.intern("fn_time"), fn_time) - if pmt.to_python(fn_time) is not None: - self.message_port_pub(pmt.intern("fn_time_out"), fn_time_msg) - class dict_toggle_sign(gr.basic_block): def __init__(self): # only default arguments here gr.basic_block.__init__(self, @@ -227,7 +209,7 @@ class radio_if(gr.top_block): # RX & TX synchronization self.bt_filter = grgsm.burst_type_filter([3]) - self.burst_to_fn_time = burst_to_fn_time() + self.burst_to_fn_time = grgsm.burst_to_fn_time() # Connections self.msg_connect( From 7f121d6470d04242bebe4ada80bf14bd1b8c00f7 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Mon, 4 Dec 2017 02:05:49 +0700 Subject: [PATCH 08/11] Clean up grgsm_swig.i --- swig/grgsm_swig.i | 45 +++++++++++---------------------------------- 1 file changed, 11 insertions(+), 34 deletions(-) diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i index 17ed130..c600a72 100644 --- a/swig/grgsm_swig.i +++ b/swig/grgsm_swig.i @@ -60,21 +60,20 @@ #include "grgsm/misc_utils/burst_file_source.h" #include "grgsm/misc_utils/collect_system_info.h" #include "grgsm/misc_utils/extract_cmc.h" -#include "grgsm/qa_utils/burst_sink.h" -#include "grgsm/qa_utils/burst_source.h" -#include "grgsm/qa_utils/message_source.h" -#include "grgsm/qa_utils/message_sink.h" #include "grgsm/misc_utils/message_file_sink.h" #include "grgsm/misc_utils/message_file_source.h" #include "grgsm/misc_utils/msg_to_tag.h" #include "grgsm/misc_utils/controlled_fractional_resampler_cc.h" -//#include "grgsm/misc_utils/time_spec.h" +#include "grgsm/misc_utils/trx_burst_if.h" +#include "grgsm/misc_utils/burst_to_fn_time.h" #include "grgsm/misc_utils/fn_time.h" +#include "grgsm/qa_utils/burst_sink.h" +#include "grgsm/qa_utils/burst_source.h" +#include "grgsm/qa_utils/message_source.h" +#include "grgsm/qa_utils/message_sink.h" #include "grgsm/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 "grgsm/misc_utils/burst_to_fn_time.h" %} %include "constants.i" @@ -146,6 +145,11 @@ GR_SWIG_BLOCK_MAGIC2(gsm, msg_to_tag); GR_SWIG_BLOCK_MAGIC2(gsm, controlled_fractional_resampler_cc); %include "grgsm/misc_utils/extract_cmc.h" GR_SWIG_BLOCK_MAGIC2(gsm, extract_cmc); +%include "grgsm/misc_utils/trx_burst_if.h" +GR_SWIG_BLOCK_MAGIC2(gsm, trx_burst_if); +%include "grgsm/misc_utils/burst_to_fn_time.h" +GR_SWIG_BLOCK_MAGIC2(gsm, burst_to_fn_time); + %include "grgsm/qa_utils/burst_sink.h" GR_SWIG_BLOCK_MAGIC2(gsm, burst_sink); %include "grgsm/qa_utils/burst_source.h" @@ -155,28 +159,6 @@ 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); @@ -184,8 +166,3 @@ GR_SWIG_BLOCK_MAGIC2(gsm, txtime_setter); 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); -%include "grgsm/misc_utils/burst_to_fn_time.h" -GR_SWIG_BLOCK_MAGIC2(gsm, burst_to_fn_time); From 9dded9b9f6e3a8a0412c2ab8f5b3e49b376d1b04 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 5 Dec 2017 01:00:51 +0700 Subject: [PATCH 09/11] trx/radio_if.py: clean up and explain GSM timings --- python/trx/radio_if.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py index f84a710..e0678ab 100644 --- a/python/trx/radio_if.py +++ b/python/trx/radio_if.py @@ -66,9 +66,17 @@ class radio_if(gr.top_block): # Application state flags trx_started = False - # GSM timings - delay_correction = 285.616e-6 - ul_dl_shift = -(6.0/1625000*(156.25)*3) + # GSM timings (in microseconds [uS]) + # One timeslot duration is 576.9 μs = 15/26 ms, + # or 156.25 symbol periods (a symbol period is 48/13 μs) + GSM_SYM_PERIOD_uS = 48.0 / 13.0 + GSM_TS_PERIOD_uS = GSM_SYM_PERIOD_uS * 156.25 + GSM_UL_DL_SHIFT_uS = -(GSM_TS_PERIOD_uS * 3) + + # FIXME: shall be measured (automatically?) for + # particular device and particular clock rate. + # The current value is measured for USRP B2X0 at 26e6. + delay_correction = (285.616 + 2 * GSM_SYM_PERIOD_uS) * 1e-6 def __init__(self, phy_args, phy_sample_rate, phy_rx_gain, phy_tx_gain, phy_ppm, @@ -154,7 +162,7 @@ class radio_if(gr.top_block): self.tx_time_setter = grgsm.txtime_setter( 0xffffffff, 0, 0, 0, 0, 0, - self.delay_correction + self.ul_dl_shift) + self.delay_correction + self.GSM_UL_DL_SHIFT_uS * 1e-6) self.tx_burst_proc = grgsm.preprocess_tx_burst() From 34266e785dc7c203c978dc5c6910dd2db4e6b3b8 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 5 Dec 2017 01:01:43 +0700 Subject: [PATCH 10/11] trx/radio_if.py: handle Timing Advance from CTRL --- python/trx/ctrl_if_bb.py | 14 ++++++++++++++ python/trx/radio_if.py | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/python/trx/ctrl_if_bb.py b/python/trx/ctrl_if_bb.py index 26ae49a..5874e59 100644 --- a/python/trx/ctrl_if_bb.py +++ b/python/trx/ctrl_if_bb.py @@ -62,6 +62,7 @@ class ctrl_if_bb(ctrl_if): if self.tb.trx_started: print("[i] Stopping transceiver...") self.tb.trx_started = False + self.tb.set_ta(0) self.tb.stop() self.tb.wait() @@ -144,6 +145,19 @@ class ctrl_if_bb(ctrl_if): return (0, [meas_dbm]) + # Timing Advance control + elif self.verify_cmd(request, "SETTA", 1): + print("[i] Recv SETTA cmd") + + # Check TA range + ta = int(request[1]) + if ta < 0 or ta > 63: + print("[!] TA value must be in range: 0..63") + return -1 + + self.tb.set_ta(ta) + return 0 + # Misc elif self.verify_cmd(request, "ECHO", 0): print("[i] Recv ECHO cmd") diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py index e0678ab..82491a8 100644 --- a/python/trx/radio_if.py +++ b/python/trx/radio_if.py @@ -281,3 +281,8 @@ class radio_if(gr.top_block): def set_tx_gain(self, gain): self.phy_sink.set_gain(gain, 0) self.tx_gain = gain + + def set_ta(self, ta): + print("[i] Setting TA value %d" % ta) + advance_time_sec = ta * self.GSM_SYM_PERIOD_uS * 1e-6 + self.tx_time_setter.set_timing_advance(advance_time_sec) From 012323230549af786f04fd94fc85ab7fbfa7a53d Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Sat, 9 Dec 2017 20:16:44 +0700 Subject: [PATCH 11/11] txtime_setter_impl: fix wrong time_hint reference --- lib/transmitter/txtime_setter_impl.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/transmitter/txtime_setter_impl.cc b/lib/transmitter/txtime_setter_impl.cc index f6141f0..03cc82e 100644 --- a/lib/transmitter/txtime_setter_impl.cc +++ b/lib/transmitter/txtime_setter_impl.cc @@ -87,15 +87,14 @@ namespace gr { 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); + pmt::intern("fn_time"), pmt::PMT_NIL); time_hint = pmt::dict_ref(msg, - pmt::intern("fn_time"), not_found); + pmt::intern("time_hint"), pmt::PMT_NIL); - if (fn_time != not_found) { + if (fn_time != pmt::PMT_NIL) { uint32_t fn_ref = static_cast (pmt::to_uint64(pmt::car(pmt::car(fn_time)))); uint32_t ts = static_cast @@ -106,7 +105,7 @@ namespace gr { pmt::cdr(pmt::cdr(fn_time))); set_fn_time_reference(fn_ref, ts, time_secs, time_fracs); - } else if (time_hint != not_found) { + } else if (time_hint != pmt::PMT_NIL) { set_time_hint(pmt::to_uint64(pmt::car(fn_time)), pmt::to_double(pmt::cdr(fn_time))); }