blob: bf227b4917d7dbb0f289a19565b6c391fffda001 [file] [log] [blame]
Roman Khassraf91448612015-08-21 11:14:51 +02001#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# @file
Piotr Krysika6268a52017-08-23 16:02:19 +02004# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
Roman Khassraf91448612015-08-21 11:14:51 +02005# @section LICENSE
6#
7# Gr-gsm is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 3, or (at your option)
10# any later version.
11#
12# Gr-gsm is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with gr-gsm; see the file COPYING. If not, write to
19# the Free Software Foundation, Inc., 51 Franklin Street,
20# Boston, MA 02110-1301, USA.
21#
22#
23
Roman Khassrafe7e75f02015-08-22 19:26:12 +020024import collections
25
Roman Khassraffb772f82016-09-23 07:23:05 +020026# first uplink freq, distance between uplink/downlink frequency, list of range tuple
27# each tuple in a range tuple contains: first arfcn of the range, last arfcn of the range, offset of the range
Roman Khassrafe7e75f02015-08-22 19:26:12 +020028# entries are ordered by relevance
29__band_conf = collections.OrderedDict([
Roman Khassraffb772f82016-09-23 07:23:05 +020030 ('P-GSM', {'f_start': 890.0e6, 'distance': 45e6, 'ranges': [(1, 124, 0)]}),
31 ('DCS1800', {'f_start': 1710.2e6, 'distance': 95e6, 'ranges': [(512, 885, 512)]}),
32 ('PCS1900', {'f_start': 1850.2e6, 'distance': 80e6, 'ranges': [(512, 810, 512)]}),
33 ('E-GSM', {'f_start': 890.0e6, 'distance': 45e6, 'ranges': [(0, 124, 0), (975, 1023, 1024)]}),
34 ('R-GSM', {'f_start': 890.0e6, 'distance': 45e6, 'ranges': [(0, 124, 0), (955, 1023, 1024)]}),
35 ('GSM450', {'f_start': 450.6e6, 'distance': 10e6, 'ranges': [(259, 293, 259)]}),
36 ('GSM480', {'f_start': 479e6, 'distance': 10e6, 'ranges': [(306, 340, 306)]}),
37 ('GSM850', {'f_start': 824.2e6, 'distance': 45e6, 'ranges': [(128, 251, 128)]}),
38])
Roman Khassraf91448612015-08-21 11:14:51 +020039
40__chan_spacing = 2e5
41
42
43def get_bands():
44 return __band_conf.keys()
45
46
Roman Khassraf91448612015-08-21 11:14:51 +020047def is_valid_arfcn(arfcn, band):
48 """
49 Returns True if arfcn is valid in the given band, else False
50 """
51 if band in __band_conf:
52 conf = __band_conf.get(band)
Roman Khassraffb772f82016-09-23 07:23:05 +020053 for arfcn_range in conf['ranges']:
54 arfcn_start = arfcn_range[0]
55 arfcn_end = arfcn_range[1]
56 if arfcn_start <= arfcn <= arfcn_end:
57 return True
Roman Khassraf91448612015-08-21 11:14:51 +020058 return False
59
60
61def is_valid_uplink(freq, band):
62 """
63 Returns True if the given frequency is a valid uplink frequency in the given band
64 """
Roman Khassraffb772f82016-09-23 07:23:05 +020065 result = None
Roman Khassraf91448612015-08-21 11:14:51 +020066 if band in __band_conf:
67 conf = __band_conf.get(band)
Roman Khassraffb772f82016-09-23 07:23:05 +020068 result = False
69 for arfcn_range in conf['ranges']:
70 arfcn_start = arfcn_range[0]
71 arfcn_end = arfcn_range[1]
72 first_freq = arfcn2uplink(arfcn_start, band)
73 last_freq = arfcn2uplink(arfcn_end, band)
74 if first_freq is None or last_freq is None:
75 result = False
76 elif first_freq <= freq <= last_freq:
77 result = True
78 return result
Roman Khassraf91448612015-08-21 11:14:51 +020079
80
81def is_valid_downlink(freq, band):
82 """
83 Returns True if the given frequency is a valid downlink frequency in the given band
84 """
Roman Khassraffb772f82016-09-23 07:23:05 +020085 result = None
Roman Khassraf91448612015-08-21 11:14:51 +020086 if band in __band_conf:
87 conf = __band_conf.get(band)
Roman Khassraffb772f82016-09-23 07:23:05 +020088 result = False
89 for arfcn_range in conf['ranges']:
90 arfcn_start = arfcn_range[0]
91 arfcn_end = arfcn_range[1]
92 first_freq = arfcn2downlink(arfcn_start, band)
93 last_freq = arfcn2downlink(arfcn_end, band)
94 if first_freq is None or last_freq is None:
95 result = False
96 elif first_freq <= freq <= last_freq:
97 result = True
98 return result
Roman Khassraf91448612015-08-21 11:14:51 +020099
100
101def arfcn2uplink(arfcn, band):
102 if band in __band_conf and is_valid_arfcn(arfcn, band):
Roman Khassraf91448612015-08-21 11:14:51 +0200103 conf = __band_conf.get(band)
Roman Khassraffb772f82016-09-23 07:23:05 +0200104 f_start = conf['f_start']
105 offset = None
106 for arfcn_range in conf['ranges']:
107 arfcn_start = arfcn_range[0]
108 arfcn_end = arfcn_range[1]
109 if arfcn_start <= arfcn <= arfcn_end:
110 offset = arfcn_range[2]
111
112 if offset is not None:
113 f = f_start + (__chan_spacing * (arfcn - offset))
114 return round(f, 1)
Roman Khassraf91448612015-08-21 11:14:51 +0200115 return None
116
117
118def arfcn2downlink(arfcn, band):
119 if band in __band_conf and is_valid_arfcn(arfcn, band):
120 conf = __band_conf.get(band)
Roman Khassraffb772f82016-09-23 07:23:05 +0200121 distance = conf['distance']
Roman Khassraf91448612015-08-21 11:14:51 +0200122 return round(arfcn2uplink(arfcn, band) + distance, 1)
123 return None
124
125
126def uplink2arfcn(freq, band):
127 if band in __band_conf and is_valid_uplink(freq, band):
128 conf = __band_conf.get(band)
Roman Khassraffb772f82016-09-23 07:23:05 +0200129 f_start = conf['f_start']
130 offset = None
131 for arfcn_range in conf['ranges']:
132 arfcn_start = arfcn_range[0]
133 arfcn_end = arfcn_range[1]
134 offset = arfcn_range[2]
135 arfcn = int(round(offset + ((freq - f_start) / __chan_spacing), 0))
136 if arfcn_start <= arfcn <= arfcn_end:
137 return arfcn
Roman Khassraf91448612015-08-21 11:14:51 +0200138 return None
139
140
141def downlink2arfcn(freq, band):
142 if band in __band_conf and is_valid_downlink(freq, band):
143 conf = __band_conf.get(band)
Roman Khassraffb772f82016-09-23 07:23:05 +0200144 distance = conf['distance']
Roman Khassraf91448612015-08-21 11:14:51 +0200145 freq_uplink = freq - distance
146 return int(round(uplink2arfcn(freq_uplink, band), 0))
147 return None
Roman Khassraffb772f82016-09-23 07:23:05 +0200148
149
150def get_arfcn_ranges(band):
151 """
152 Returns a list of arfcn tuples, each with first and last arfcn of the range.
153 """
154 result = []
155 if band in __band_conf:
156 conf = __band_conf.get(band)
157 for arfcn_range in conf['ranges']:
158 arfcn_tuple = (arfcn_range[0], arfcn_range[1])
159 result.append(arfcn_tuple)
160 return result