Vadim Yanitskiy has uploaded this change for review. ( 
https://gerrit.osmocom.org/12635


Change subject: python/trx: introduce and use Transceiver class
......................................................................

python/trx: introduce and use Transceiver class

Change-Id: I6dc88edbb69a68746cc8e01206dc86f7ea2fa80f
---
M apps/grgsm_trx
M python/trx/CMakeLists.txt
M python/trx/__init__.py
M python/trx/ctrl_if_bb.py
M python/trx/radio_if.py
A python/trx/transceiver.py
6 files changed, 142 insertions(+), 54 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/gr-gsm refs/changes/35/12635/1

diff --git a/apps/grgsm_trx b/apps/grgsm_trx
index c3e83d9..5e5e3be 100755
--- a/apps/grgsm_trx
+++ b/apps/grgsm_trx
@@ -29,8 +29,8 @@
 from argparse import ArgumentTypeError
 from gnuradio import eng_notation

-from grgsm.trx import CTRLInterfaceBB
 from grgsm.trx import RadioInterface
+from grgsm.trx import Transceiver

 COPYRIGHT = \
        "Copyright (C) 2016-2018 by Vadim Yanitskiy <[email protected]>\n" \
@@ -64,18 +64,17 @@
                        self.phy_freq_offset, self.bind_addr,
                        self.remote_addr, self.base_port)

-               # Init TRX CTRL interface
-               self.server = CTRLInterfaceBB(
-                       self.remote_addr, self.base_port + 101,
-                       self.bind_addr, self.base_port + 1,
-                       self.radio)
+               # Init Transceiver
+               self.trx = Transceiver(self.bind_addr,
+                       self.remote_addr, self.base_port,
+                       radio_if = self.radio)

                print("[i] Init complete")

        def run(self):
                # Enter main loop
                while True:
-                       self.server.loop()
+                       self.trx.ctrl_if.loop()

        def shutdown(self):
                print("[i] Shutting down...")
diff --git a/python/trx/CMakeLists.txt b/python/trx/CMakeLists.txt
index 4333407..11290f3 100644
--- a/python/trx/CMakeLists.txt
+++ b/python/trx/CMakeLists.txt
@@ -25,6 +25,7 @@
     ctrl_if_bb.py
     radio_if.py
     radio_if_grc.py
+    transceiver.py
     dict_toggle_sign.py
     DESTINATION ${GR_PYTHON_DIR}/grgsm/trx
 )
diff --git a/python/trx/__init__.py b/python/trx/__init__.py
index 7b20699..00d370b 100644
--- a/python/trx/__init__.py
+++ b/python/trx/__init__.py
@@ -25,5 +25,6 @@
 from ctrl_if_bb import CTRLInterfaceBB
 from radio_if_grc import RadioInterfaceGRC
 from radio_if import RadioInterface
+from transceiver import Transceiver

 from dict_toggle_sign import dict_toggle_sign
diff --git a/python/trx/ctrl_if_bb.py b/python/trx/ctrl_if_bb.py
index 0e194d0..4814263 100644
--- a/python/trx/ctrl_if_bb.py
+++ b/python/trx/ctrl_if_bb.py
@@ -4,7 +4,7 @@
 # GR-GSM based transceiver
 # CTRL interface for OsmocomBB
 #
-# (C) 2016-2017 by Vadim Yanitskiy <[email protected]>
+# (C) 2016-2019 by Vadim Yanitskiy <[email protected]>
 #
 # All Rights Reserved
 #
@@ -22,49 +22,32 @@
 # 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 CTRLInterface

 class CTRLInterfaceBB(CTRLInterface):
-       def __init__(self, remote_addr, remote_port, bind_addr, bind_port, tb):
-               CTRLInterface.__init__(self, remote_addr, remote_port,
-                       bind_addr, bind_port)
-
+       def __init__(self, trx, *ctrl_if_args):
+               CTRLInterface.__init__(self, *ctrl_if_args)
                print("[i] Init CTRL interface (%s)" % self.desc_link())

-               # Set link to the follow graph (top block)
-               self.tb = tb
+               # Transceiver instance we belong to
+               self.trx = trx

        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")
+                       # Start transceiver
+                       if not self.trx.start():
                                return -1

-                       print("[i] Starting transceiver...")
-                       self.tb.trx_started = True
-                       self.tb.start()
-
                        return 0

                elif self.verify_cmd(request, "POWEROFF", 0):
                        print("[i] Recv POWEROFF cmd")

-                       # TODO: flush all buffers between blocks
-                       if self.tb.trx_started:
-                               print("[i] Stopping transceiver...")
-                               self.tb.trx_started = False
-                               self.tb.set_ta(0)
-                               self.tb.stop()
-                               self.tb.wait()
-
-                       # POWEROFF is also used to reset transceiver
-                       self.tb.reset()
+                       # Stop transceiver
+                       self.trx.stop()

                        return 0

@@ -74,7 +57,7 @@

                        # TODO: check gain value
                        gain = int(request[1])
-                       self.tb.set_rx_gain(gain)
+                       self.trx.radio_if.set_rx_gain(gain)

                        return 0

@@ -83,7 +66,7 @@

                        # TODO: check gain value
                        gain = int(request[1])
-                       self.tb.set_tx_gain(gain)
+                       self.trx.radio_if.set_tx_gain(gain)

                        return 0

@@ -93,7 +76,7 @@

                        # TODO: check freq range
                        freq = int(request[1]) * 1000
-                       self.tb.set_rx_freq(freq)
+                       self.trx.radio_if.set_rx_freq(freq)

                        return 0

@@ -102,7 +85,7 @@

                        # TODO: check freq range
                        freq = int(request[1]) * 1000
-                       self.tb.set_tx_freq(freq)
+                       self.trx.radio_if.set_tx_freq(freq)

                        return 0

@@ -116,19 +99,12 @@
                                print("[!] TS index should be in range: 0..7")
                                return -1

-                       # Ignore timeslot type for now
+                       # Channel combination number (see GSM TS 05.02)
+                       # TODO: check this value
                        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)
+                       # TODO: check return value
+                       self.trx.radio_if.set_slot(tn, config)

                        return 0

@@ -138,9 +114,11 @@

                        # TODO: check freq range
                        meas_freq = int(request[1]) * 1000
-                       meas_dbm = str(self.tb.measure(meas_freq))
+                       meas_dbm = self.trx.measure(meas_freq)
+                       if meas_dbm is None:
+                               return -1

-                       return (0, [meas_dbm])
+                       return (0, [str(meas_dbm)])

                # Timing Advance control
                elif self.verify_cmd(request, "SETTA", 1):
@@ -152,7 +130,7 @@
                                print("[!] TA value must be in range: 0..63")
                                return -1

-                       self.tb.set_ta(ta)
+                       self.trx.radio_if.set_ta(ta)
                        return 0

                # Misc
diff --git a/python/trx/radio_if.py b/python/trx/radio_if.py
index ed5a8de..ec9cd5f 100644
--- a/python/trx/radio_if.py
+++ b/python/trx/radio_if.py
@@ -47,9 +47,6 @@
        tx_freq = None
        osr = 4

-       # Application state flags
-       trx_started = False
-
        # 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)
@@ -304,6 +301,20 @@
                self.phy_sink.set_gain(gain, 0)
                self.tx_gain = gain

+       def set_slot(self, slot, config):
+               print("[i] Configure timeslot filter to: %s"
+                       % ("drop all" if config == 0 else "tn=%d" % slot))
+
+               if config == 0:
+                       # Value 0 is used for deactivation
+                       self.ts_filter.set_policy(grgsm.FILTER_POLICY_DROP_ALL)
+               else:
+                       # FIXME: ideally, we should (re)configure the Receiver
+                       # block, but there is no API for that, and hard-coded
+                       # timeslot configuration is used...
+                       self.ts_filter.set_policy(grgsm.FILTER_POLICY_DEFAULT)
+                       self.ts_filter.set_tn(slot)
+
        def set_ta(self, ta):
                print("[i] Setting TA value %d" % ta)
                advance_time_sec = ta * self.GSM_SYM_PERIOD_uS * 1e-6
diff --git a/python/trx/transceiver.py b/python/trx/transceiver.py
new file mode 100644
index 0000000..837a61f
--- /dev/null
+++ b/python/trx/transceiver.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python2
+# -*- coding: utf-8 -*-
+
+# GR-GSM based transceiver
+# Transceiver implementation
+#
+# (C) 2018-2019 by Vadim Yanitskiy <[email protected]>
+#
+# All Rights Reserved
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+from ctrl_if_bb import CTRLInterfaceBB
+
+class Transceiver:
+       """ Base transceiver implementation.
+
+       Represents a single transceiver, that can be used as for the BTS side,
+       as for the MS side. Each individual instance of Transceiver unifies
+       three basic interfaces built on three independent UDP connections:
+
+         - CLCK (base port + 100/0) - clock indications from TRX to L1,
+         - CTRL (base port + 101/1) - control interface for L1,
+         - DATA (base port + 102/2) - bidirectional data interface for bursts.
+
+       A transceiver can be either in active (i.e. working), or in idle mode.
+
+       NOTE: both CLCK and DATA interfaces are handled by the flow-graph,
+             (see RadioInterface), so we only initialize CTRL interface.
+
+       """
+
+       def __init__(self, bind_addr, remote_addr, base_port, radio_if):
+               # Connection info
+               self.remote_addr = remote_addr
+               self.bind_addr = bind_addr
+               self.base_port = base_port
+
+               # Execution state (running or idle)
+               self.running = False
+
+               # Radio interface (handles both CLCK and DATA interfaces)
+               self.radio_if = radio_if
+
+               # Init CTRL interface
+               self.ctrl_if = CTRLInterfaceBB(self,
+                       remote_addr, base_port + 101,
+                       bind_addr, base_port + 1)
+
+       def start(self):
+               # Check execution state
+               if self.running:
+                       print("[!] Transceiver is already started")
+                       return False
+
+               # Make sure that Radio interface is ready, i.e.
+               # all parameters (e.g. RX / RX freq) are set.
+               if not self.radio_if.ready:
+                       print("[!] RadioInterface is not ready")
+                       return False
+
+               print("[i] Starting transceiver...")
+               self.radio_if.start()
+               self.running = True
+
+               return True
+
+       def stop(self):
+               # POWEROFF is also used to reset transceiver,
+               # so we should not complain that it isn't running.
+               if not self.running:
+                       print("[i] Resetting transceiver")
+                       self.radio_if.reset()
+                       return
+
+               print("[i] Stopping transceiver...")
+
+               # TODO: flush all buffers between blocks
+               self.radio_if.stop()
+               self.radio_if.wait()
+
+               self.running = False
+
+       def measure(self, freq):
+               # TODO: transceiver should be in idle mode
+               return self.radio_if.measure(freq)

--
To view, visit https://gerrit.osmocom.org/12635
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: gr-gsm
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I6dc88edbb69a68746cc8e01206dc86f7ea2fa80f
Gerrit-Change-Number: 12635
Gerrit-PatchSet: 1
Gerrit-Owner: Vadim Yanitskiy <[email protected]>

Reply via email to