aboutsummaryrefslogtreecommitdiffstats
path: root/Transceiver52M/device/common
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 /Transceiver52M/device/common
parent19e134a626abdb99435d96b0bfcc46b0804715e5 (diff)
devices: unify band handling
This is basically common, but optional code. Change-Id: I64f5a462451e967d4750d8e4f1d5832cbab41cff
Diffstat (limited to 'Transceiver52M/device/common')
-rw-r--r--Transceiver52M/device/common/Makefile.am2
-rw-r--r--Transceiver52M/device/common/bandmanager.h133
2 files changed, 134 insertions, 1 deletions
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