1 # -*- coding: utf-8 -*-
4 # Common GSM constants and helpers
6 # (C) 2018-2020 by Vadim Yanitskiy <axilirator@gmail.com>
7 # Contributions by sysmocom - s.f.m.c. GmbH
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 2 of the License, or
14 # (at your option) any later version.
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
24 GSM_SUPERFRAME
= 26 * 51
25 GSM_HYPERFRAME
= 2048 * GSM_SUPERFRAME
29 EDGE_BURST_LEN
= GMSK_BURST_LEN
* 3
31 class BurstType(Enum
):
32 """ Burst types defined in 3GPP TS 45.002 """
33 DUMMY
= ("DB") # Dummy burst (5.2.6)
34 SYNC
= ("SB") # Synchronization Burst (5.2.5)
35 FREQ
= ("FB") # Frequency correction Burst (5.2.4)
36 ACCESS
= ("AB") # Access Burst (5.2.7)
37 NORMAL
= ("NB") # Normal Burst (5.2.3)
38 # HSR = ("HB") # Higher symbol rate burst (5.2.3a)
40 class TrainingSeqGMSK(Enum
):
41 """ Training Sequences defined in 3GPP TS 45.002 """
43 # Training Sequences for Access Burst (table 5.2.7-3)
44 AB_TS0
= (0, BurstType
.ACCESS
, "01001011011111111001100110101010001111000")
45 AB_TS1
= (1, BurstType
.ACCESS
, "01010100111110001000011000101111001001101")
46 AB_TS2
= (2, BurstType
.ACCESS
, "11101111001001110101011000001101101110111")
47 AB_TS4
= (4, BurstType
.ACCESS
, "11001001110001001110000000001101010110010")
49 # Training Sequences for Access Burst (table 5.2.7-4)
50 AB_TS3
= (3, BurstType
.ACCESS
, "10001000111010111011010000010000101100010")
51 AB_TS5
= (5, BurstType
.ACCESS
, "01010000111111110101110101101100110010100")
52 AB_TS6
= (6, BurstType
.ACCESS
, "01011110011101011110110100010011000010111")
53 AB_TS7
= (7, BurstType
.ACCESS
, "01000010110000011101001010111011100010000")
55 # Training Sequences for Synchronization Burst (table 5.2.5-3)
56 SB_TS0
= (0, BurstType
.SYNC
, "1011100101100010000001000000111100101101010001010111011000011011")
57 SB_TS1
= (1, BurstType
.SYNC
, "1110111001101011001010000011111011110100011111101100101100010101")
58 SB_TS2
= (2, BurstType
.SYNC
, "1110110000110111010100010101101001111000000100000010001101001110")
59 SB_TS3
= (3, BurstType
.SYNC
, "1011101000111101110101101111010010001011010000001000111010011000")
61 # Training Sequences for Normal Burst (table 5.2.3a, TSC set 1)
62 NB_TS0
= (0, BurstType
.NORMAL
, "00100101110000100010010111")
63 NB_TS1
= (1, BurstType
.NORMAL
, "00101101110111100010110111")
64 NB_TS2
= (2, BurstType
.NORMAL
, "01000011101110100100001110")
65 NB_TS3
= (3, BurstType
.NORMAL
, "01000111101101000100011110")
66 NB_TS4
= (4, BurstType
.NORMAL
, "00011010111001000001101011")
67 NB_TS5
= (5, BurstType
.NORMAL
, "01001110101100000100111010")
68 NB_TS6
= (6, BurstType
.NORMAL
, "10100111110110001010011111")
69 NB_TS7
= (7, BurstType
.NORMAL
, "11101111000100101110111100")
71 # TODO: more TSC sets from tables 5.2.3b-d
73 def __init__(self
, tsc
, bt
, seq_str
, tsc_set
= 0):
74 # Training Sequence Code
79 # Training Sequence Code set
80 # NOTE: unlike the specs. we count from zero
81 self
.tsc_set
= tsc_set
83 # Generate Training Sequence bits
84 self
.seq
= [int(x
) for x
in seq_str
]
87 def pick(self
, burst
):
88 # Normal burst TS (26 bits)
89 nb_seq
= burst
[3 + 57 + 1:][:26]
90 # Access burst TS (41 bits)
91 ab_seq
= burst
[8:][:41]
92 # Sync Burst TS (64 bits)
93 sb_seq
= burst
[3 + 39:][:64]
96 # Ugly Python way of writing 'switch' statement
97 if ts
.bt
is BurstType
.NORMAL
and ts
.seq
== nb_seq
:
99 elif ts
.bt
is BurstType
.ACCESS
and ts
.seq
== ab_seq
:
101 elif ts
.bt
is BurstType
.SYNC
and ts
.seq
== sb_seq
:
107 """ Hopping sequence generation as per 3GPP TS 45.002, section 6.2.3.
109 Based on firmware/layer1/rfch.c:rfch_hop_seq_gen() by Sylvain Munaut.
113 # Magic numbers for pseudo-random hopping sequence generation
115 48, 98, 63, 1, 36, 95, 78, 102, 94, 73,
116 0, 64, 25, 81, 76, 59, 124, 23, 104, 100,
117 101, 47, 118, 85, 18, 56, 96, 86, 54, 2,
118 80, 34, 127, 13, 6, 89, 57, 103, 12, 74,
119 55, 111, 75, 38, 109, 71, 112, 29, 11, 88,
120 87, 19, 3, 68, 110, 26, 33, 31, 8, 45,
121 82, 58, 40, 107, 32, 5, 106, 92, 62, 67,
122 77, 108, 122, 37, 60, 66, 121, 42, 51, 126,
123 117, 114, 4, 90, 43, 52, 53, 113, 120, 72,
124 16, 49, 7, 79, 119, 61, 22, 84, 9, 97,
125 91, 15, 21, 24, 46, 39, 93, 105, 65, 70,
129 def __init__(self
, hsn
, maio
, ma
):
130 # Make sure MA is not empty
132 if ma_len
== 0: # TODO: or rather > 1?
133 raise ValueError("Mobile Allocation is empty")
139 # Pre-calculate 2 ** NBIN in advance
140 self
._pnm
= (ma_len
>> 0) |
(ma_len
>> 1) \
141 |
(ma_len
>> 2) |
(ma_len
>> 3) \
142 |
(ma_len
>> 4) |
(ma_len
>> 5) \
146 fmt
= "hsn=%u, maio=%u, ma_len=%u"
147 return fmt
% (self
.hsn
, self
.maio
, len(self
.ma
))
155 return (t1
, t2
, t3
, tc
)
157 # Resolve current ARFCN using the given TDMA frame number
158 def resolve(self
, fn
):
161 mai
= (fn
+ self
.maio
) % len(self
.ma
)
164 # Pseudo random hopping
165 (t1
, t2
, t3
, tc
) = self
.fn2gsm_time(fn
)
166 ma_len
= len(self
.ma
)
168 rn_idx
= (self
.hsn ^
(t1
& 63)) + t3
169 m
= t2
+ self
.RNTABLE
[rn_idx
]
172 s
= mp
if mp
< ma_len
else (mp
+ t3
& self
._pnm
) % ma_len
173 mai
= (s
+ self
.maio
) % ma_len