aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CommonLibs/trx_vty.c2
-rw-r--r--CommonLibs/trx_vty.h1
-rw-r--r--Transceiver52M/device/lms/LMSDevice.cpp131
-rw-r--r--Transceiver52M/device/lms/LMSDevice.h11
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 <stdint.h>
#include <string.h>
#include <stdlib.h>
+
+#include <map>
+
+#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<enum lms_dev_type, struct dev_desc> 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<enum lms_dev_type, struct dev_desc>::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<std::string>& tx_paths,
const std::vector<std::string>& 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<chans; i++) {
@@ -342,6 +388,43 @@ bool LMSDevice::stop()
return true;
}
+bool LMSDevice::do_clock_src_freq(enum ReferenceType ref, double freq)
+{
+ struct dev_desc dev_desc = dev_param_map.at(m_dev_type);
+ size_t lms_clk_id;
+
+ switch (ref) {
+ case REF_EXTERNAL:
+ lms_clk_id = LMS_CLOCK_EXTREF;
+ break;
+ case REF_INTERNAL:
+ if (!dev_desc.clock_src_int_usable) {
+ LOGC(DDEV, ERROR) << "Device type " << dev_desc.name_prefix
+ << " doesn't support internal reference clock";
+ return false;
+ }
+ /* According to lms using LMS_CLOCK_EXTREF with a
+ frequency <= 0 is the correct way to set clock to
+ internal reference */
+ lms_clk_id = LMS_CLOCK_EXTREF;
+ freq = -1;
+ break;
+ default:
+ LOGC(DDEV, ERROR) << "Invalid reference type " << get_value_string(clock_ref_names, ref);
+ return false;
+ }
+
+ if (dev_desc.clock_src_switchable) {
+ if (LMS_SetClockFreq(m_lms_dev, lms_clk_id, freq) < 0)
+ return false;
+ } else {
+ LOGC(DDEV, INFO) << "Device type " << dev_desc.name_prefix
+ << " doesn't support switching clock source through SW";
+ }
+
+ return true;
+}
+
/* do rx/tx calibration - depends on gain, freq and bw */
bool LMSDevice::do_calib(size_t chan)
{
@@ -383,7 +466,7 @@ bool LMSDevice::do_filters(size_t chan)
double LMSDevice::maxTxGain()
{
- return maxTxGainClamp;
+ return dev_param_map.at(m_dev_type).max_tx_gain;
}
double LMSDevice::minTxGain()
diff --git a/Transceiver52M/device/lms/LMSDevice.h b/Transceiver52M/device/lms/LMSDevice.h
index cdba72c..755f6c4 100644
--- a/Transceiver52M/device/lms/LMSDevice.h
+++ b/Transceiver52M/device/lms/LMSDevice.h
@@ -41,6 +41,13 @@
* A^2 = 1 */
#define LIMESDR_TX_AMPL 0.707
+enum lms_dev_type {
+ LMS_DEV_SDR_USB, /* LimeSDR-USB */
+ LMS_DEV_SDR_MINI, /* LimeSDR-Mini */
+ LMS_DEV_NET_MICRO, /* LimeNet-micro */
+ LMS_DEV_UNKNOWN,
+};
+
/** A class to handle a LimeSuite supported device */
class LMSDevice:public RadioDevice {
@@ -59,7 +66,8 @@ private:
TIMESTAMP ts_initial, ts_offset;
std::vector<double> 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: