From a7bf6cd8a41c62c95959298978e86f324a8e140f Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Tue, 14 Jan 2020 17:52:15 +0100 Subject: lms: Store device type specific parameters in one place Add an enum containing each supported device type (LimeSDR-USB, LimeSDR-Mini and LimeNet-Micro) plus "unknown", to leave some room for yet-to-come devices to run with some generic parameters without rebuilding osmo-trx. Each device type is assigned a dev_desc structure, and all of them are put in HashMap, similar to what's already done in UHDDevice.cpp. Device type is infered from string provided by LMS_GetDeviceInfo(), as it was already done before in several places. From now on, we only need to parse the string once since we store the device type after first during open time. Later on, more fields will be moved to device-type specific structure, such as Tx timing offset, clock rate, etc. Change-Id: I7658615787c5bc41c365bab9c11733b701ac2ae5 --- CommonLibs/trx_vty.c | 2 +- CommonLibs/trx_vty.h | 1 + Transceiver52M/device/lms/LMSDevice.cpp | 131 ++++++++++++++++++++++++++------ Transceiver52M/device/lms/LMSDevice.h | 11 ++- 4 files changed, 119 insertions(+), 26 deletions(-) diff --git a/CommonLibs/trx_vty.c b/CommonLibs/trx_vty.c index 44e1d31..3f875f5 100644 --- a/CommonLibs/trx_vty.c +++ b/CommonLibs/trx_vty.c @@ -42,7 +42,7 @@ static struct trx_ctx* g_trx_ctx; -static const struct value_string clock_ref_names[] = { +const struct value_string clock_ref_names[] = { { REF_INTERNAL, "internal" }, { REF_EXTERNAL, "external" }, { REF_GPS, "gpsdo" }, diff --git a/CommonLibs/trx_vty.h b/CommonLibs/trx_vty.h index d20dd96..c0d54cf 100644 --- a/CommonLibs/trx_vty.h +++ b/CommonLibs/trx_vty.h @@ -5,6 +5,7 @@ #include "config_defs.h" extern struct vty_app_info g_vty_info; +extern const struct value_string clock_ref_names[]; extern const struct value_string filler_names[]; /* Maximum number of physical RF channels */ diff --git a/Transceiver52M/device/lms/LMSDevice.cpp b/Transceiver52M/device/lms/LMSDevice.cpp index 8ad338b..1ef7728 100644 --- a/Transceiver52M/device/lms/LMSDevice.cpp +++ b/Transceiver52M/device/lms/LMSDevice.cpp @@ -20,6 +20,10 @@ #include #include #include + +#include + +#include "trx_vty.h" #include "Logger.h" #include "Threads.h" #include "LMSDevice.h" @@ -44,11 +48,61 @@ using namespace std; #define LMS_CALIBRATE_BW_HZ OSMO_MAX(GSM_CARRIER_BW, LMS_MIN_BW_SUPPORTED) #define SAMPLE_BUF_SZ (1 << 20) /* Size of Rx timestamp based Ring buffer, in bytes */ + +/* Device Name Prefixes as presented by LimeSuite API LMS_GetDeviceInfo(): */ +#define LMS_DEV_SDR_USB_PREFIX_NAME "LimeSDR-USB" +#define LMS_DEV_SDR_MINI_PREFIX_NAME "LimeSDR-Mini" +#define LMS_DEV_NET_MICRO_PREFIX_NAME "LimeNET-Micro" + +/* Device parameter descriptor */ +struct dev_desc { + /* Does LimeSuite allow switching the clock source for this device? + * LimeSDR-Mini does not have switches but needs soldering to select + * external/internal clock. Any call to LMS_SetClockFreq() will fail. + */ + bool clock_src_switchable; + /* Does LimeSuite allow using REF_INTERNAL for this device? + * LimeNET-Micro does not like selecting internal clock + */ + bool clock_src_int_usable; + /* Device specific maximum tx levels selected by phasenoise measurements, in dB */ + double max_tx_gain; + /* Device Name Prefix as presented by LimeSuite API LMS_GetDeviceInfo() */ + std::string name_prefix; +}; + +static const std::map dev_param_map { + { LMS_DEV_SDR_USB, { true, true, 73.0, LMS_DEV_SDR_USB_PREFIX_NAME } }, + { LMS_DEV_SDR_MINI, { false, true, 66.0, LMS_DEV_SDR_MINI_PREFIX_NAME } }, + { LMS_DEV_NET_MICRO, { true, false, 71.0, LMS_DEV_NET_MICRO_PREFIX_NAME } }, + { LMS_DEV_UNKNOWN, { true, true, 73.0, "UNKNOWN" } }, +}; + +static enum lms_dev_type parse_dev_type(lms_device_t *m_lms_dev) +{ + std::map::const_iterator it = dev_param_map.begin(); + + const lms_dev_info_t* device_info = LMS_GetDeviceInfo(m_lms_dev); + + while (it != dev_param_map.end()) + { + enum lms_dev_type dev_type = it->first; + struct dev_desc desc = it->second; + + if (strncmp(device_info->deviceName, desc.name_prefix.c_str(), desc.name_prefix.length()) == 0) { + LOGC(DDEV, INFO) << "Device identified as " << desc.name_prefix; + return dev_type; + } + it++; + } + return LMS_DEV_UNKNOWN; +} + LMSDevice::LMSDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t chan_num, double lo_offset, const std::vector& tx_paths, const std::vector& rx_paths): RadioDevice(tx_sps, rx_sps, iface, chan_num, lo_offset, tx_paths, rx_paths), - m_lms_dev(NULL), started(false) + m_lms_dev(NULL), started(false), m_dev_type(LMS_DEV_UNKNOWN) { LOGC(DDEV, INFO) << "creating LMS device..."; @@ -138,11 +192,11 @@ int info_list_find(lms_info_str_t* info_list, unsigned int count, const std::str int LMSDevice::open(const std::string &args, int ref, bool swap_channels) { lms_info_str_t* info_list; - const lms_dev_info_t* device_info; lms_range_t range_sr; float_type sr_host, sr_rf; unsigned int i, n; int rc, dev_id; + struct dev_desc dev_desc; LOGC(DDEV, INFO) << "Opening LMS device.."; @@ -179,19 +233,20 @@ int LMSDevice::open(const std::string &args, int ref, bool swap_channels) delete [] info_list; - device_info = LMS_GetDeviceInfo(m_lms_dev); + m_dev_type = parse_dev_type(m_lms_dev); + dev_desc = dev_param_map.at(m_dev_type); if ((ref != REF_EXTERNAL) && (ref != REF_INTERNAL)){ LOGC(DDEV, ERROR) << "Invalid reference type"; goto out_close; } - /* if reference clock is external setup must happen _before_ calling LMS_Init */ - /* FIXME make external reference frequency configurable */ + /* if reference clock is external, setup must happen _before_ calling LMS_Init */ if (ref == REF_EXTERNAL) { LOGC(DDEV, INFO) << "Setting External clock reference to 10MHz"; - /* Assume an external 10 MHz reference clock */ - if (LMS_SetClockFreq(m_lms_dev, LMS_CLOCK_EXTREF, 10000000.0) < 0) + /* FIXME: Assume an external 10 MHz reference clock. make + external reference frequency configurable */ + if (!do_clock_src_freq(REF_EXTERNAL, 10000000.0)) goto out_close; } @@ -201,22 +256,13 @@ int LMSDevice::open(const std::string &args, int ref, bool swap_channels) goto out_close; } - /* LimeSDR-Mini does not have switches but needs soldering to select external/internal clock */ - /* LimeNET-Micro also does not like selecting internal clock*/ - /* also set device specific maximum tx levels selected by phasenoise measurements*/ - if (strncmp(device_info->deviceName,"LimeSDR-USB",11) == 0){ - /* if reference clock is internal setup must happen _after_ calling LMS_Init */ - /* according to lms using LMS_CLOCK_EXTREF with a frequency <= 0 is the correct way to set clock to internal reference*/ - if (ref == REF_INTERNAL) { - LOGC(DDEV, INFO) << "Setting Internal clock reference"; - if (LMS_SetClockFreq(m_lms_dev, LMS_CLOCK_EXTREF, -1) < 0) - goto out_close; - } - maxTxGainClamp = 73.0; - } else if (strncmp(device_info->deviceName,"LimeSDR-Mini",12) == 0) - maxTxGainClamp = 66.0; - else - maxTxGainClamp = 71.0; /* "LimeNET-Micro", etc FIXME pciE based LMS boards?*/ + /* if reference clock is internal, setup must happen _after_ calling LMS_Init */ + if (ref == REF_INTERNAL) { + LOGC(DDEV, INFO) << "Setting Internal clock reference"; + /* Internal freq param is not used */ + if (!do_clock_src_freq(REF_INTERNAL, 0)) + goto out_close; + } /* enable all used channels */ for (i=0; i tx_gains, rx_gains; - double maxTxGainClamp; + + enum lms_dev_type m_dev_type; bool do_calib(size_t chan); bool do_filters(size_t chan); @@ -68,6 +76,7 @@ private: bool flush_recv(size_t num_pkts); void update_stream_stats_rx(size_t chan, bool *overrun); void update_stream_stats_tx(size_t chan, bool *underrun); + bool do_clock_src_freq(enum ReferenceType ref, double freq); public: -- cgit v1.2.3-59-g8ed1b