diff --git a/CommonLibs/trx_vty.c b/CommonLibs/trx_vty.c index 44e1d310..3f875f5c 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 d20dd964..c0d54cf7 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 8ad338b1..1ef7728a 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: