aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric <ewild@sysmocom.de>2023-05-12 13:00:14 +0200
committerEric <ewild@sysmocom.de>2023-07-25 18:25:49 +0200
commitc0f78a37ed6fcb900c232eeba41f22f2dffa48d1 (patch)
tree521ab93b0038f0f4d218a1f8e50d8323cea5e8aa
parent19e134a626abdb99435d96b0bfcc46b0804715e5 (diff)
devices: unify band handling
This is basically common, but optional code. Change-Id: I64f5a462451e967d4750d8e4f1d5832cbab41cff
-rw-r--r--Transceiver52M/device/bladerf/bladerf.cpp99
-rw-r--r--Transceiver52M/device/bladerf/bladerf.h26
-rw-r--r--Transceiver52M/device/common/Makefile.am2
-rw-r--r--Transceiver52M/device/common/bandmanager.h133
-rw-r--r--Transceiver52M/device/lms/LMSDevice.cpp121
-rw-r--r--Transceiver52M/device/lms/LMSDevice.h37
-rw-r--r--Transceiver52M/device/uhd/UHDDevice.cpp116
-rw-r--r--Transceiver52M/device/uhd/UHDDevice.h23
8 files changed, 231 insertions, 326 deletions
diff --git a/Transceiver52M/device/bladerf/bladerf.cpp b/Transceiver52M/device/bladerf/bladerf.cpp
index 3d9aab9..3e830b1 100644
--- a/Transceiver52M/device/bladerf/bladerf.cpp
+++ b/Transceiver52M/device/bladerf/bladerf.cpp
@@ -47,25 +47,11 @@ extern "C" {
LOGC(DDEV, ERROR) << bladerf_strerror(status); \
}
-/* Device Type, Tx-SPS, Rx-SPS */
-typedef std::tuple<blade_dev_type, int, int> dev_key;
-
-/* Device parameter descriptor */
-struct dev_desc {
- unsigned channels;
- double mcr;
- double rate;
- double offset;
- std::string str;
-};
-
-static const std::map<dev_key, dev_desc> dev_param_map{
+static const dev_map_t dev_param_map{
{ std::make_tuple(blade_dev_type::BLADE2, 4, 4), { 1, 26e6, GSMRATE, B2XX_TIMING_4_4SPS, "B200 4 SPS" } },
};
-typedef std::tuple<blade_dev_type, enum gsm_band> dev_band_key;
-typedef std::map<dev_band_key, dev_band_desc>::const_iterator dev_band_map_it;
-static const std::map<dev_band_key, dev_band_desc> dev_band_nom_power_param_map{
+static const power_map_t dev_band_nom_power_param_map{
{ std::make_tuple(blade_dev_type::BLADE2, GSM_BAND_850), { 89.75, 13.3, -7.5 } },
{ std::make_tuple(blade_dev_type::BLADE2, GSM_BAND_900), { 89.75, 13.3, -7.5 } },
{ std::make_tuple(blade_dev_type::BLADE2, GSM_BAND_1800), { 89.75, 7.5, -11.0 } },
@@ -85,9 +71,9 @@ static double TxPower2TxGain(const dev_band_desc &desc, double tx_power_dbm)
}
blade_device::blade_device(InterfaceType iface, const struct trx_cfg *cfg)
- : RadioDevice(iface, cfg), dev(nullptr), rx_gain_min(0.0), rx_gain_max(0.0), band_ass_curr_sess(false),
- band((enum gsm_band)0), tx_spp(0), rx_spp(0), started(false), aligned(false), drop_cnt(0), prev_ts(0),
- ts_initial(0), ts_offset(0), async_event_thrd(NULL)
+ : RadioDevice(iface, cfg), band_manager(dev_band_nom_power_param_map, dev_param_map), dev(nullptr),
+ rx_gain_min(0.0), rx_gain_max(0.0), tx_spp(0), rx_spp(0), started(false), aligned(false), drop_cnt(0),
+ prev_ts(0), ts_initial(0), ts_offset(0), async_event_thrd(NULL)
{
}
@@ -104,47 +90,6 @@ blade_device::~blade_device()
delete rx_buffers[i];
}
-void blade_device::assign_band_desc(enum gsm_band req_band)
-{
- dev_band_map_it it;
-
- it = dev_band_nom_power_param_map.find(dev_band_key(dev_type, req_band));
- if (it == dev_band_nom_power_param_map.end()) {
- dev_desc desc = dev_param_map.at(dev_key(dev_type, tx_sps, rx_sps));
- LOGC(DDEV, ERROR) << "No Power parameters exist for device " << desc.str << " on band "
- << gsm_band_name(req_band) << ", using B210 ones as fallback";
- it = dev_band_nom_power_param_map.find(dev_band_key(blade_dev_type::BLADE2, req_band));
- }
- OSMO_ASSERT(it != dev_band_nom_power_param_map.end())
- band_desc = it->second;
-}
-
-bool blade_device::set_band(enum gsm_band req_band)
-{
- if (band_ass_curr_sess && req_band != band) {
- LOGC(DDEV, ALERT) << "Requesting band " << gsm_band_name(req_band) << " different from previous band "
- << gsm_band_name(band);
- return false;
- }
-
- if (req_band != band) {
- band = req_band;
- assign_band_desc(band);
- }
- band_ass_curr_sess = true;
- return true;
-}
-
-void blade_device::get_dev_band_desc(dev_band_desc &desc)
-{
- if (band == 0) {
- LOGC(DDEV, ERROR)
- << "Power parameters requested before Tx Frequency was set! Providing band 900 by default...";
- assign_band_desc(GSM_BAND_900);
- }
- desc = band_desc;
-}
-
void blade_device::init_gains()
{
double tx_gain_min, tx_gain_max;
@@ -457,7 +402,7 @@ bool blade_device::stop()
for (size_t i = 0; i < rx_buffers.size(); i++)
rx_buffers[i]->reset();
- band_ass_curr_sess = false;
+ band_reset();
started = false;
return true;
@@ -580,27 +525,13 @@ bool blade_device::set_freq(double freq, size_t chan, bool tx)
bool blade_device::setTxFreq(double wFreq, size_t chan)
{
- uint16_t req_arfcn;
- enum gsm_band req_band;
-
if (chan >= tx_freqs.size()) {
LOGC(DDEV, ALERT) << "Requested non-existent channel " << chan;
return false;
}
ScopedLock lock(tune_lock);
- req_arfcn = gsm_freq102arfcn(wFreq / 1000 / 100, 0);
- if (req_arfcn == 0xffff) {
- LOGCHAN(chan, DDEV, ALERT) << "Unknown ARFCN for Tx Frequency " << wFreq / 1000 << " kHz";
- return false;
- }
- if (gsm_arfcn2band_rc(req_arfcn, &req_band) < 0) {
- LOGCHAN(chan, DDEV, ALERT)
- << "Unknown GSM band for Tx Frequency " << wFreq << " Hz (ARFCN " << req_arfcn << " )";
- return false;
- }
-
- if (!set_band(req_band))
+ if (!update_band_from_freq(wFreq, chan, true))
return false;
if (!set_freq(wFreq, chan, true))
@@ -611,27 +542,13 @@ bool blade_device::setTxFreq(double wFreq, size_t chan)
bool blade_device::setRxFreq(double wFreq, size_t chan)
{
- uint16_t req_arfcn;
- enum gsm_band req_band;
-
if (chan >= rx_freqs.size()) {
LOGC(DDEV, ALERT) << "Requested non-existent channel " << chan;
return false;
}
ScopedLock lock(tune_lock);
- req_arfcn = gsm_freq102arfcn(wFreq / 1000 / 100, 1);
- if (req_arfcn == 0xffff) {
- LOGCHAN(chan, DDEV, ALERT) << "Unknown ARFCN for Rx Frequency " << wFreq / 1000 << " kHz";
- return false;
- }
- if (gsm_arfcn2band_rc(req_arfcn, &req_band) < 0) {
- LOGCHAN(chan, DDEV, ALERT)
- << "Unknown GSM band for Rx Frequency " << wFreq << " Hz (ARFCN " << req_arfcn << " )";
- return false;
- }
-
- if (!set_band(req_band))
+ if (!update_band_from_freq(wFreq, chan, false))
return false;
return set_freq(wFreq, chan, false);
diff --git a/Transceiver52M/device/bladerf/bladerf.h b/Transceiver52M/device/bladerf/bladerf.h
index 4db2569..e32581e 100644
--- a/Transceiver52M/device/bladerf/bladerf.h
+++ b/Transceiver52M/device/bladerf/bladerf.h
@@ -22,10 +22,12 @@
#pragma once
+#include <map>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#include "bandmanager.h"
#include "radioDevice.h"
#include "smpl_buf.h"
@@ -33,8 +35,6 @@ extern "C" {
#include <osmocom/gsm/gsm_utils.h>
}
-#include <bladerf.h>
-
enum class blade_dev_type { BLADE1, BLADE2 };
struct dev_band_desc {
@@ -52,7 +52,21 @@ struct dev_band_desc {
double rxgain2rssioffset_rel; /* dB */
};
-class blade_device : public RadioDevice {
+/* Device parameter descriptor */
+struct dev_desc {
+ unsigned channels;
+ double mcr;
+ double rate;
+ double offset;
+ std::string desc_str;
+};
+
+using dev_key = std::tuple<blade_dev_type, int, int>;
+using dev_band_key = std::tuple<blade_dev_type, enum gsm_band>;
+using power_map_t = std::map<dev_band_key, dev_band_desc>;
+using dev_map_t = std::map<dev_key, dev_desc>;
+
+class blade_device : public RadioDevice, public band_manager<power_map_t, dev_map_t> {
public:
blade_device(InterfaceType iface, const struct trx_cfg *cfg);
~blade_device();
@@ -153,9 +167,6 @@ class blade_device : public RadioDevice {
std::vector<double> tx_gains, rx_gains;
std::vector<double> tx_freqs, rx_freqs;
- bool band_ass_curr_sess; /* true if "band" was set after last POWEROFF */
- enum gsm_band band;
- struct dev_band_desc band_desc;
size_t tx_spp, rx_spp;
bool started;
@@ -178,9 +189,6 @@ class blade_device : public RadioDevice {
bool flush_recv(size_t num_pkts);
bool set_freq(double freq, size_t chan, bool tx);
- void get_dev_band_desc(dev_band_desc &desc);
- bool set_band(enum gsm_band req_band);
- void assign_band_desc(enum gsm_band req_band);
Thread *async_event_thrd;
Mutex tune_lock;
diff --git a/Transceiver52M/device/common/Makefile.am b/Transceiver52M/device/common/Makefile.am
index 4d29e98..1a33592 100644
--- a/Transceiver52M/device/common/Makefile.am
+++ b/Transceiver52M/device/common/Makefile.am
@@ -4,7 +4,7 @@ AM_CPPFLAGS = -Wall $(STD_DEFINES_AND_INCLUDES)
AM_CXXFLAGS = -lpthread $(LIBOSMOCORE_CFLAGS)
-noinst_HEADERS = radioDevice.h smpl_buf.h
+noinst_HEADERS = radioDevice.h smpl_buf.h bandmanager.h
noinst_LTLIBRARIES = libdevice_common.la
diff --git a/Transceiver52M/device/common/bandmanager.h b/Transceiver52M/device/common/bandmanager.h
new file mode 100644
index 0000000..a198937
--- /dev/null
+++ b/Transceiver52M/device/common/bandmanager.h
@@ -0,0 +1,133 @@
+#pragma once
+/*
+ * (C) 2022 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Eric Wild <ewild@sysmocom.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <string>
+#include <tuple>
+
+#include "Logger.h"
+
+extern "C" {
+#include <osmocom/gsm/gsm_utils.h>
+}
+
+template <typename powermapt, typename devmapt>
+class band_manager {
+ using powerkeyt = typename powermapt::key_type;
+ using powermappedt = typename powermapt::mapped_type;
+ using devkeyt = typename devmapt::key_type;
+ const devkeyt &m_dev_type;
+ const powermapt &m_power_map;
+ const devmapt &m_dev_map;
+ powerkeyt m_fallback;
+ enum gsm_band m_band;
+ powermappedt m_band_desc;
+ bool band_ass_curr_sess{}; /* true if "band" was set after last POWEROFF */
+
+ // looks up either first tuple element (->enum) or straight enum
+ template <typename T, typename std::enable_if<std::is_enum<T>::value>::type *dummy = nullptr>
+ auto key_helper(T &t) -> T
+ {
+ return t;
+ }
+
+ template <typename T>
+ auto key_helper(T t) -> typename std::tuple_element<0, T>::type
+ {
+ return std::get<0>(t);
+ }
+
+ void assign_band_desc(enum gsm_band req_band)
+ {
+ auto key = key_helper(m_dev_type);
+ auto fallback_key = key_helper(m_fallback);
+ auto it = m_power_map.find({ key, req_band });
+ if (it == m_power_map.end()) {
+ auto desc = m_dev_map.at(m_dev_type);
+ LOGC(DDEV, ERROR) << "No Tx Power measurements exist for device " << desc.desc_str
+ << " on band " << gsm_band_name(req_band) << ", using fallback..";
+ it = m_power_map.find({ fallback_key, req_band });
+ }
+ OSMO_ASSERT(it != m_power_map.end());
+ m_band_desc = it->second;
+ }
+
+ bool set_band(enum gsm_band req_band)
+ {
+ if (band_ass_curr_sess && req_band != m_band) {
+ LOGC(DDEV, ALERT) << "Requesting band " << gsm_band_name(req_band)
+ << " different from previous band " << gsm_band_name(m_band);
+ return false;
+ }
+
+ if (req_band != m_band) {
+ m_band = req_band;
+ assign_band_desc(m_band);
+ }
+ band_ass_curr_sess = true;
+ return true;
+ }
+
+ public:
+ band_manager(const devkeyt &dev_type, const powermapt &power_map, const devmapt &dev_map, powerkeyt fallback)
+ : m_dev_type(dev_type), m_power_map(power_map), m_dev_map(dev_map), m_fallback(fallback),
+ m_band((enum gsm_band)0)
+ {
+ }
+ band_manager(const powermapt &power_map, const devmapt &dev_map)
+ : m_dev_type(dev_map.begin()->first), m_power_map(power_map), m_dev_map(dev_map),
+ m_fallback(m_power_map.begin()->first), m_band((enum gsm_band)0)
+ {
+ }
+ void band_reset()
+ {
+ band_ass_curr_sess = false;
+ }
+
+ void get_dev_band_desc(powermappedt &desc)
+ {
+ if (m_band == 0) {
+ LOGC(DDEV, ERROR)
+ << "Power parameters requested before Tx Frequency was set! Providing band 900 by default...";
+ assign_band_desc(GSM_BAND_900);
+ }
+ desc = m_band_desc;
+ }
+
+ bool update_band_from_freq(double wFreq, int chan, bool is_tx)
+ {
+ enum gsm_band req_band;
+ auto dirstr = is_tx ? "Tx" : "Rx";
+ auto req_arfcn = gsm_freq102arfcn(wFreq / 1000 / 100, !is_tx);
+ if (req_arfcn == 0xffff) {
+ LOGCHAN(chan, DDEV, ALERT)
+ << "Unknown ARFCN for " << dirstr << " Frequency " << wFreq / 1000 << " kHz";
+ return false;
+ }
+ if (gsm_arfcn2band_rc(req_arfcn, &req_band) < 0) {
+ LOGCHAN(chan, DDEV, ALERT) << "Unknown GSM band for " << dirstr << " Frequency " << wFreq
+ << " Hz (ARFCN " << req_arfcn << " )";
+ return false;
+ }
+
+ return set_band(req_band);
+ }
+}; \ No newline at end of file
diff --git a/Transceiver52M/device/lms/LMSDevice.cpp b/Transceiver52M/device/lms/LMSDevice.cpp
index e336e77..451d2b9 100644
--- a/Transceiver52M/device/lms/LMSDevice.cpp
+++ b/Transceiver52M/device/lms/LMSDevice.cpp
@@ -52,39 +52,16 @@ extern "C" {
#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;
- /* Sample rate coef (without having TX/RX samples per symbol into account) */
- double rate;
- /* Sample rate coef (without having TX/RX samples per symbol into account), if multi-arfcn is enabled */
- double rate_multiarfcn;
- /* Coefficient multiplied by TX sample rate in order to shift Tx time */
- double ts_offset_coef;
- /* Coefficient multiplied by TX sample rate in order to shift Tx time, if multi-arfcn is enabled */
- double ts_offset_coef_multiarfcn;
- /* 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 {
+
+static const dev_map_t dev_param_map {
{ LMS_DEV_SDR_USB, { true, true, GSMRATE, MCBTS_SPACING, 8.9e-5, 7.9e-5, LMS_DEV_SDR_USB_PREFIX_NAME } },
{ LMS_DEV_SDR_MINI, { false, true, GSMRATE, MCBTS_SPACING, 8.9e-5, 8.2e-5, LMS_DEV_SDR_MINI_PREFIX_NAME } },
{ LMS_DEV_NET_MICRO, { true, false, GSMRATE, MCBTS_SPACING, 8.9e-5, 7.9e-5, LMS_DEV_NET_MICRO_PREFIX_NAME } },
{ LMS_DEV_UNKNOWN, { true, true, GSMRATE, MCBTS_SPACING, 8.9e-5, 7.9e-5, "UNKNOWN" } },
};
-typedef std::tuple<lms_dev_type, enum gsm_band> dev_band_key;
-typedef std::map<dev_band_key, dev_band_desc>::const_iterator dev_band_map_it;
-static const std::map<dev_band_key, dev_band_desc> dev_band_nom_power_param_map {
+static const power_map_t dev_band_nom_power_param_map {
{ std::make_tuple(LMS_DEV_SDR_USB, GSM_BAND_850), { 73.0, 11.2, -6.0 } },
{ std::make_tuple(LMS_DEV_SDR_USB, GSM_BAND_900), { 73.0, 10.8, -6.0 } },
{ std::make_tuple(LMS_DEV_SDR_USB, GSM_BAND_1800), { 65.0, -3.5, -17.0 } }, /* FIXME: OS#4583: 1800Mhz is failing above TxGain=65, which is around -3.5dBm (already < 0 dBm) */
@@ -122,8 +99,8 @@ static enum lms_dev_type parse_dev_type(lms_device_t *m_lms_dev)
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;
+ if (strncmp(device_info->deviceName, desc.desc_str.c_str(), desc.desc_str.length()) == 0) {
+ LOGC(DDEV, INFO) << "Device identified as " << desc.desc_str;
return dev_type;
}
it++;
@@ -132,8 +109,9 @@ static enum lms_dev_type parse_dev_type(lms_device_t *m_lms_dev)
}
LMSDevice::LMSDevice(InterfaceType iface, const struct trx_cfg *cfg)
- : RadioDevice(iface, cfg), m_lms_dev(NULL), started(false), band_ass_curr_sess(false), band((enum gsm_band)0),
- m_dev_type(LMS_DEV_UNKNOWN)
+ : RadioDevice(iface, cfg),
+ band_manager(m_dev_type, dev_band_nom_power_param_map, dev_param_map, {LMS_DEV_SDR_USB, GSM_BAND_850}), m_lms_dev(NULL),
+ started(false), m_dev_type(LMS_DEV_UNKNOWN)
{
LOGC(DDEV, INFO) << "creating LMS device...";
@@ -220,47 +198,6 @@ int info_list_find(lms_info_str_t* info_list, unsigned int count, const std::str
return -1;
}
-void LMSDevice::assign_band_desc(enum gsm_band req_band)
-{
- dev_band_map_it it;
-
- it = dev_band_nom_power_param_map.find(dev_band_key(m_dev_type, req_band));
- if (it == dev_band_nom_power_param_map.end()) {
- dev_desc desc = dev_param_map.at(m_dev_type);
- LOGC(DDEV, ERROR) << "No Tx Power measurements exist for device "
- << desc.name_prefix << " on band " << gsm_band_name(req_band)
- << ", using LimeSDR-USB ones as fallback";
- it = dev_band_nom_power_param_map.find(dev_band_key(LMS_DEV_SDR_USB, req_band));
- }
- OSMO_ASSERT(it != dev_band_nom_power_param_map.end());
- band_desc = it->second;
-}
-
-bool LMSDevice::set_band(enum gsm_band req_band)
-{
- if (band_ass_curr_sess && req_band != band) {
- LOGC(DDEV, ALERT) << "Requesting band " << gsm_band_name(req_band)
- << " different from previous band " << gsm_band_name(band);
- return false;
- }
-
- if (req_band != band) {
- band = req_band;
- assign_band_desc(band);
- }
- band_ass_curr_sess = true;
- return true;
-}
-
-void LMSDevice::get_dev_band_desc(dev_band_desc& desc)
-{
- if (band == 0) {
- LOGC(DDEV, ERROR) << "Power parameters requested before Tx Frequency was set! Providing band 900 by default...";
- assign_band_desc(GSM_BAND_900);
- }
- desc = band_desc;
-}
-
int LMSDevice::open()
{
lms_info_str_t* info_list;
@@ -466,7 +403,7 @@ bool LMSDevice::stop()
LMS_DestroyStream(m_lms_dev, &m_lms_stream_rx[i]);
}
- band_ass_curr_sess = false;
+ band_reset();
started = false;
return true;
@@ -483,8 +420,8 @@ bool LMSDevice::do_clock_src_freq(enum ReferenceType ref, double freq)
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";
+ LOGC(DDEV, ERROR)
+ << "Device type " << dev_desc.desc_str << " doesn't support internal reference clock";
return false;
}
/* According to lms using LMS_CLOCK_EXTREF with a
@@ -502,8 +439,8 @@ bool LMSDevice::do_clock_src_freq(enum ReferenceType ref, double freq)
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";
+ LOGC(DDEV, INFO)
+ << "Device type " << dev_desc.desc_str << " doesn't support switching clock source through SW";
}
return true;
@@ -996,9 +933,6 @@ bool LMSDevice::updateAlignment(TIMESTAMP timestamp)
bool LMSDevice::setTxFreq(double wFreq, size_t chan)
{
- uint16_t req_arfcn;
- enum gsm_band req_band;
-
if (chan >= chans) {
LOGC(DDEV, ALERT) << "Requested non-existent channel " << chan;
return false;
@@ -1006,18 +940,7 @@ bool LMSDevice::setTxFreq(double wFreq, size_t chan)
LOGCHAN(chan, DDEV, NOTICE) << "Setting Tx Freq to " << wFreq << " Hz";
- req_arfcn = gsm_freq102arfcn(wFreq / 1000 / 100 , 0);
- if (req_arfcn == 0xffff) {
- LOGCHAN(chan, DDEV, ALERT) << "Unknown ARFCN for Tx Frequency " << wFreq / 1000 << " kHz";
- return false;
- }
- if (gsm_arfcn2band_rc(req_arfcn, &req_band) < 0) {
- LOGCHAN(chan, DDEV, ALERT) << "Unknown GSM band for Tx Frequency " << wFreq
- << " Hz (ARFCN " << req_arfcn << " )";
- return false;
- }
-
- if (!set_band(req_band))
+ if (!update_band_from_freq(wFreq, chan, true))
return false;
if (LMS_SetLOFrequency(m_lms_dev, LMS_CH_TX, chan, wFreq) < 0) {
@@ -1030,23 +953,9 @@ bool LMSDevice::setTxFreq(double wFreq, size_t chan)
bool LMSDevice::setRxFreq(double wFreq, size_t chan)
{
- uint16_t req_arfcn;
- enum gsm_band req_band;
-
LOGCHAN(chan, DDEV, NOTICE) << "Setting Rx Freq to " << wFreq << " Hz";
- req_arfcn = gsm_freq102arfcn(wFreq / 1000 / 100, 1);
- if (req_arfcn == 0xffff) {
- LOGCHAN(chan, DDEV, ALERT) << "Unknown ARFCN for Rx Frequency " << wFreq / 1000 << " kHz";
- return false;
- }
- if (gsm_arfcn2band_rc(req_arfcn, &req_band) < 0) {
- LOGCHAN(chan, DDEV, ALERT) << "Unknown GSM band for Rx Frequency " << wFreq
- << " Hz (ARFCN " << req_arfcn << " )";
- return false;
- }
-
- if (!set_band(req_band))
+ if (!update_band_from_freq(wFreq, chan, false))
return false;
if (LMS_SetLOFrequency(m_lms_dev, LMS_CH_RX, chan, wFreq) < 0) {
diff --git a/Transceiver52M/device/lms/LMSDevice.h b/Transceiver52M/device/lms/LMSDevice.h
index 75d11cf..2e5ca4c 100644
--- a/Transceiver52M/device/lms/LMSDevice.h
+++ b/Transceiver52M/device/lms/LMSDevice.h
@@ -18,11 +18,13 @@
#ifndef _LMS_DEVICE_H_
#define _LMS_DEVICE_H_
+#include <map>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "radioDevice.h"
+#include "bandmanager.h"
#include "smpl_buf.h"
#include <sys/time.h>
@@ -69,8 +71,35 @@ struct dev_band_desc {
double rxgain2rssioffset_rel; /* dB */
};
+/* 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;
+ /* Sample rate coef (without having TX/RX samples per symbol into account) */
+ double rate;
+ /* Sample rate coef (without having TX/RX samples per symbol into account), if multi-arfcn is enabled */
+ double rate_multiarfcn;
+ /* Coefficient multiplied by TX sample rate in order to shift Tx time */
+ double ts_offset_coef;
+ /* Coefficient multiplied by TX sample rate in order to shift Tx time, if multi-arfcn is enabled */
+ double ts_offset_coef_multiarfcn;
+ /* Device Name Prefix as presented by LimeSuite API LMS_GetDeviceInfo() */
+ std::string desc_str;
+};
+
+using dev_band_key_t = std::tuple<lms_dev_type, gsm_band>;
+using power_map_t = std::map<dev_band_key_t, dev_band_desc>;
+using dev_map_t = std::map<lms_dev_type, struct dev_desc>;
+
/** A class to handle a LimeSuite supported device */
-class LMSDevice:public RadioDevice {
+class LMSDevice:public RadioDevice, public band_manager<power_map_t, dev_map_t> {
private:
lms_device_t *m_lms_dev;
@@ -87,9 +116,6 @@ private:
TIMESTAMP ts_initial, ts_offset;
std::vector<double> tx_gains, rx_gains;
- bool band_ass_curr_sess; /* true if "band" was set after last POWEROFF */
- enum gsm_band band;
- struct dev_band_desc band_desc;
enum lms_dev_type m_dev_type;
@@ -101,9 +127,6 @@ private:
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);
- void get_dev_band_desc(dev_band_desc& desc);
- bool set_band(enum gsm_band req_band);
- void assign_band_desc(enum gsm_band req_band);
public:
/** Object constructor */
diff --git a/Transceiver52M/device/uhd/UHDDevice.cpp b/Transceiver52M/device/uhd/UHDDevice.cpp
index a0021db..95ea8e7 100644
--- a/Transceiver52M/device/uhd/UHDDevice.cpp
+++ b/Transceiver52M/device/uhd/UHDDevice.cpp
@@ -91,19 +91,7 @@ extern "C" {
* USRP1 with timestamps is not supported by UHD.
*/
-/* Device Type, Tx-SPS, Rx-SPS */
-typedef std::tuple<uhd_dev_type, int, int> dev_key;
-
-/* Device parameter descriptor */
-struct dev_desc {
- unsigned channels;
- double mcr;
- double rate;
- double offset;
- std::string str;
-};
-
-static const std::map<dev_key, dev_desc> dev_param_map {
+static const dev_map_t dev_param_map {
{ std::make_tuple(USRP2, 1, 1), { 1, 0.0, 390625, 1.2184e-4, "N2XX 1 SPS" } },
{ std::make_tuple(USRP2, 4, 1), { 1, 0.0, 390625, 7.6547e-5, "N2XX 4/1 Tx/Rx SPS" } },
{ std::make_tuple(USRP2, 4, 4), { 1, 0.0, 390625, 4.6080e-5, "N2XX 4 SPS" } },
@@ -129,9 +117,7 @@ static const std::map<dev_key, dev_desc> dev_param_map {
{ std::make_tuple(B2XX_MCBTS, 4, 4), { 1, 51.2e6, MCBTS_SPACING*4, B2XX_TIMING_MCBTS, "B200/B210 4 SPS Multi-ARFCN" } },
};
-typedef std::tuple<uhd_dev_type, enum gsm_band> dev_band_key;
-typedef std::map<dev_band_key, dev_band_desc>::const_iterator dev_band_map_it;
-static const std::map<dev_band_key, dev_band_desc> dev_band_nom_power_param_map {
+static const power_map_t dev_band_nom_power_param_map {
{ std::make_tuple(B200, GSM_BAND_850), { 89.75, 13.3, -7.5 } },
{ std::make_tuple(B200, GSM_BAND_900), { 89.75, 13.3, -7.5 } },
{ std::make_tuple(B200, GSM_BAND_1800), { 89.75, 7.5, -11.0 } },
@@ -221,8 +207,8 @@ static double TxPower2TxGain(const dev_band_desc &desc, double tx_power_dbm)
}
uhd_device::uhd_device(InterfaceType iface, const struct trx_cfg *cfg)
- : RadioDevice(iface, cfg), rx_gain_min(0.0), rx_gain_max(0.0), band_ass_curr_sess(false),
- band((enum gsm_band)0), tx_spp(0), rx_spp(0), started(false), aligned(false), drop_cnt(0), prev_ts(0, 0),
+ : RadioDevice(iface, cfg), band_manager(dev_band_nom_power_param_map, dev_param_map), rx_gain_min(0.0),
+ rx_gain_max(0.0), tx_spp(0), rx_spp(0), started(false), aligned(false), drop_cnt(0), prev_ts(0, 0),
ts_initial(0), ts_offset(0), async_event_thrd(NULL)
{
}
@@ -235,47 +221,6 @@ uhd_device::~uhd_device()
delete rx_buffers[i];
}
-void uhd_device::assign_band_desc(enum gsm_band req_band)
-{
- dev_band_map_it it;
-
- it = dev_band_nom_power_param_map.find(dev_band_key(dev_type, req_band));
- if (it == dev_band_nom_power_param_map.end()) {
- dev_desc desc = dev_param_map.at(dev_key(dev_type, tx_sps, rx_sps));
- LOGC(DDEV, ERROR) << "No Power parameters exist for device "
- << desc.str << " on band " << gsm_band_name(req_band)
- << ", using B210 ones as fallback";
- it = dev_band_nom_power_param_map.find(dev_band_key(B210, req_band));
- }
- OSMO_ASSERT(it != dev_band_nom_power_param_map.end())
- band_desc = it->second;
-}
-
-bool uhd_device::set_band(enum gsm_band req_band)
-{
- if (band_ass_curr_sess && req_band != band) {
- LOGC(DDEV, ALERT) << "Requesting band " << gsm_band_name(req_band)
- << " different from previous band " << gsm_band_name(band);
- return false;
- }
-
- if (req_band != band) {
- band = req_band;
- assign_band_desc(band);
- }
- band_ass_curr_sess = true;
- return true;
-}
-
-void uhd_device::get_dev_band_desc(dev_band_desc& desc)
-{
- if (band == 0) {
- LOGC(DDEV, ERROR) << "Power parameters requested before Tx Frequency was set! Providing band 900 by default...";
- assign_band_desc(GSM_BAND_900);
- }
- desc = band_desc;
-}
-
void uhd_device::init_gains()
{
double tx_gain_min, tx_gain_max;
@@ -340,7 +285,7 @@ void uhd_device::set_rates()
rx_rate = usrp_dev->get_rx_rate();
ts_offset = static_cast<TIMESTAMP>(desc.offset * rx_rate);
- LOGC(DDEV, INFO) << "Rates configured for " << desc.str;
+ LOGC(DDEV, INFO) << "Rates configured for " << desc.desc_str;
}
double uhd_device::setRxGain(double db, size_t chan)
@@ -791,7 +736,7 @@ bool uhd_device::stop()
for (size_t i = 0; i < rx_buffers.size(); i++)
rx_buffers[i]->reset();
- band_ass_curr_sess = false;
+ band_reset();
started = false;
return true;
@@ -1031,17 +976,19 @@ bool uhd_device::set_freq(double freq, size_t chan, bool tx)
{
std::vector<double> freqs;
uhd::tune_result_t tres;
+ std::string str_dir = tx ? "Tx" : "Rx";
+
+ if (!update_band_from_freq(freq, chan, tx))
+ return false;
+
uhd::tune_request_t treq = select_freq(freq, chan, tx);
- std::string str_dir;
if (tx) {
tres = usrp_dev->set_tx_freq(treq, chan);
tx_freqs[chan] = usrp_dev->get_tx_freq(chan);
- str_dir = "Tx";
} else {
tres = usrp_dev->set_rx_freq(treq, chan);
rx_freqs[chan] = usrp_dev->get_rx_freq(chan);
- str_dir = "Rx";
}
LOGCHAN(chan, DDEV, INFO) << "set_freq(" << freq << ", " << str_dir << "): " << tres.to_pp_string() << std::endl;
@@ -1071,59 +1018,20 @@ bool uhd_device::set_freq(double freq, size_t chan, bool tx)
bool uhd_device::setTxFreq(double wFreq, size_t chan)
{
- uint16_t req_arfcn;
- enum gsm_band req_band;
-
if (chan >= tx_freqs.size()) {
LOGC(DDEV, ALERT) << "Requested non-existent channel " << chan;
return false;
}
- ScopedLock lock(tune_lock);
-
- req_arfcn = gsm_freq102arfcn(wFreq / 1000 / 100 , 0);
- if (req_arfcn == 0xffff) {
- LOGCHAN(chan, DDEV, ALERT) << "Unknown ARFCN for Tx Frequency " << wFreq / 1000 << " kHz";
- return false;
- }
- if (gsm_arfcn2band_rc(req_arfcn, &req_band) < 0) {
- LOGCHAN(chan, DDEV, ALERT) << "Unknown GSM band for Tx Frequency " << wFreq
- << " Hz (ARFCN " << req_arfcn << " )";
- return false;
- }
-
- if (!set_band(req_band))
- return false;
-
- if (!set_freq(wFreq, chan, true))
- return false;
- return true;
+ return set_freq(wFreq, chan, true);
}
bool uhd_device::setRxFreq(double wFreq, size_t chan)
{
- uint16_t req_arfcn;
- enum gsm_band req_band;
-
if (chan >= rx_freqs.size()) {
LOGC(DDEV, ALERT) << "Requested non-existent channel " << chan;
return false;
}
- ScopedLock lock(tune_lock);
-
- req_arfcn = gsm_freq102arfcn(wFreq / 1000 / 100, 1);
- if (req_arfcn == 0xffff) {
- LOGCHAN(chan, DDEV, ALERT) << "Unknown ARFCN for Rx Frequency " << wFreq / 1000 << " kHz";
- return false;
- }
- if (gsm_arfcn2band_rc(req_arfcn, &req_band) < 0) {
- LOGCHAN(chan, DDEV, ALERT) << "Unknown GSM band for Rx Frequency " << wFreq
- << " Hz (ARFCN " << req_arfcn << " )";
- return false;
- }
-
- if (!set_band(req_band))
- return false;
return set_freq(wFreq, chan, false);
}
diff --git a/Transceiver52M/device/uhd/UHDDevice.h b/Transceiver52M/device/uhd/UHDDevice.h
index 299d98c..f5e5232 100644
--- a/Transceiver52M/device/uhd/UHDDevice.h
+++ b/Transceiver52M/device/uhd/UHDDevice.h
@@ -30,6 +30,7 @@
#include "config.h"
#endif
+#include "bandmanager.h"
#include "radioDevice.h"
#include "smpl_buf.h"
@@ -71,6 +72,19 @@ struct dev_band_desc {
double rxgain2rssioffset_rel; /* dB */
};
+struct dev_desc {
+ unsigned channels;
+ double mcr;
+ double rate;
+ double offset;
+ std::string desc_str;
+};
+
+using dev_key = std::tuple<uhd_dev_type, int, int>;
+using dev_band_key = std::tuple<uhd_dev_type, enum gsm_band>;
+using power_map_t = std::map<dev_band_key, dev_band_desc>;
+using dev_map_t = std::map<dev_key, dev_desc>;
+
/*
uhd_device - UHD implementation of the Device interface. Timestamped samples
are sent to and received from the device. An intermediate buffer
@@ -78,7 +92,7 @@ struct dev_band_desc {
Events and errors such as underruns are reported asynchronously
by the device and received in a separate thread.
*/
-class uhd_device : public RadioDevice {
+class uhd_device : public RadioDevice, public band_manager<power_map_t, dev_map_t> {
public:
uhd_device(InterfaceType iface, const struct trx_cfg *cfg);
~uhd_device();
@@ -160,9 +174,6 @@ protected:
std::vector<double> tx_gains, rx_gains;
std::vector<double> tx_freqs, rx_freqs;
- bool band_ass_curr_sess; /* true if "band" was set after last POWEROFF */
- enum gsm_band band;
- struct dev_band_desc band_desc;
size_t tx_spp, rx_spp;
bool started;
@@ -191,10 +202,6 @@ protected:
uhd::tune_request_t select_freq(double wFreq, size_t chan, bool tx);
bool set_freq(double freq, size_t chan, bool tx);
- void get_dev_band_desc(dev_band_desc& desc);
- bool set_band(enum gsm_band req_band);
- void assign_band_desc(enum gsm_band req_band);
Thread *async_event_thrd;
- Mutex tune_lock;
};