<p>Harald Welte has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/9600">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">lms: Several improvements and compilation/runtime fixes<br><br>Continuation of initial work done on LimeSuite support from Harald.<br><br>Change-Id: Ib2fca81b76d027b08e2891056fa076d071597783<br>---<br>M CommonLibs/Logger.h<br>M CommonLibs/debug.c<br>M CommonLibs/debug.h<br>M Transceiver52M/device/lms/LMSDevice.cpp<br>M Transceiver52M/device/lms/LMSDevice.h<br>M Transceiver52M/device/radioDevice.h<br>6 files changed, 274 insertions(+), 127 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-trx refs/changes/00/9600/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/CommonLibs/Logger.h b/CommonLibs/Logger.h</span><br><span>index 5b0b05c..e18ecfb 100644</span><br><span>--- a/CommonLibs/Logger.h</span><br><span>+++ b/CommonLibs/Logger.h</span><br><span>@@ -53,6 +53,9 @@</span><br><span> #define LOGC(category, level) \</span><br><span>     Log(category, LOGL_##level, __BASE_FILE__, __LINE__).get() <<  "[tid=" << pthread_self() << "] "</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define LOGLV(category, level) \</span><br><span style="color: hsl(120, 100%, 40%);">+  Log(category, level, __BASE_FILE__, __LINE__).get() <<  "[tid=" << pthread_self() << "] "</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /**</span><br><span>     A C++ stream-based thread-safe logger.</span><br><span>       This object is NOT the global logger;</span><br><span>diff --git a/CommonLibs/debug.c b/CommonLibs/debug.c</span><br><span>index e4db2f3..01854c0 100644</span><br><span>--- a/CommonLibs/debug.c</span><br><span>+++ b/CommonLibs/debug.c</span><br><span>@@ -10,6 +10,12 @@</span><br><span>              .color = NULL,</span><br><span>               .enabled = 1, .loglevel = LOGL_NOTICE,</span><br><span>       },</span><br><span style="color: hsl(120, 100%, 40%);">+    [DLMS] = {</span><br><span style="color: hsl(120, 100%, 40%);">+            .name = "DLMS",</span><br><span style="color: hsl(120, 100%, 40%);">+             .description = "LimeSuite category",</span><br><span style="color: hsl(120, 100%, 40%);">+                .color = NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+                .enabled = 1, .loglevel = LOGL_NOTICE,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span> };</span><br><span> </span><br><span> const struct log_info log_info = {</span><br><span>diff --git a/CommonLibs/debug.h b/CommonLibs/debug.h</span><br><span>index 7038f4c..06ad74e 100644</span><br><span>--- a/CommonLibs/debug.h</span><br><span>+++ b/CommonLibs/debug.h</span><br><span>@@ -5,4 +5,5 @@</span><br><span> /* Debug Areas of the code */</span><br><span> enum {</span><br><span>         DMAIN,</span><br><span style="color: hsl(120, 100%, 40%);">+        DLMS,</span><br><span> };</span><br><span>diff --git a/Transceiver52M/device/lms/LMSDevice.cpp b/Transceiver52M/device/lms/LMSDevice.cpp</span><br><span>index ed51cdb..603b23d 100644</span><br><span>--- a/Transceiver52M/device/lms/LMSDevice.cpp</span><br><span>+++ b/Transceiver52M/device/lms/LMSDevice.cpp</span><br><span>@@ -24,26 +24,40 @@</span><br><span> </span><br><span> #include <lime/LimeSuite.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #ifdef HAVE_CONFIG_H</span><br><span> #include "config.h"</span><br><span> #endif</span><br><span> </span><br><span> using namespace std;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-const double LMSDevice::masterClockRate = 52.0e6;</span><br><span style="color: hsl(120, 100%, 40%);">+constexpr double LMSDevice::masterClockRate;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-LMSDevice::LMSDevice(size_t sps)</span><br><span style="color: hsl(120, 100%, 40%);">+#define MAX_ANTENNA_LIST_SIZE 10</span><br><span style="color: hsl(120, 100%, 40%);">+#define LMS_SAMPLE_RATE GSMRATE*32</span><br><span style="color: hsl(120, 100%, 40%);">+#define GSM_CARRIER_BW 270000.0 /* 270kHz */</span><br><span style="color: hsl(120, 100%, 40%);">+#define LMS_MIN_BW_SUPPORTED 2.5e6 /* 2.5mHz, minimum supported by LMS */</span><br><span style="color: hsl(120, 100%, 40%);">+#define LMS_CALIBRATE_BW_HZ OSMO_MAX(GSM_CARRIER_BW, LMS_MIN_BW_SUPPORTED)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+LMSDevice::LMSDevice(size_t sps, size_t chans):</span><br><span style="color: hsl(120, 100%, 40%);">+  m_lms_dev(NULL), sps(sps), chans(chans)</span><br><span> {</span><br><span>         LOG(INFO) << "creating LMS device...";</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      m_lms_device = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    this->sps = sps;</span><br><span style="color: hsl(120, 100%, 40%);">+   m_lms_stream_rx.resize(chans);</span><br><span style="color: hsl(120, 100%, 40%);">+        m_lms_stream_tx.resize(chans);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      m_last_rx_underruns.resize(chans, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ m_last_rx_overruns.resize(chans, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+  m_last_tx_underruns.resize(chans, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ m_last_tx_overruns.resize(chans, 0);</span><br><span> }</span><br><span> </span><br><span> static void lms_log_callback(int lvl, const char *msg)</span><br><span> {</span><br><span>         /* map lime specific log levels */</span><br><span style="color: hsl(0, 100%, 40%);">-      static const lvl_map[4] = {</span><br><span style="color: hsl(120, 100%, 40%);">+   static const int lvl_map[5] = {</span><br><span>              [0] = LOGL_FATAL,</span><br><span>            [1] = LOGL_ERROR,</span><br><span>            [2] = LOGL_NOTICE,</span><br><span>@@ -51,40 +65,71 @@</span><br><span>             [4] = LOGL_DEBUG,</span><br><span>    };</span><br><span>   /* protect against future higher log level values (lower importance) */</span><br><span style="color: hsl(0, 100%, 40%);">- if (lvl >= ARRAY_SIZE(lvl_map))</span><br><span style="color: hsl(120, 100%, 40%);">+    if ((unsigned int) lvl >= ARRAY_SIZE(lvl_map))</span><br><span>            lvl = ARRAY_SIZE(lvl_map)-1;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        LOG(lvl) << msg;</span><br><span style="color: hsl(120, 100%, 40%);">+        LOGLV(DLMS, lvl) << msg;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-int LMSDevice::open(const std::string &, int, bool)</span><br><span style="color: hsl(120, 100%, 40%);">+static void thread_enable_cancel(bool cancel)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-      lms_info_str dev_str;</span><br><span style="color: hsl(0, 100%, 40%);">-   uint16_t dac_val;</span><br><span style="color: hsl(120, 100%, 40%);">+     cancel ? pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) :</span><br><span style="color: hsl(120, 100%, 40%);">+                 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   LOG(INFO) << "opening LMS device..";</span><br><span style="color: hsl(120, 100%, 40%);">+int LMSDevice::open(const std::string &args, int ref, bool swap_channels)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        //lms_info_str_t dev_str;</span><br><span style="color: hsl(120, 100%, 40%);">+     lms_info_str_t* info_list;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint16_t dac_val;</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned int i, n;</span><br><span style="color: hsl(120, 100%, 40%);">+    int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     LOG(INFO) << "Opening LMS device..";</span><br><span> </span><br><span>     LMS_RegisterLogHandler(&lms_log_callback);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      rc = LMS_Open(&m_lms_dev, NULL, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-      if (rc != 0)</span><br><span style="color: hsl(0, 100%, 40%);">-            return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+        if ((n = LMS_GetDeviceList(NULL)) < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+            LOG(ERROR) << "LMS_GetDeviceList(NULL) failed";</span><br><span style="color: hsl(120, 100%, 40%);">+        LOG(DEBUG) << "Devices found: " << n;</span><br><span style="color: hsl(120, 100%, 40%);">+        if (n < 1)</span><br><span style="color: hsl(120, 100%, 40%);">+            return -1;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      if (LMS_SetSampleRate(m_lms_dev, GSMRATE, sps) < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+        info_list = new lms_info_str_t[n];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (LMS_GetDeviceList(info_list) < 0)                //Populate device list</span><br><span style="color: hsl(120, 100%, 40%);">+            LOG(ERROR) << "LMS_GetDeviceList(info_list) failed";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        for (i = 0; i < n; i++)                     //print device list</span><br><span style="color: hsl(120, 100%, 40%);">+           LOG(DEBUG) << "Device [" << i << "]: " << info_list[i];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        rc = LMS_Open(&m_lms_dev, info_list[0], NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (rc != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOG(ERROR) << "LMS_GetDeviceList() failed)";</span><br><span style="color: hsl(120, 100%, 40%);">+          delete [] info_list;</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   delete [] info_list;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        LOG(DEBUG) << "Setting sample rate to " << GSMRATE*sps << " " << sps;</span><br><span style="color: hsl(120, 100%, 40%);">+     if (LMS_SetSampleRate(m_lms_dev, GSMRATE*sps, 32) < 0)</span><br><span>            goto out_close;</span><br><span>      /* FIXME: make this device/model dependent, like UHDDevice:dev_param_map! */</span><br><span style="color: hsl(0, 100%, 40%);">-    ts_offset = static_caset<TIMESTAMP>(8.9e-5 * GSMRATE);</span><br><span style="color: hsl(120, 100%, 40%);">+  ts_offset = static_cast<TIMESTAMP>(8.9e-5 * GSMRATE);</span><br><span> </span><br><span>      switch (ref) {</span><br><span>       case REF_INTERNAL:</span><br><span style="color: hsl(120, 100%, 40%);">+            LOG(DEBUG) << "Setting Internal clock reference";</span><br><span>            /* Ugly API: Selecting clock source implicit by writing to VCTCXO DAC ?!? */</span><br><span>                 if (LMS_VCTCXORead(m_lms_dev, &dac_val) < 0)</span><br><span>                  goto out_close;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+               LOG(DEBUG) << "Setting VCTCXO to " << dac_val;</span><br><span>                 if (LMS_VCTCXOWrite(m_lms_dev, dac_val) < 0)</span><br><span>                      goto out_close;</span><br><span>              break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case REF_EXTENAL:</span><br><span style="color: hsl(120, 100%, 40%);">+     case REF_EXTERNAL:</span><br><span style="color: hsl(120, 100%, 40%);">+            LOG(DEBUG) << "Setting Internal clock reference to " << 10000000.0;</span><br><span>            /* Assume an external 10 MHz reference clock */</span><br><span>              if (LMS_SetClockFreq(m_lms_dev, LMS_CLOCK_EXTREF, 10000000.0) < 0)</span><br><span>                        goto out_close;</span><br><span>@@ -94,14 +139,18 @@</span><br><span>               goto out_close;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ LOG(INFO) << "Init LMS device";</span><br><span>      if (LMS_Init(m_lms_dev) < 0)</span><br><span>              goto out_close;</span><br><span> </span><br><span>  /* Perform Rx and Tx calibration */</span><br><span style="color: hsl(0, 100%, 40%);">-     if (LMS_Calibrate(m_lms_dev, LMS_CH_RX, chan, 270000.0, 0) < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-              goto out_close;</span><br><span style="color: hsl(0, 100%, 40%);">- if (LMS_Calibrate(m_lms_dev, LMS_CH_TX, chan, 270000.0, 0) < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-              goto out_close;</span><br><span style="color: hsl(120, 100%, 40%);">+       for (i=0; i<chans; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          LOG(INFO) << "Calibrating chan " << i;</span><br><span style="color: hsl(120, 100%, 40%);">+          if (LMS_Calibrate(m_lms_dev, LMS_CH_RX, i, LMS_CALIBRATE_BW_HZ, 0) < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                    goto out_close;</span><br><span style="color: hsl(120, 100%, 40%);">+               if (LMS_Calibrate(m_lms_dev, LMS_CH_TX, i, LMS_CALIBRATE_BW_HZ, 0) < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                    goto out_close;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span> </span><br><span>        samplesRead = 0;</span><br><span>     samplesWritten = 0;</span><br><span>@@ -119,42 +168,47 @@</span><br><span> {</span><br><span>     LOG(INFO) << "starting LMS...";</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     if (LMS_EnableChannel(m_lms_dev, LMS_CH_RX, 0, true) < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-            return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int i;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     if (LMS_EnableChannel(m_lms_dev, LMS_CH_TX, 0, true) < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-            return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i=0; i<chans; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (LMS_EnableChannel(m_lms_dev, LMS_CH_RX, i, true) < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                  return false;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       // Set gains to midpoint</span><br><span style="color: hsl(0, 100%, 40%);">-        setTxGain((minTxGain() + maxTxGain()) / 2);</span><br><span style="color: hsl(0, 100%, 40%);">-     setRxGain((minRxGain() + maxRxGain()) / 2);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (LMS_EnableChannel(m_lms_dev, LMS_CH_TX, i, true) < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                  return false;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       m_lms_stream_rx = {</span><br><span style="color: hsl(0, 100%, 40%);">-             .isTx = false,</span><br><span style="color: hsl(0, 100%, 40%);">-          .channel = 0,</span><br><span style="color: hsl(0, 100%, 40%);">-           .fifoSize = 1024 * 1024,</span><br><span style="color: hsl(0, 100%, 40%);">-                .throughputVsLatency = 0.3,</span><br><span style="color: hsl(0, 100%, 40%);">-             .dataFmt = LMS_FMT_I16,</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-       m_lms_stream_tx = {</span><br><span style="color: hsl(0, 100%, 40%);">-             .ixTx = true,</span><br><span style="color: hsl(0, 100%, 40%);">-           .channel = 0,</span><br><span style="color: hsl(0, 100%, 40%);">-           .fifoSize = 1024 * 1024,</span><br><span style="color: hsl(0, 100%, 40%);">-                .throughputVsLatency = 0.3,</span><br><span style="color: hsl(0, 100%, 40%);">-             .dataFmt = LMS_FMT_I16,</span><br><span style="color: hsl(120, 100%, 40%);">+               // Set gains to midpoint</span><br><span style="color: hsl(120, 100%, 40%);">+              setTxGain((minTxGain() + maxTxGain()) / 2, i);</span><br><span style="color: hsl(120, 100%, 40%);">+                setRxGain((minRxGain() + maxRxGain()) / 2, i);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              m_lms_stream_rx[i] = {};</span><br><span style="color: hsl(120, 100%, 40%);">+              m_lms_stream_rx[i].isTx = false;</span><br><span style="color: hsl(120, 100%, 40%);">+              m_lms_stream_rx[i].channel = i;</span><br><span style="color: hsl(120, 100%, 40%);">+               m_lms_stream_rx[i].fifoSize = 1024 * 1024;</span><br><span style="color: hsl(120, 100%, 40%);">+            m_lms_stream_rx[i].throughputVsLatency = 0.3;</span><br><span style="color: hsl(120, 100%, 40%);">+         m_lms_stream_rx[i].dataFmt = lms_stream_t::LMS_FMT_I16;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             m_lms_stream_tx[i] = {};</span><br><span style="color: hsl(120, 100%, 40%);">+              m_lms_stream_tx[i].isTx = true;</span><br><span style="color: hsl(120, 100%, 40%);">+               m_lms_stream_tx[i].channel = i;</span><br><span style="color: hsl(120, 100%, 40%);">+               m_lms_stream_tx[i].fifoSize = 1024 * 1024;</span><br><span style="color: hsl(120, 100%, 40%);">+            m_lms_stream_tx[i].throughputVsLatency = 0.3;</span><br><span style="color: hsl(120, 100%, 40%);">+         m_lms_stream_tx[i].dataFmt = lms_stream_t::LMS_FMT_I16;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             if (LMS_SetupStream(m_lms_dev, &m_lms_stream_rx[i]) < 0)</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%);">+               if (LMS_SetupStream(m_lms_dev, &m_lms_stream_tx[i]) < 0)</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%);">+               if (LMS_StartStream(&m_lms_stream_rx[i]) < 0)</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%);">+               if (LMS_StartStream(&m_lms_stream_tx[i]) < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                  return false;</span><br><span>        }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (LMS_SetupStream(m_lms_dev, &m_lms_stream_rx) < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-            return false;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   if (LMS_SetupStream(m_lms_dev, &m_lms_stream_tx) < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-            return false;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   if (LMS_StartStream(&m_lms_stream_rx) < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-               return false;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   if (LMS_StartStream(&m_lms_stream_tx) < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-               return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ flush_recv(10);</span><br><span> </span><br><span>  started = true;</span><br><span>      return true;</span><br><span>@@ -162,14 +216,18 @@</span><br><span> </span><br><span> bool LMSDevice::stop()</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>    if (!started)</span><br><span>                return true;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        LMS_StopStream(&m_lms_stream_tx);</span><br><span style="color: hsl(0, 100%, 40%);">-   LMS_StopStream(&m_lms_stream_rx);</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i=0; i<chans; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          LMS_StopStream(&m_lms_stream_tx[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+              LMS_StopStream(&m_lms_stream_rx[i]);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    LMS_EnableChannel(m_lms_dev, LMS_CH_RX, 0, false);</span><br><span style="color: hsl(0, 100%, 40%);">-      LMS_EnableChannel(m_lms_dev, LMS_CH_TX, 0, false);</span><br><span style="color: hsl(120, 100%, 40%);">+            LMS_EnableChannel(m_lms_dev, LMS_CH_RX, i, false);</span><br><span style="color: hsl(120, 100%, 40%);">+            LMS_EnableChannel(m_lms_dev, LMS_CH_TX, i, false);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span> </span><br><span>        return true;</span><br><span> }</span><br><span>@@ -236,18 +294,50 @@</span><br><span>    return dB;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-int get_ant_idx(const char *name, bool dir_tx)</span><br><span style="color: hsl(120, 100%, 40%);">+int LMSDevice::get_ant_idx(const std::string & name, bool dir_tx, size_t chan)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-      lms_name_t name_list;</span><br><span style="color: hsl(120, 100%, 40%);">+ lms_name_t name_list[MAX_ANTENNA_LIST_SIZE]; /* large enough list for antenna names. */</span><br><span style="color: hsl(120, 100%, 40%);">+       const char* c_name = name.c_str();</span><br><span>   int num_names;</span><br><span style="color: hsl(0, 100%, 40%);">-  num_names = LMS_GetAntennaList(m_lms_dev, dir_tx, &name_list);</span><br><span style="color: hsl(120, 100%, 40%);">+    int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      num_names = LMS_GetAntennaList(m_lms_dev, dir_tx, chan, name_list);</span><br><span>  for (i = 0; i < num_names; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-            if (!strcmp(name, name_list[i]))</span><br><span style="color: hsl(120, 100%, 40%);">+              if (!strcmp(c_name, name_list[i]))</span><br><span>                   return i;</span><br><span>    }</span><br><span>    return -1;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+bool LMSDevice::flush_recv(size_t num_pkts)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   #define CHUNK 625</span><br><span style="color: hsl(120, 100%, 40%);">+     int len = CHUNK * sps;</span><br><span style="color: hsl(120, 100%, 40%);">+        short *buffer = new short[len * 2];</span><br><span style="color: hsl(120, 100%, 40%);">+   int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       lms_stream_meta_t rx_metadata = {};</span><br><span style="color: hsl(120, 100%, 40%);">+   rx_metadata.flushPartialPacket = false;</span><br><span style="color: hsl(120, 100%, 40%);">+       rx_metadata.waitForTimestamp = false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ts_initial = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     while (!ts_initial || (num_pkts-- > 0)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          rc = LMS_RecvStream(&m_lms_stream_rx[0], &buffer[0], len, &rx_metadata, 100);</span><br><span style="color: hsl(120, 100%, 40%);">+             LOG(DEBUG) << "Flush: Recv buffer of len " << rc << " at " << std::hex << rx_metadata.timestamp;</span><br><span style="color: hsl(120, 100%, 40%);">+            if (rc != len) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      LOG(ALERT) << "LMS: Device receive timed out";</span><br><span style="color: hsl(120, 100%, 40%);">+                        delete[] buffer;</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           ts_initial = rx_metadata.timestamp;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   LOG(INFO) << "Initial timestamp " << ts_initial << std::endl;</span><br><span style="color: hsl(120, 100%, 40%);">+     delete[] buffer;</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%);">+</span><br><span> bool LMSDevice::setRxAntenna(const std::string & ant, size_t chan)</span><br><span> {</span><br><span>     int idx;</span><br><span>@@ -257,7 +347,7 @@</span><br><span>               return false;</span><br><span>        }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   idx = get_ant_idx(ant, LMS_CH_RX);</span><br><span style="color: hsl(120, 100%, 40%);">+    idx = get_ant_idx(ant, LMS_CH_RX, chan);</span><br><span>     if (idx < 0) {</span><br><span>            LOG(ALERT) << "Invalid Rx Antenna";</span><br><span>          return false;</span><br><span>@@ -272,6 +362,9 @@</span><br><span> </span><br><span> std::string LMSDevice::getRxAntenna(size_t chan)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+      lms_name_t name_list[MAX_ANTENNA_LIST_SIZE]; /* large enough list for antenna names. */</span><br><span style="color: hsl(120, 100%, 40%);">+       int idx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>   if (chan >= rx_paths.size()) {</span><br><span>            LOG(ALERT) << "Requested non-existent channel " << chan;</span><br><span>               return "";</span><br><span>@@ -283,12 +376,12 @@</span><br><span>                 return "";</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (LMS_GetAntennaList(m_lms_dev, LMS_CH_RX, chan, &list) < idx) {</span><br><span style="color: hsl(120, 100%, 40%);">+     if (LMS_GetAntennaList(m_lms_dev, LMS_CH_RX, chan, name_list) < idx) {</span><br><span>            LOG(ALERT) << "Error getting Rx Antenna List";</span><br><span>               return "";</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   return list[idx];</span><br><span style="color: hsl(120, 100%, 40%);">+     return name_list[idx];</span><br><span> }</span><br><span> </span><br><span> bool LMSDevice::setTxAntenna(const std::string & ant, size_t chan)</span><br><span>@@ -300,7 +393,7 @@</span><br><span>              return false;</span><br><span>        }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   idx = get_ant_idx(ant, LMS_CH_TX);</span><br><span style="color: hsl(120, 100%, 40%);">+    idx = get_ant_idx(ant, LMS_CH_TX, chan);</span><br><span>     if (idx < 0) {</span><br><span>            LOG(ALERT) << "Invalid Rx Antenna";</span><br><span>          return false;</span><br><span>@@ -315,6 +408,7 @@</span><br><span> </span><br><span> std::string LMSDevice::getTxAntenna(size_t chan)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+      lms_name_t name_list[MAX_ANTENNA_LIST_SIZE]; /* large enough list for antenna names. */</span><br><span>      int idx;</span><br><span> </span><br><span>         if (chan >= tx_paths.size()) {</span><br><span>@@ -328,49 +422,73 @@</span><br><span>            return "";</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (LMS_GetAntennaList(m_lms_dev, LMS_CH_TX, chan, &list) < idx) {</span><br><span style="color: hsl(120, 100%, 40%);">+     if (LMS_GetAntennaList(m_lms_dev, LMS_CH_TX, chan, name_list) < idx) {</span><br><span>            LOG(ALERT) << "Error getting Tx Antenna List";</span><br><span>               return "";</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   return list[idx];</span><br><span style="color: hsl(120, 100%, 40%);">+     return name_list[idx];</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+bool LMSDevice::requiresRadioAlign()</span><br><span style="color: hsl(120, 100%, 40%);">+{</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+GSM::Time LMSDevice::minLatency() {</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Empirical data from a handful of</span><br><span style="color: hsl(120, 100%, 40%);">+   relatively recent machines shows that the B100 will underrun when</span><br><span style="color: hsl(120, 100%, 40%);">+     the transmit threshold is reduced to a time of 6 and a half frames,</span><br><span style="color: hsl(120, 100%, 40%);">+   so we set a minimum 7 frame threshold. */</span><br><span style="color: hsl(120, 100%, 40%);">+     return GSM::Time(6,7);</span><br><span> }</span><br><span> </span><br><span> // NOTE: Assumes sequential reads</span><br><span> int LMSDevice::readSamples(std::vector < short *>&bufs, int len, bool * overrun,</span><br><span>                      TIMESTAMP timestamp, bool * underrun, unsigned *RSSI)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-   lms_stream_meta_t rx_metadata = {</span><br><span style="color: hsl(0, 100%, 40%);">-               .flushPartialPacket = false,</span><br><span style="color: hsl(0, 100%, 40%);">-            .waitForTimestamp = false,</span><br><span style="color: hsl(0, 100%, 40%);">-      };</span><br><span style="color: hsl(0, 100%, 40%);">-      int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+       lms_stream_status_t status;</span><br><span style="color: hsl(120, 100%, 40%);">+   lms_stream_meta_t rx_metadata = {};</span><br><span style="color: hsl(120, 100%, 40%);">+   rx_metadata.flushPartialPacket = false;</span><br><span style="color: hsl(120, 100%, 40%);">+       rx_metadata.waitForTimestamp = false;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Shift read time with respect to transmit clock */</span><br><span style="color: hsl(120, 100%, 40%);">+  timestamp += ts_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+       rx_metadata.timestamp = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  if (bufs.size != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bufs.size() != chans) {</span><br><span>          LOG(ALERT) << "Invalid channel combination " << bufs.size();</span><br><span>           return -1;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* Shift read time with respect to transmit clock */</span><br><span style="color: hsl(0, 100%, 40%);">-    timestamp += ts_offset;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- rc = LMS_RecvStream(&m_lms_stream_rx, bufs[0], len, &rx_metadata, 100);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>      *overrun = false;</span><br><span>    *underrun = false;</span><br><span style="color: hsl(120, 100%, 40%);">+    for (i = 0; i<chans; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                thread_enable_cancel(false);</span><br><span style="color: hsl(120, 100%, 40%);">+          rc = LMS_RecvStream(&m_lms_stream_rx[i], bufs[i], len, &rx_metadata, 100);</span><br><span style="color: hsl(120, 100%, 40%);">+            LOG(ALERT) << "chan "<< i << " recv buffer of len " << rc << " expect " << std::hex << timestamp << " got " << std::hex << (TIMESTAMP)rx_metadata.timestamp << " (" << std::hex << rx_metadata.timestamp <<") diff=" << rx_metadata.timestamp - timestamp;</span><br><span style="color: hsl(120, 100%, 40%);">+              if (rc != len) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      LOG(ALERT) << "LMS: Device receive timed out";</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (LMS_GetStreamStatus(&m_lms_stream_rx, &status) == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-              if (status.underrun > m_last_rx_underruns)</span><br><span style="color: hsl(0, 100%, 40%);">-                   *underrun = true;</span><br><span style="color: hsl(0, 100%, 40%);">-               m_last_rx_underruns = status.underrun;</span><br><span style="color: hsl(120, 100%, 40%);">+                if (LMS_GetStreamStatus(&m_lms_stream_rx[i], &status) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (status.underrun > m_last_rx_underruns[i])</span><br><span style="color: hsl(120, 100%, 40%);">+                              *underrun = true;</span><br><span style="color: hsl(120, 100%, 40%);">+                     m_last_rx_underruns[i] = status.underrun;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           if (status.overrun > m_last_rx_overruns)</span><br><span style="color: hsl(0, 100%, 40%);">-                     *overrun = true;</span><br><span style="color: hsl(0, 100%, 40%);">-                m_last_rx_overruns = status.overrun;</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (status.overrun > m_last_rx_overruns[i])</span><br><span style="color: hsl(120, 100%, 40%);">+                                *overrun = true;</span><br><span style="color: hsl(120, 100%, 40%);">+                      m_last_rx_overruns[i] = status.overrun;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+             thread_enable_cancel(true);</span><br><span>  }</span><br><span> </span><br><span>        samplesRead += rc;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+        if (((TIMESTAMP) rx_metadata.timestamp) < timestamp)</span><br><span style="color: hsl(120, 100%, 40%);">+               rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>    return rc;</span><br><span> }</span><br><span> </span><br><span>@@ -378,35 +496,40 @@</span><br><span>                      bool * underrun, unsigned long long timestamp,</span><br><span>                       bool isControl)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-        lms_stream_status_t status;</span><br><span style="color: hsl(0, 100%, 40%);">-     lms_stream_meta_t tx_metadata = {</span><br><span style="color: hsl(0, 100%, 40%);">-               .flushPartialPacket = false,</span><br><span style="color: hsl(0, 100%, 40%);">-            .waitForTimestamp = true,</span><br><span style="color: hsl(0, 100%, 40%);">-               .timestamp = timestamp,</span><br><span style="color: hsl(0, 100%, 40%);">- };</span><br><span>   int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+       lms_stream_status_t status;</span><br><span style="color: hsl(120, 100%, 40%);">+   lms_stream_meta_t tx_metadata = {};</span><br><span style="color: hsl(120, 100%, 40%);">+   tx_metadata.flushPartialPacket = false;</span><br><span style="color: hsl(120, 100%, 40%);">+       tx_metadata.waitForTimestamp = true;</span><br><span style="color: hsl(120, 100%, 40%);">+  tx_metadata.timestamp = timestamp;</span><br><span> </span><br><span>       if (isControl) {</span><br><span>             LOG(ERR) << "Control packets not supported";</span><br><span>                 return 0;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (bufs.size() != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+       if (bufs.size() != chans) {</span><br><span>          LOG(ALERT) << "Invalid channel combination " << bufs.size();</span><br><span>           return -1;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   rc = LMS_Send_Stream(&m_lms_stream_tx, bufs[0], len, &tx_metadata, 100);</span><br><span style="color: hsl(0, 100%, 40%);">-        if (rc != len) {</span><br><span style="color: hsl(0, 100%, 40%);">-                LOG(ALERT) << "LMS: Device send timed out ";</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>    *underrun = false;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  if (LMS_GetStreamStatus(&m_lms_stream_tx, &status) == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-              if (status.underrun > m_last_tx_underruns)</span><br><span style="color: hsl(0, 100%, 40%);">-                   *underrun = true;</span><br><span style="color: hsl(0, 100%, 40%);">-               m_last_tx_underruns = status.underrun;</span><br><span style="color: hsl(120, 100%, 40%);">+        for (i = 0; i<chans; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOG(ALERT) << "chan "<< i << " send buffer of len " << len << " timestamp " << std::hex << tx_metadata.timestamp;</span><br><span style="color: hsl(120, 100%, 40%);">+             thread_enable_cancel(false);</span><br><span style="color: hsl(120, 100%, 40%);">+          rc = LMS_SendStream(&m_lms_stream_tx[i], bufs[i], len, &tx_metadata, 100);</span><br><span style="color: hsl(120, 100%, 40%);">+            if (rc != len) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      LOG(ALERT) << "LMS: Device send timed out";</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (LMS_GetStreamStatus(&m_lms_stream_tx[i], &status) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (status.underrun > m_last_tx_underruns[i])</span><br><span style="color: hsl(120, 100%, 40%);">+                              *underrun = true;</span><br><span style="color: hsl(120, 100%, 40%);">+                     m_last_tx_underruns[i] = status.underrun;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             thread_enable_cancel(true);</span><br><span>  }</span><br><span> </span><br><span>        samplesWritten += rc;</span><br><span>@@ -416,17 +539,7 @@</span><br><span> </span><br><span> bool LMSDevice::updateAlignment(TIMESTAMP timestamp)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-   short data[] = { 0x00, 0x02, 0x00, 0x00 };</span><br><span style="color: hsl(0, 100%, 40%);">-      uint32_t *wordPtr = (uint32_t *) data;</span><br><span style="color: hsl(0, 100%, 40%);">-  *wordPtr = host_to_usrp_u32(*wordPtr);</span><br><span style="color: hsl(0, 100%, 40%);">-  bool tmpUnderrun;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       std::vector < short *>buf(1, data);</span><br><span style="color: hsl(0, 100%, 40%);">-       if (writeSamples(buf, 1, &tmpUnderrun, timestamp & 0x0ffffffffll, true)) {</span><br><span style="color: hsl(0, 100%, 40%);">-              pingTimestamp = timestamp;</span><br><span style="color: hsl(0, 100%, 40%);">-              return true;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-       return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ return true;</span><br><span> }</span><br><span> </span><br><span> bool LMSDevice::setTxFreq(double wFreq, size_t chan)</span><br><span>@@ -465,5 +578,5 @@</span><br><span>                         const std::vector < std::string > &tx_paths,</span><br><span>                               const std::vector < std::string > &rx_paths)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-      return new LMSDevice(tx_sps);</span><br><span style="color: hsl(120, 100%, 40%);">+ return new LMSDevice(tx_sps, chans);</span><br><span> }</span><br><span>diff --git a/Transceiver52M/device/lms/LMSDevice.h b/Transceiver52M/device/lms/LMSDevice.h</span><br><span>index 653d159..99eed43 100644</span><br><span>--- a/Transceiver52M/device/lms/LMSDevice.h</span><br><span>+++ b/Transceiver52M/device/lms/LMSDevice.h</span><br><span>@@ -21,22 +21,33 @@</span><br><span> </span><br><span> #include "radioDevice.h"</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#include <lime/LMSDevice.h></span><br><span> #include <sys/time.h></span><br><span> #include <math.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <limits.h></span><br><span> #include <string></span><br><span> #include <iostream></span><br><span style="color: hsl(120, 100%, 40%);">+#include <lime/LimeSuite.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define LIMESDR_TX_AMPL  0.3</span><br><span> </span><br><span> /** A class to handle a LimeSuite supported device */</span><br><span> class LMSDevice:public RadioDevice {</span><br><span> </span><br><span> private:</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        lms_device_t *m_lms_dev;</span><br><span style="color: hsl(0, 100%, 40%);">-        lms_stream_t m_lms_Stream_rx;</span><br><span style="color: hsl(0, 100%, 40%);">-   lms_stream_t m_lms_Stream_tx;</span><br><span style="color: hsl(120, 100%, 40%);">+ static constexpr double masterClockRate = 52.0e6;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   int sps;</span><br><span style="color: hsl(120, 100%, 40%);">+      lms_device_t *m_lms_dev;</span><br><span style="color: hsl(120, 100%, 40%);">+      std::vector<lms_stream_t> m_lms_stream_rx;</span><br><span style="color: hsl(120, 100%, 40%);">+      std::vector<lms_stream_t> m_lms_stream_tx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    std::vector<uint32_t> m_last_rx_underruns;</span><br><span style="color: hsl(120, 100%, 40%);">+      std::vector<uint32_t> m_last_rx_overruns;</span><br><span style="color: hsl(120, 100%, 40%);">+       std::vector<uint32_t> m_last_tx_underruns;</span><br><span style="color: hsl(120, 100%, 40%);">+      std::vector<uint32_t> m_last_tx_overruns;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     size_t sps, chans;</span><br><span style="color: hsl(120, 100%, 40%);">+    double actualSampleRate;        ///< the actual USRP sampling rate</span><br><span> </span><br><span>    unsigned long long samplesRead; ///< number of samples read from LMS</span><br><span>      unsigned long long samplesWritten;      ///< number of samples sent to LMS</span><br><span>@@ -44,15 +55,20 @@</span><br><span>  bool started;           ///< flag indicates LMS has started</span><br><span>       bool skipRx;            ///< set if LMS is transmit-only.</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        TIMESTAMP ts_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+  TIMESTAMP ts_initial, ts_offset;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    double rxGain;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      int get_ant_idx(const std::string & name, bool dir_tx, size_t chan);</span><br><span style="color: hsl(120, 100%, 40%);">+      bool flush_recv(size_t num_pkts);</span><br><span> </span><br><span> public:</span><br><span> </span><br><span>         /** Object constructor */</span><br><span style="color: hsl(0, 100%, 40%);">-       LMSDevice(size_t sps);</span><br><span style="color: hsl(120, 100%, 40%);">+        LMSDevice(size_t sps, size_t chans);</span><br><span> </span><br><span>     /** Instantiate the LMS */</span><br><span style="color: hsl(0, 100%, 40%);">-      int open(const std::string &, int, bool);</span><br><span style="color: hsl(120, 100%, 40%);">+ int open(const std::string &args, int ref, bool swap_channels);</span><br><span> </span><br><span>      /** Start the LMS */</span><br><span>         bool start();</span><br><span>@@ -62,7 +78,9 @@</span><br><span> </span><br><span>        /** Set priority not supported */</span><br><span>    void setPriority(float prio = 0.5) {</span><br><span style="color: hsl(0, 100%, 40%);">-    } enum TxWindowType getWindowType() {</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   enum TxWindowType getWindowType() {</span><br><span>          return TX_WINDOW_LMS1;</span><br><span>       }</span><br><span> </span><br><span>@@ -103,22 +121,22 @@</span><br><span> </span><br><span>    /** Returns the starting write Timestamp*/</span><br><span>   TIMESTAMP initialWriteTimestamp(void) {</span><br><span style="color: hsl(0, 100%, 40%);">-         return 20000;</span><br><span style="color: hsl(120, 100%, 40%);">+         return ts_initial;</span><br><span>   }</span><br><span> </span><br><span>        /** Returns the starting read Timestamp*/</span><br><span>    TIMESTAMP initialReadTimestamp(void) {</span><br><span style="color: hsl(0, 100%, 40%);">-          return 20000;</span><br><span style="color: hsl(120, 100%, 40%);">+         return ts_initial;</span><br><span>   }</span><br><span> </span><br><span>        /** returns the full-scale transmit amplitude **/</span><br><span>    double fullScaleInputValue() {</span><br><span style="color: hsl(0, 100%, 40%);">-          return 13500.0;</span><br><span style="color: hsl(120, 100%, 40%);">+               return(double) SHRT_MAX * LIMESDR_TX_AMPL;</span><br><span>   }</span><br><span> </span><br><span>        /** returns the full-scale receive amplitude **/</span><br><span>     double fullScaleOutputValue() {</span><br><span style="color: hsl(0, 100%, 40%);">-         return 9450.0;</span><br><span style="color: hsl(120, 100%, 40%);">+                return (double) SHRT_MAX;</span><br><span>    }</span><br><span> </span><br><span>        /** sets the receive chan gain, returns the gain setting **/</span><br><span>@@ -156,6 +174,12 @@</span><br><span>  /* return the used RX path */</span><br><span>        std::string getTxAntenna(size_t chan = 0);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+        /** return whether user drives synchronization of Tx/Rx of USRP */</span><br><span style="color: hsl(120, 100%, 40%);">+        bool requiresRadioAlign();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /** return whether user drives synchronization of Tx/Rx of USRP */</span><br><span style="color: hsl(120, 100%, 40%);">+        virtual GSM::Time minLatency();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      /** Return internal status values */</span><br><span>         inline double getTxFreq(size_t chan = 0) {</span><br><span>           return 0;</span><br><span>diff --git a/Transceiver52M/device/radioDevice.h b/Transceiver52M/device/radioDevice.h</span><br><span>index 44636d5..c5cd461 100644</span><br><span>--- a/Transceiver52M/device/radioDevice.h</span><br><span>+++ b/Transceiver52M/device/radioDevice.h</span><br><span>@@ -39,7 +39,7 @@</span><br><span> </span><br><span>   public:</span><br><span>   /* Available transport bus types */</span><br><span style="color: hsl(0, 100%, 40%);">-  enum TxWindowType { TX_WINDOW_USRP1, TX_WINDOW_FIXED };</span><br><span style="color: hsl(120, 100%, 40%);">+  enum TxWindowType { TX_WINDOW_USRP1, TX_WINDOW_FIXED, TX_WINDOW_LMS1 };</span><br><span> </span><br><span>   /* Radio interface types */</span><br><span>   enum InterfaceType {</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/9600">change 9600</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/9600"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-trx </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Ib2fca81b76d027b08e2891056fa076d071597783 </div>
<div style="display:none"> Gerrit-Change-Number: 9600 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Pau Espin Pedrol <pespin@sysmocom.de> </div>