blob: 296bc7ab3a53bc9858838f232c461e7efb48337b [file] [log] [blame]
# SPDX-FileCopyrightText: 2020 The Magma Authors.
# SPDX-FileCopyrightText: 2022 Open Networking Foundation <support@opennetworking.org>
#
# SPDX-License-Identifier: BSD-3-Clause
from enum import Enum
from typing import Optional
class DuplexMode(Enum):
FDD = 1
TDD = 2
class LTEBandInfo:
""" Class for holding information related to LTE band.
Takes advantage of the following properties of LTE EARFCN assignment:
- EARFCN spacing within a band is always 0.1MHz
- 1:1 mapping between EARFCNDL and EARFCNUL (for FDD)
"""
def __init__(
self, duplex_mode, earfcndl, start_freq_dl_mhz,
start_earfcnul=None, start_freq_ul_mhz=None,
):
"""
Inputs:
- Duplex mode - type = DuplexMode
- earfcndl - List/generator of integer EARFCNDLs in band, from lowest to
highest
- start_freq_dl_mhz - Frequency of lowest numbered EARFCNDL in band
(MHz)
- start_earfcnul - Lowest numbered EARFCNUL in band
(or None if band is TDD)
- start_freq_ul_mhz - Frequency of lowest numbered EARFCNUL in band
(MHz) (or None if band is TDD)
"""
# Validate inputs
assert type(earfcndl) == list or type(earfcndl) == range
assert type(start_freq_dl_mhz) == int
assert type(duplex_mode) == DuplexMode
if duplex_mode == DuplexMode.FDD:
assert type(start_earfcnul) == int
assert type(start_freq_ul_mhz) == int
else:
assert start_earfcnul is None
assert start_freq_ul_mhz is None
# DuplexMode.TDD or DuplexMode.FDD
self.duplex_mode = duplex_mode
# Array of EARFCNDL values
self.earfcndl = earfcndl
# Array of DL frequencies in MHz, one per EARFCNDL
self.freq_mhz_dl = [
start_freq_dl_mhz + 0.1 * (earfcn - earfcndl[0])
for earfcn in earfcndl
]
if duplex_mode == DuplexMode.FDD:
# Array of EARFCNUL values that map to EARFCNDL
self.earfcnul = range(
start_earfcnul,
start_earfcnul + len(earfcndl),
)
# Array of UL frequencies in MHz, one per EARFCNUL
self.freq_mhz_ul = [
start_freq_ul_mhz + 0.1 * (
earfcn -
self.earfcnul[0]
) for earfcn in self.earfcnul
]
else:
self.earfcnul = None
self.freq_mhz_ul = None
# See, for example, http://niviuk.free.fr/lte_band.php for LTE band info
LTE_BAND_INFO = {
# FDD bands
# duplex_mode, EARFCNDL, start_freq_dl, start_EARCNUL, start_freq_ul
1: LTEBandInfo(DuplexMode.FDD, range(0, 600), 2110, 18000, 1920),
2: LTEBandInfo(DuplexMode.FDD, range(600, 1200), 1930, 18600, 1850),
3: LTEBandInfo(DuplexMode.FDD, range(1200, 1950), 1805, 19200, 1710),
4: LTEBandInfo(DuplexMode.FDD, range(1950, 2400), 2110, 19950, 1710),
5: LTEBandInfo(DuplexMode.FDD, range(2400, 2649), 869, 20400, 824),
28: LTEBandInfo(DuplexMode.FDD, range(9210, 9660), 758, 27210, 703),
# TDD bands
# duplex_mode, EARFCNDL, start_freq_dl
33: LTEBandInfo(DuplexMode.TDD, range(36000, 36199), 1900),
34: LTEBandInfo(DuplexMode.TDD, range(36200, 36349), 2010),
35: LTEBandInfo(DuplexMode.TDD, range(36350, 36949), 1850),
36: LTEBandInfo(DuplexMode.TDD, range(36950, 37549), 1930),
37: LTEBandInfo(DuplexMode.TDD, range(37550, 37750), 1910),
38: LTEBandInfo(DuplexMode.TDD, range(37750, 38250), 2570),
39: LTEBandInfo(DuplexMode.TDD, range(38250, 38650), 1880),
40: LTEBandInfo(DuplexMode.TDD, range(38650, 39650), 2300),
41: LTEBandInfo(DuplexMode.TDD, range(39650, 41590), 2496),
42: LTEBandInfo(DuplexMode.TDD, range(41590, 43590), 3400),
43: LTEBandInfo(DuplexMode.TDD, range(43590, 45590), 3600),
44: LTEBandInfo(DuplexMode.TDD, range(45590, 46589), 703),
45: LTEBandInfo(DuplexMode.TDD, range(46590, 46789), 1447),
46: LTEBandInfo(DuplexMode.TDD, range(46790, 54539), 5150),
47: LTEBandInfo(DuplexMode.TDD, range(54540, 55239), 5855),
48: LTEBandInfo(DuplexMode.TDD, range(55240, 56740), 3550),
49: LTEBandInfo(DuplexMode.TDD, range(56740, 58239), 3550),
50: LTEBandInfo(DuplexMode.TDD, range(58240, 59089), 1432),
51: LTEBandInfo(DuplexMode.TDD, range(59090, 59139), 1427),
52: LTEBandInfo(DuplexMode.TDD, range(59140, 60139), 3300),
# For the band #53 start_freq_dl is float value which require some changes
# in the code
# 53: LTEBandInfo(DuplexMode.TDD, range(60140, 60254), 2483.5),
}
# TODO - add remaining FDD LTE bands
def map_earfcndl_to_duplex_mode(earfcndl: int) -> Optional[DuplexMode]:
"""
Returns None if we do not support the EARFCNDL
"""
for band in LTE_BAND_INFO.keys():
if earfcndl in LTE_BAND_INFO[band].earfcndl:
return LTE_BAND_INFO[band].duplex_mode
return None
def map_earfcndl_to_band_earfcnul_mode(earfcndl):
""" Inputs:
- EARFCNDL (integer)
Outputs:
- Band (integer)
- Mode (DuplexMode)
- EARFCNUL (integer - or None if TDD)
"""
for band in LTE_BAND_INFO.keys():
if earfcndl in LTE_BAND_INFO[band].earfcndl:
if LTE_BAND_INFO[band].duplex_mode == DuplexMode.FDD:
index = LTE_BAND_INFO[band].earfcndl.index(earfcndl)
earfcnul = LTE_BAND_INFO[band].earfcnul[index]
else:
earfcnul = None
return band, LTE_BAND_INFO[band].duplex_mode, earfcnul
raise ValueError('EARFCNDL %d not found in LTE band info' % earfcndl)