<p>pespin <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-trx/+/16876">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  laforge: Looks good to me, but someone else must approve
  fixeria: Looks good to me, but someone else must approve
  pespin: Looks good to me, approved
  Jenkins Builder: Verified

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">lms: Store device type specific parameters in one place<br><br>Add an enum containing each supported device type (LimeSDR-USB,<br>LimeSDR-Mini and LimeNet-Micro) plus "unknown", to leave some room for<br>yet-to-come devices to run with some generic parameters without<br>rebuilding osmo-trx.<br><br>Each device type is assigned a dev_desc structure, and all of them are<br>put in HashMap, similar to what's already done in UHDDevice.cpp.<br><br>Device type is infered from string provided by LMS_GetDeviceInfo(), as<br>it was already done before in several places. From now on, we only need<br>to parse the string once since we store the device type after first<br>during open time.<br><br>Later on, more fields will be moved to device-type specific structure,<br>such as Tx timing offset, clock rate, etc.<br><br>Change-Id: I7658615787c5bc41c365bab9c11733b701ac2ae5<br>---<br>M CommonLibs/trx_vty.c<br>M CommonLibs/trx_vty.h<br>M Transceiver52M/device/lms/LMSDevice.cpp<br>M Transceiver52M/device/lms/LMSDevice.h<br>4 files changed, 119 insertions(+), 26 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/CommonLibs/trx_vty.c b/CommonLibs/trx_vty.c</span><br><span>index 44e1d31..3f875f5 100644</span><br><span>--- a/CommonLibs/trx_vty.c</span><br><span>+++ b/CommonLibs/trx_vty.c</span><br><span>@@ -42,7 +42,7 @@</span><br><span> </span><br><span> static struct trx_ctx* g_trx_ctx;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static const struct value_string clock_ref_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+const struct value_string clock_ref_names[] = {</span><br><span>     { REF_INTERNAL, "internal" },</span><br><span>      { REF_EXTERNAL, "external" },</span><br><span>      { REF_GPS,      "gpsdo" },</span><br><span>diff --git a/CommonLibs/trx_vty.h b/CommonLibs/trx_vty.h</span><br><span>index d20dd96..c0d54cf 100644</span><br><span>--- a/CommonLibs/trx_vty.h</span><br><span>+++ b/CommonLibs/trx_vty.h</span><br><span>@@ -5,6 +5,7 @@</span><br><span> #include "config_defs.h"</span><br><span> </span><br><span> extern struct vty_app_info g_vty_info;</span><br><span style="color: hsl(120, 100%, 40%);">+extern const struct value_string clock_ref_names[];</span><br><span> extern const struct value_string filler_names[];</span><br><span> </span><br><span> /* Maximum number of physical RF channels */</span><br><span>diff --git a/Transceiver52M/device/lms/LMSDevice.cpp b/Transceiver52M/device/lms/LMSDevice.cpp</span><br><span>index 8ad338b..1ef7728 100644</span><br><span>--- a/Transceiver52M/device/lms/LMSDevice.cpp</span><br><span>+++ b/Transceiver52M/device/lms/LMSDevice.cpp</span><br><span>@@ -20,6 +20,10 @@</span><br><span> #include <stdint.h></span><br><span> #include <string.h></span><br><span> #include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <map></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "trx_vty.h"</span><br><span> #include "Logger.h"</span><br><span> #include "Threads.h"</span><br><span> #include "LMSDevice.h"</span><br><span>@@ -44,11 +48,61 @@</span><br><span> #define LMS_CALIBRATE_BW_HZ OSMO_MAX(GSM_CARRIER_BW, LMS_MIN_BW_SUPPORTED)</span><br><span> #define SAMPLE_BUF_SZ    (1 << 20) /* Size of Rx timestamp based Ring buffer, in bytes */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Device Name Prefixes as presented by LimeSuite API LMS_GetDeviceInfo(): */</span><br><span style="color: hsl(120, 100%, 40%);">+#define LMS_DEV_SDR_USB_PREFIX_NAME "LimeSDR-USB"</span><br><span style="color: hsl(120, 100%, 40%);">+#define LMS_DEV_SDR_MINI_PREFIX_NAME "LimeSDR-Mini"</span><br><span style="color: hsl(120, 100%, 40%);">+#define LMS_DEV_NET_MICRO_PREFIX_NAME "LimeNET-Micro"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Device parameter descriptor */</span><br><span style="color: hsl(120, 100%, 40%);">+struct dev_desc {</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Does LimeSuite allow switching the clock source for this device?</span><br><span style="color: hsl(120, 100%, 40%);">+    * LimeSDR-Mini does not have switches but needs soldering to select</span><br><span style="color: hsl(120, 100%, 40%);">+   * external/internal clock. Any call to LMS_SetClockFreq() will fail.</span><br><span style="color: hsl(120, 100%, 40%);">+  */</span><br><span style="color: hsl(120, 100%, 40%);">+   bool clock_src_switchable;</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Does LimeSuite allow using REF_INTERNAL for this device?</span><br><span style="color: hsl(120, 100%, 40%);">+    * LimeNET-Micro does not like selecting internal clock</span><br><span style="color: hsl(120, 100%, 40%);">+        */</span><br><span style="color: hsl(120, 100%, 40%);">+   bool clock_src_int_usable;</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Device specific maximum tx levels selected by phasenoise measurements, in dB */</span><br><span style="color: hsl(120, 100%, 40%);">+    double max_tx_gain;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Device Name Prefix as presented by LimeSuite API LMS_GetDeviceInfo() */</span><br><span style="color: hsl(120, 100%, 40%);">+    std::string name_prefix;</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%);">+static const std::map<enum lms_dev_type, struct dev_desc> dev_param_map {</span><br><span style="color: hsl(120, 100%, 40%);">+       { LMS_DEV_SDR_USB,   { true,  true,  73.0, LMS_DEV_SDR_USB_PREFIX_NAME } },</span><br><span style="color: hsl(120, 100%, 40%);">+   { LMS_DEV_SDR_MINI,  { false, true,  66.0, LMS_DEV_SDR_MINI_PREFIX_NAME } },</span><br><span style="color: hsl(120, 100%, 40%);">+  { LMS_DEV_NET_MICRO, { true,  false, 71.0, LMS_DEV_NET_MICRO_PREFIX_NAME } },</span><br><span style="color: hsl(120, 100%, 40%);">+ { LMS_DEV_UNKNOWN,   { true,  true,  73.0, "UNKNOWN" } },</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%);">+static enum lms_dev_type parse_dev_type(lms_device_t *m_lms_dev)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        std::map<enum lms_dev_type, struct dev_desc>::const_iterator it = dev_param_map.begin();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      const lms_dev_info_t* device_info = LMS_GetDeviceInfo(m_lms_dev);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   while (it != dev_param_map.end())</span><br><span style="color: hsl(120, 100%, 40%);">+     {</span><br><span style="color: hsl(120, 100%, 40%);">+             enum lms_dev_type dev_type = it->first;</span><br><span style="color: hsl(120, 100%, 40%);">+            struct dev_desc desc = it->second;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               if (strncmp(device_info->deviceName, desc.name_prefix.c_str(), desc.name_prefix.length()) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  LOGC(DDEV, INFO) << "Device identified as " << desc.name_prefix;</span><br><span style="color: hsl(120, 100%, 40%);">+                        return dev_type;</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+             it++;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+     return LMS_DEV_UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> LMSDevice::LMSDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t chan_num, double lo_offset,</span><br><span>                const std::vector<std::string>& tx_paths,</span><br><span>                  const std::vector<std::string>& rx_paths):</span><br><span>    RadioDevice(tx_sps, rx_sps, iface, chan_num, lo_offset, tx_paths, rx_paths),</span><br><span style="color: hsl(0, 100%, 40%);">-    m_lms_dev(NULL), started(false)</span><br><span style="color: hsl(120, 100%, 40%);">+       m_lms_dev(NULL), started(false), m_dev_type(LMS_DEV_UNKNOWN)</span><br><span> {</span><br><span>    LOGC(DDEV, INFO) << "creating LMS device...";</span><br><span> </span><br><span>@@ -138,11 +192,11 @@</span><br><span> int LMSDevice::open(const std::string &args, int ref, bool swap_channels)</span><br><span> {</span><br><span>      lms_info_str_t* info_list;</span><br><span style="color: hsl(0, 100%, 40%);">-      const lms_dev_info_t* device_info;</span><br><span>   lms_range_t range_sr;</span><br><span>        float_type sr_host, sr_rf;</span><br><span>   unsigned int i, n;</span><br><span>   int rc, dev_id;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct dev_desc dev_desc;</span><br><span> </span><br><span>        LOGC(DDEV, INFO) << "Opening LMS device..";</span><br><span> </span><br><span>@@ -179,19 +233,20 @@</span><br><span> </span><br><span>  delete [] info_list;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        device_info = LMS_GetDeviceInfo(m_lms_dev);</span><br><span style="color: hsl(120, 100%, 40%);">+   m_dev_type = parse_dev_type(m_lms_dev);</span><br><span style="color: hsl(120, 100%, 40%);">+       dev_desc = dev_param_map.at(m_dev_type);</span><br><span> </span><br><span>         if ((ref != REF_EXTERNAL) && (ref != REF_INTERNAL)){</span><br><span>                 LOGC(DDEV, ERROR) << "Invalid reference type";</span><br><span>               goto out_close;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* if reference clock is external setup must happen _before_ calling LMS_Init */</span><br><span style="color: hsl(0, 100%, 40%);">-        /* FIXME make external reference frequency configurable */</span><br><span style="color: hsl(120, 100%, 40%);">+    /* if reference clock is external, setup must happen _before_ calling LMS_Init */</span><br><span>    if (ref == REF_EXTERNAL) {</span><br><span>           LOGC(DDEV, INFO) << "Setting External clock reference to 10MHz";</span><br><span style="color: hsl(0, 100%, 40%);">-                /* Assume an external 10 MHz reference clock */</span><br><span style="color: hsl(0, 100%, 40%);">-         if (LMS_SetClockFreq(m_lms_dev, LMS_CLOCK_EXTREF, 10000000.0) < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+         /* FIXME: Assume an external 10 MHz reference clock. make</span><br><span style="color: hsl(120, 100%, 40%);">+                external reference frequency configurable */</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!do_clock_src_freq(REF_EXTERNAL, 10000000.0))</span><br><span>                    goto out_close;</span><br><span>      }</span><br><span> </span><br><span>@@ -201,22 +256,13 @@</span><br><span>                goto out_close;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* LimeSDR-Mini does not have switches but needs soldering to select external/internal clock */</span><br><span style="color: hsl(0, 100%, 40%);">- /* LimeNET-Micro also does not like selecting internal clock*/</span><br><span style="color: hsl(0, 100%, 40%);">-  /* also set device specific maximum tx levels selected by phasenoise measurements*/</span><br><span style="color: hsl(0, 100%, 40%);">-     if (strncmp(device_info->deviceName,"LimeSDR-USB",11) == 0){</span><br><span style="color: hsl(0, 100%, 40%);">-               /* if reference clock is internal setup must happen _after_ calling LMS_Init */</span><br><span style="color: hsl(0, 100%, 40%);">-         /* according to lms using LMS_CLOCK_EXTREF with a frequency <= 0 is the correct way to set clock to internal reference*/</span><br><span style="color: hsl(0, 100%, 40%);">-             if (ref == REF_INTERNAL) {</span><br><span style="color: hsl(0, 100%, 40%);">-                      LOGC(DDEV, INFO) << "Setting Internal clock reference";</span><br><span style="color: hsl(0, 100%, 40%);">-                 if (LMS_SetClockFreq(m_lms_dev, LMS_CLOCK_EXTREF, -1) < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-                           goto out_close;</span><br><span style="color: hsl(0, 100%, 40%);">-         }</span><br><span style="color: hsl(0, 100%, 40%);">-               maxTxGainClamp = 73.0;</span><br><span style="color: hsl(0, 100%, 40%);">-  } else if (strncmp(device_info->deviceName,"LimeSDR-Mini",12) == 0)</span><br><span style="color: hsl(0, 100%, 40%);">-                maxTxGainClamp = 66.0;</span><br><span style="color: hsl(0, 100%, 40%);">-  else</span><br><span style="color: hsl(0, 100%, 40%);">-            maxTxGainClamp = 71.0; /* "LimeNET-Micro", etc FIXME pciE based LMS boards?*/</span><br><span style="color: hsl(120, 100%, 40%);">+       /* if reference clock is internal, setup must happen _after_ calling LMS_Init */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (ref == REF_INTERNAL) {</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGC(DDEV, INFO) << "Setting Internal clock reference";</span><br><span style="color: hsl(120, 100%, 40%);">+               /* Internal freq param is not used */</span><br><span style="color: hsl(120, 100%, 40%);">+         if (!do_clock_src_freq(REF_INTERNAL, 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>        /* enable all used channels */</span><br><span>       for (i=0; i<chans; i++) {</span><br><span>@@ -342,6 +388,43 @@</span><br><span>  return true;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+bool LMSDevice::do_clock_src_freq(enum ReferenceType ref, double freq)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct dev_desc dev_desc = dev_param_map.at(m_dev_type);</span><br><span style="color: hsl(120, 100%, 40%);">+      size_t lms_clk_id;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  switch (ref) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case REF_EXTERNAL:</span><br><span style="color: hsl(120, 100%, 40%);">+            lms_clk_id = LMS_CLOCK_EXTREF;</span><br><span style="color: hsl(120, 100%, 40%);">+                break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case REF_INTERNAL:</span><br><span style="color: hsl(120, 100%, 40%);">+            if (!dev_desc.clock_src_int_usable) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 LOGC(DDEV, ERROR) << "Device type " << dev_desc.name_prefix</span><br><span style="color: hsl(120, 100%, 40%);">+                                       << " doesn't support internal reference clock";</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%);">+             /* According to lms using LMS_CLOCK_EXTREF with a</span><br><span style="color: hsl(120, 100%, 40%);">+                frequency <= 0 is the correct way to set clock to</span><br><span style="color: hsl(120, 100%, 40%);">+                  internal reference */</span><br><span style="color: hsl(120, 100%, 40%);">+              lms_clk_id = LMS_CLOCK_EXTREF;</span><br><span style="color: hsl(120, 100%, 40%);">+                freq = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGC(DDEV, ERROR) << "Invalid reference type " << get_value_string(clock_ref_names, ref);</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%);">+   if (dev_desc.clock_src_switchable) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (LMS_SetClockFreq(m_lms_dev, lms_clk_id, freq) < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                     return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              LOGC(DDEV, INFO) << "Device type " << dev_desc.name_prefix</span><br><span style="color: hsl(120, 100%, 40%);">+                               << " doesn't support switching clock source through SW";</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%);">+   return true;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* do rx/tx calibration - depends on gain, freq and bw */</span><br><span> bool LMSDevice::do_calib(size_t chan)</span><br><span> {</span><br><span>@@ -383,7 +466,7 @@</span><br><span> </span><br><span> double LMSDevice::maxTxGain()</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-    return maxTxGainClamp;</span><br><span style="color: hsl(120, 100%, 40%);">+        return dev_param_map.at(m_dev_type).max_tx_gain;</span><br><span> }</span><br><span> </span><br><span> double LMSDevice::minTxGain()</span><br><span>diff --git a/Transceiver52M/device/lms/LMSDevice.h b/Transceiver52M/device/lms/LMSDevice.h</span><br><span>index cdba72c..755f6c4 100644</span><br><span>--- a/Transceiver52M/device/lms/LMSDevice.h</span><br><span>+++ b/Transceiver52M/device/lms/LMSDevice.h</span><br><span>@@ -41,6 +41,13 @@</span><br><span>  *  A^2 = 1 */</span><br><span> #define LIMESDR_TX_AMPL  0.707</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+enum lms_dev_type {</span><br><span style="color: hsl(120, 100%, 40%);">+ LMS_DEV_SDR_USB,   /* LimeSDR-USB */</span><br><span style="color: hsl(120, 100%, 40%);">+  LMS_DEV_SDR_MINI,  /* LimeSDR-Mini */</span><br><span style="color: hsl(120, 100%, 40%);">+ LMS_DEV_NET_MICRO, /* LimeNet-micro */</span><br><span style="color: hsl(120, 100%, 40%);">+        LMS_DEV_UNKNOWN,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /** A class to handle a LimeSuite supported device */</span><br><span> class LMSDevice:public RadioDevice {</span><br><span> </span><br><span>@@ -59,7 +66,8 @@</span><br><span>      TIMESTAMP ts_initial, ts_offset;</span><br><span> </span><br><span>         std::vector<double> tx_gains, rx_gains;</span><br><span style="color: hsl(0, 100%, 40%);">-   double maxTxGainClamp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      enum lms_dev_type m_dev_type;</span><br><span> </span><br><span>    bool do_calib(size_t chan);</span><br><span>  bool do_filters(size_t chan);</span><br><span>@@ -68,6 +76,7 @@</span><br><span>    bool flush_recv(size_t num_pkts);</span><br><span>    void update_stream_stats_rx(size_t chan, bool *overrun);</span><br><span>     void update_stream_stats_tx(size_t chan, bool *underrun);</span><br><span style="color: hsl(120, 100%, 40%);">+     bool do_clock_src_freq(enum ReferenceType ref, double freq);</span><br><span> </span><br><span> public:</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-trx/+/16876">change 16876</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/osmo-trx/+/16876"/><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-Change-Id: I7658615787c5bc41c365bab9c11733b701ac2ae5 </div>
<div style="display:none"> Gerrit-Change-Number: 16876 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: fixeria <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>