<p>fixeria has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmocom-bb/+/18262">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">trx_toolkit/transceiver.py: add frequency hopping support<br><br>There are two ways to implement frequency hopping:<br><br>  a) The Transceiver is configured with the hopping parameters, in<br>     particular HSN, MAIO, and the list of ARFCNs (channels), so the<br>     actual Rx/Tx frequencies are changed by the Transceiver itself<br>     depending on the current TDMA frame number.<br><br>  b) The L1 maintains several Transceivers (two or more), so each<br>     instance is assigned one dedicated RF carrier frequency, and<br>     hence the number of available hopping frequencies is equal to<br>     the number of Transceivers. In this case, it's the task of<br>     the L1 to commutate bursts between Transceivers (frequencies).<br><br>For the MS side, a) is preferred, because a phone usually has only<br>one Transceiver (per RAT). On the other hand, b) is more suitable<br>for the BTS side, because it's relatively easy to implement and<br>there is no technical limitation on the amount of Transceivers.<br><br>FakeTRX obviously does support b) since multi-TRX feature has been<br>implemented, as well as a) by resolving UL/DL frequencies using a<br>preconfigured (by the L1) set of the hopping parameters. The later<br>can be enabled using the SETFH control command:<br><br>  CMD SETFH <HSN> <MAIO> <RXF1> <TXF1><br>                    <RXF2> <TXF2><br>                [... <RXFN> <TXFN>]<br><br>where <RXFN> and <TXFN> is a pair of Rx/Tx frequencies (in kHz)<br>corresponding to one ARFCN the Mobile Allocation. Note that the<br>channel list is expected to be sorted in ascending order.<br><br>NOTE: in the current implementation, mode a) applies to the whole<br>Transceiver and all its timeslots, so using in for the BTS side<br>does not make any sense (imagine BCCH hopping together with DCCH).<br><br>Change-Id: I587e4f5da67c7b7f28e010ed46b24622c31a3fdd<br>---<br>M src/target/trx_toolkit/burst_fwd.py<br>M src/target/trx_toolkit/ctrl_if.py<br>M src/target/trx_toolkit/ctrl_if_trx.py<br>M src/target/trx_toolkit/fake_pm.py<br>M src/target/trx_toolkit/transceiver.py<br>5 files changed, 147 insertions(+), 16 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/62/18262/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/target/trx_toolkit/burst_fwd.py b/src/target/trx_toolkit/burst_fwd.py</span><br><span>index fd6013b..9fb308f 100644</span><br><span>--- a/src/target/trx_toolkit/burst_fwd.py</span><br><span>+++ b/src/target/trx_toolkit/burst_fwd.py</span><br><span>@@ -4,7 +4,8 @@</span><br><span> # TRX Toolkit</span><br><span> # Burst forwarding between transceivers</span><br><span> #</span><br><span style="color: hsl(0, 100%, 40%);">-# (C) 2017-2018 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+# (C) 2017-2020 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+# Contributions by sysmocom - s.f.m.c. GmbH</span><br><span> #</span><br><span> # All Rights Reserved</span><br><span> #</span><br><span>@@ -65,6 +66,10 @@</span><br><span>            self.trx_list.remove(trx)</span><br><span> </span><br><span>        def forward_msg(self, src_trx, rx_msg):</span><br><span style="color: hsl(120, 100%, 40%);">+               # Originating Transceiver may use frequency hopping,</span><br><span style="color: hsl(120, 100%, 40%);">+          # so let's precalculate its Tx frequency in advance</span><br><span style="color: hsl(120, 100%, 40%);">+               tx_freq = src_trx.get_tx_freq(rx_msg.fn)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>           # Iterate over all known transceivers</span><br><span>                for trx in self.trx_list:</span><br><span>                    if trx == src_trx:</span><br><span>@@ -73,11 +78,13 @@</span><br><span>                     # Check transceiver state</span><br><span>                    if not trx.running:</span><br><span>                          continue</span><br><span style="color: hsl(0, 100%, 40%);">-                        if trx.rx_freq != src_trx.tx_freq:</span><br><span style="color: hsl(0, 100%, 40%);">-                              continue</span><br><span>                     if rx_msg.tn not in trx.ts_list:</span><br><span>                             continue</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+                  # Match Tx/Rx frequencies of the both transceivers</span><br><span style="color: hsl(120, 100%, 40%);">+                    if trx.get_rx_freq(rx_msg.fn) != tx_freq:</span><br><span style="color: hsl(120, 100%, 40%);">+                             continue</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>                   # Transform from L12TRX to TRX2L1 and forward</span><br><span>                        tx_msg = rx_msg.gen_trx2l1(ver = trx.data_if._hdr_ver)</span><br><span>                       trx.handle_data_msg(src_trx, rx_msg, tx_msg)</span><br><span>diff --git a/src/target/trx_toolkit/ctrl_if.py b/src/target/trx_toolkit/ctrl_if.py</span><br><span>index 89dfe46..7333501 100644</span><br><span>--- a/src/target/trx_toolkit/ctrl_if.py</span><br><span>+++ b/src/target/trx_toolkit/ctrl_if.py</span><br><span>@@ -4,7 +4,8 @@</span><br><span> # TRX Toolkit</span><br><span> # CTRL interface implementation</span><br><span> #</span><br><span style="color: hsl(0, 100%, 40%);">-# (C) 2016-2017 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+# (C) 2016-2020 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+# Contributions by sysmocom - s.f.m.c. GmbH</span><br><span> #</span><br><span> # All Rights Reserved</span><br><span> #</span><br><span>@@ -61,13 +62,17 @@</span><br><span>               # Now we have something like ["TXTUNE", "941600"]</span><br><span>                return request</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      def verify_cmd(self, request, cmd, argc):</span><br><span style="color: hsl(120, 100%, 40%);">+     # If va is True, the command can have variable number of arguments</span><br><span style="color: hsl(120, 100%, 40%);">+    def verify_cmd(self, request, cmd, argc, va = False):</span><br><span>                # Check if requested command matches</span><br><span>                 if request[0] != cmd:</span><br><span>                        return False</span><br><span> </span><br><span>             # And has enough arguments</span><br><span style="color: hsl(0, 100%, 40%);">-              if len(request) - 1 != argc:</span><br><span style="color: hsl(120, 100%, 40%);">+          req_len = len(request[1:])</span><br><span style="color: hsl(120, 100%, 40%);">+            if not va and req_len != argc:</span><br><span style="color: hsl(120, 100%, 40%);">+                        return False</span><br><span style="color: hsl(120, 100%, 40%);">+          elif va and req_len < argc:</span><br><span>                       return False</span><br><span> </span><br><span>             return True</span><br><span>diff --git a/src/target/trx_toolkit/ctrl_if_trx.py b/src/target/trx_toolkit/ctrl_if_trx.py</span><br><span>index e44f8a9..aab161b 100644</span><br><span>--- a/src/target/trx_toolkit/ctrl_if_trx.py</span><br><span>+++ b/src/target/trx_toolkit/ctrl_if_trx.py</span><br><span>@@ -4,7 +4,8 @@</span><br><span> # TRX Toolkit</span><br><span> # CTRL interface implementation (common commands)</span><br><span> #</span><br><span style="color: hsl(0, 100%, 40%);">-# (C) 2016-2019 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+# (C) 2016-2020 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+# Contributions by sysmocom - s.f.m.c. GmbH</span><br><span> #</span><br><span> # All Rights Reserved</span><br><span> #</span><br><span>@@ -105,9 +106,9 @@</span><br><span>                              log.error("(%s) Transceiver already started" % self.trx)</span><br><span>                           return -1</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-                   # Ensure RX / TX freq. are set</span><br><span style="color: hsl(0, 100%, 40%);">-                  if (self.trx.rx_freq is None) or (self.trx.tx_freq is None):</span><br><span style="color: hsl(0, 100%, 40%);">-                            log.error("(%s) RX / TX freq. are not set" % self.trx)</span><br><span style="color: hsl(120, 100%, 40%);">+                      # Ensure that transceiver is ready</span><br><span style="color: hsl(120, 100%, 40%);">+                    if not self.trx.ready:</span><br><span style="color: hsl(120, 100%, 40%);">+                                log.error("(%s) Transceiver is not ready" % self.trx)</span><br><span>                              return -1</span><br><span> </span><br><span>                        log.info("(%s) Starting transceiver..." % self.trx)</span><br><span>@@ -187,6 +188,44 @@</span><br><span> </span><br><span>                     return (0, [str(meas_dbm)])</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+               # Frequency hopping configuration (variable length list).</span><br><span style="color: hsl(120, 100%, 40%);">+             #</span><br><span style="color: hsl(120, 100%, 40%);">+             # Format: CMD SETFH <HSN> <MAIO> <RXF1> <TXF1></span><br><span style="color: hsl(120, 100%, 40%);">+                #                                <RXF2> <TXF2></span><br><span style="color: hsl(120, 100%, 40%);">+            #                           [... <RXFN> <TXFN>]</span><br><span style="color: hsl(120, 100%, 40%);">+           #</span><br><span style="color: hsl(120, 100%, 40%);">+             # where <RXFN> and <TXFN> is a pair of Rx/Tx frequencies (in kHz)</span><br><span style="color: hsl(120, 100%, 40%);">+         # corresponding to one ARFCN the Mobile Allocation. Note that the</span><br><span style="color: hsl(120, 100%, 40%);">+             # channel list is expected to be sorted in ascending order.</span><br><span style="color: hsl(120, 100%, 40%);">+           if self.verify_cmd(request, "SETFH", 2, va = True):</span><br><span style="color: hsl(120, 100%, 40%);">+                 log.debug("(%s) Recv SETFH cmd" % self.trx)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                       # Parse HSN and MAIO</span><br><span style="color: hsl(120, 100%, 40%);">+                  hsn = int(request[1])</span><br><span style="color: hsl(120, 100%, 40%);">+                 maio = int(request[2])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                      # List of MA frequencies</span><br><span style="color: hsl(120, 100%, 40%);">+                      ma = request[3:]</span><br><span style="color: hsl(120, 100%, 40%);">+                      ma_len = len(ma)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                    # Make sure that MA length is even and contains at least 2 pairs</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (ma_len // 2 < 2) or (ma_len % 2 != 0):</span><br><span style="color: hsl(120, 100%, 40%);">+                         log.error("(%s) Hopping channel list is incomplete "</span><br><span style="color: hsl(120, 100%, 40%);">+                                          "(N=%d)" % (self.trx, ma_len))</span><br><span style="color: hsl(120, 100%, 40%);">+                            return -1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   # Parse the list of hopping frequencies</span><br><span style="color: hsl(120, 100%, 40%);">+                       ma = [int(f) * 1000 for f in ma] # kHz -> Hz</span><br><span style="color: hsl(120, 100%, 40%);">+                       ma = [(rx, tx) for rx, tx in zip(ma[0::2], ma[1::2])]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                       # Ask the Transceiver to enable frequency hopping</span><br><span style="color: hsl(120, 100%, 40%);">+                     try:</span><br><span style="color: hsl(120, 100%, 40%);">+                          self.trx.enable_fh(hsn, maio, ma)</span><br><span style="color: hsl(120, 100%, 40%);">+                             return 0</span><br><span style="color: hsl(120, 100%, 40%);">+                      except:</span><br><span style="color: hsl(120, 100%, 40%);">+                               log.error("(%s) Failed to enable frequency hopping" % trx)</span><br><span style="color: hsl(120, 100%, 40%);">+                          return -1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          # TRXD header version negotiation</span><br><span>            if self.verify_cmd(request, "SETFORMAT", 1):</span><br><span>                       log.debug("(%s) Recv SETFORMAT cmd" % self.trx)</span><br><span>diff --git a/src/target/trx_toolkit/fake_pm.py b/src/target/trx_toolkit/fake_pm.py</span><br><span>index 51dc057..0d66099 100644</span><br><span>--- a/src/target/trx_toolkit/fake_pm.py</span><br><span>+++ b/src/target/trx_toolkit/fake_pm.py</span><br><span>@@ -64,14 +64,19 @@</span><br><span>     def rssi_trx(self):</span><br><span>          return randint(self.trx_min, self.trx_max)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  def measure(self, freq):</span><br><span style="color: hsl(120, 100%, 40%);">+      def measure(self, freq, fn = None):</span><br><span>          # Iterate over all known transceivers</span><br><span>                for trx in self.trx_list:</span><br><span>                    if not trx.running:</span><br><span>                          continue</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+                  # FIXME: we need to know current TDMA frame number here,</span><br><span style="color: hsl(120, 100%, 40%);">+                      # because some transceivers may use frequency hopping</span><br><span style="color: hsl(120, 100%, 40%);">+                 if trx.fh is not None and fn is None:</span><br><span style="color: hsl(120, 100%, 40%);">+                         continue</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>                   # Match by given frequency</span><br><span style="color: hsl(0, 100%, 40%);">-                      if trx.tx_freq == freq:</span><br><span style="color: hsl(120, 100%, 40%);">+                       if trx.get_tx_freq(fn) == freq:</span><br><span>                              return self.rssi_trx</span><br><span> </span><br><span>             return self.rssi_noise</span><br><span>diff --git a/src/target/trx_toolkit/transceiver.py b/src/target/trx_toolkit/transceiver.py</span><br><span>index b1a5c11..3e1f14c 100644</span><br><span>--- a/src/target/trx_toolkit/transceiver.py</span><br><span>+++ b/src/target/trx_toolkit/transceiver.py</span><br><span>@@ -4,7 +4,8 @@</span><br><span> # TRX Toolkit</span><br><span> # Transceiver implementation</span><br><span> #</span><br><span style="color: hsl(0, 100%, 40%);">-# (C) 2018-2019 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+# (C) 2018-2020 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+# Contributions by sysmocom - s.f.m.c. GmbH</span><br><span> #</span><br><span> # All Rights Reserved</span><br><span> #</span><br><span>@@ -29,6 +30,8 @@</span><br><span> from udp_link import UDPLink</span><br><span> from trx_list import TRXList</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+from gsm_shared import HoppingParams</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> class Transceiver:</span><br><span>        """ Base transceiver implementation.</span><br><span> </span><br><span>@@ -88,6 +91,35 @@</span><br><span>         that shall provide at least one method: measure(freq). This</span><br><span>  is required for the MS side (i.e. OsmocomBB).</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+     == Frequency hopping (optional)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     There are two ways to implement frequency hopping:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    a) The Transceiver is configured with the hopping parameters, in</span><br><span style="color: hsl(120, 100%, 40%);">+         particular HSN, MAIO, and the list of ARFCNs (channels), so the</span><br><span style="color: hsl(120, 100%, 40%);">+       actual Rx/Tx frequencies are changed by the Transceiver itself</span><br><span style="color: hsl(120, 100%, 40%);">+        depending on the current TDMA frame number.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      b) The L1 maintains several Transceivers (two or more), so each</span><br><span style="color: hsl(120, 100%, 40%);">+          instance is assigned one dedicated RF carrier frequency, and</span><br><span style="color: hsl(120, 100%, 40%);">+          hence the number of available hopping frequencies is equal to</span><br><span style="color: hsl(120, 100%, 40%);">+         the number of Transceivers. In this case, it's the task of</span><br><span style="color: hsl(120, 100%, 40%);">+        the L1 to commutate bursts between Transceivers (frequencies).</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ For the MS side, a) is preferred, because a phone usually has only</span><br><span style="color: hsl(120, 100%, 40%);">+    one Transceiver (per RAT). On the other hand, b) is more suitable</span><br><span style="color: hsl(120, 100%, 40%);">+     for the BTS side, because it's relatively easy to implement and</span><br><span style="color: hsl(120, 100%, 40%);">+   there is no technical limitation on the amount of Transceivers.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     FakeTRX obviously does support b) since multi-TRX feature has been</span><br><span style="color: hsl(120, 100%, 40%);">+    implemented, as well as a) by resolving UL/DL frequencies using a</span><br><span style="color: hsl(120, 100%, 40%);">+     preconfigured (by the L1) set of the hopping parameters. The later</span><br><span style="color: hsl(120, 100%, 40%);">+    can be enabled using the SETFH control command.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     NOTE: in the current implementation, mode a) applies to the whole</span><br><span style="color: hsl(120, 100%, 40%);">+     Transceiver and all its timeslots, so using in for the BTS side</span><br><span style="color: hsl(120, 100%, 40%);">+       does not make any sense (imagine BCCH hopping together with DCCH).</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         """</span><br><span> </span><br><span>       def __init__(self, bind_addr, remote_addr, base_port, name = None,</span><br><span>@@ -131,8 +163,11 @@</span><br><span>            self.running = False</span><br><span> </span><br><span>             # Actual RX / TX frequencies</span><br><span style="color: hsl(0, 100%, 40%);">-            self.rx_freq = None</span><br><span style="color: hsl(0, 100%, 40%);">-             self.tx_freq = None</span><br><span style="color: hsl(120, 100%, 40%);">+           self._rx_freq = None</span><br><span style="color: hsl(120, 100%, 40%);">+          self._tx_freq = None</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                # Frequency hopping parameters (set by CTRL)</span><br><span style="color: hsl(120, 100%, 40%);">+          self.fh = None</span><br><span> </span><br><span>           # List of active (configured) timeslots</span><br><span>              self.ts_list = []</span><br><span>@@ -149,6 +184,41 @@</span><br><span> </span><br><span>                 return desc</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+       @property</span><br><span style="color: hsl(120, 100%, 40%);">+     def ready(self):</span><br><span style="color: hsl(120, 100%, 40%);">+              # Make sure that either both Rx/Tx frequencies are set</span><br><span style="color: hsl(120, 100%, 40%);">+                if self._rx_freq is None or self._tx_freq is None:</span><br><span style="color: hsl(120, 100%, 40%);">+                    # ... or frequency hopping is in use</span><br><span style="color: hsl(120, 100%, 40%);">+                  if self.fh is None:</span><br><span style="color: hsl(120, 100%, 40%);">+                           return False</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                return True</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def get_rx_freq(self, fn):</span><br><span style="color: hsl(120, 100%, 40%);">+            if self.fh is None:</span><br><span style="color: hsl(120, 100%, 40%);">+                   return self._rx_freq</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                # Frequency hopping in use, resolve by TDMA fn</span><br><span style="color: hsl(120, 100%, 40%);">+                (rx_freq, _) = self.fh.resolve(fn)</span><br><span style="color: hsl(120, 100%, 40%);">+            return rx_freq</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      def get_tx_freq(self, fn):</span><br><span style="color: hsl(120, 100%, 40%);">+            if self.fh is None:</span><br><span style="color: hsl(120, 100%, 40%);">+                   return self._tx_freq</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                # Frequency hopping in use, resolve by TDMA fn</span><br><span style="color: hsl(120, 100%, 40%);">+                (_, tx_freq) = self.fh.resolve(fn)</span><br><span style="color: hsl(120, 100%, 40%);">+            return tx_freq</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      def enable_fh(self, *args):</span><br><span style="color: hsl(120, 100%, 40%);">+           self.fh = HoppingParams(*args)</span><br><span style="color: hsl(120, 100%, 40%);">+                log.info("(%s) Frequency hopping enabled: %s" % (self, self.fh))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  def disable_fh(self):</span><br><span style="color: hsl(120, 100%, 40%);">+         if self.fh is not None:</span><br><span style="color: hsl(120, 100%, 40%);">+                       log.info("(%s) Frequency hopping disabled" % self)</span><br><span style="color: hsl(120, 100%, 40%);">+                  self.fh = None</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>     # To be overwritten if required,</span><br><span>     # no custom command handlers by default</span><br><span>      def ctrl_cmd_handler(self, request):</span><br><span>@@ -159,8 +229,13 @@</span><br><span>          for trx in self.child_trx_list.trx_list:</span><br><span>                     if event == "POWERON":</span><br><span>                             trx.running = True</span><br><span style="color: hsl(0, 100%, 40%);">-                      else:</span><br><span style="color: hsl(120, 100%, 40%);">+                 elif event == "POWEROFF":</span><br><span>                          trx.running = False</span><br><span style="color: hsl(120, 100%, 40%);">+                           trx.disable_fh()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            # Reset frequency hopping parameters</span><br><span style="color: hsl(120, 100%, 40%);">+          if event == "POWEROFF":</span><br><span style="color: hsl(120, 100%, 40%);">+                     self.disable_fh()</span><br><span> </span><br><span>                # Trigger clock generator if required</span><br><span>                if self.clck_gen is not None:</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmocom-bb/+/18262">change 18262</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmocom-bb/+/18262"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmocom-bb </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I587e4f5da67c7b7f28e010ed46b24622c31a3fdd </div>
<div style="display:none"> Gerrit-Change-Number: 18262 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: fixeria <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>