Initial import of OsmocomBB into git repository
[osmocom-bb.git] / src / target / firmware / layer1 / gsm.c
1 /* Generic GSM utility routines */
2
3 /* (C) 2010 by Harald Welte <laforge@gnumonks.org>
4  *
5  * All Rights Reserved
6  *
7  * This program 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 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program 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 along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  */
22
23
24 #include <stdint.h>
25
26 #include <gsm.h>
27
28 enum gsm_band gsm_arfcn2band(uint16_t arfcn)
29 {
30         if (arfcn & ARFCN_PCS)
31                 return GSM_1900;
32         else if (arfcn <= 124)
33                 return GSM_900;
34         else if (arfcn >= 955 && arfcn <= 1023)
35                 return GSM_900;
36         else if (arfcn >= 128 && arfcn <= 251)
37                 return GSM_850;
38         else if (arfcn >= 512 && arfcn <= 885)
39                 return GSM_1800;
40         else if (arfcn >= 259 && arfcn <= 293)
41                 return GSM_450;
42         else if (arfcn >= 306 && arfcn <= 340)
43                 return GSM_480;
44         else if (arfcn >= 350 && arfcn <= 425)
45                 return GSM_810;
46         else if (arfcn >= 438 && arfcn <= 511)
47                 return GSM_750;
48         else
49                 return GSM_1800;
50 }
51
52 /* Convert an ARFCN to the frequency in MHz * 10 */
53 uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink)
54 {
55         uint16_t freq10_ul;
56         uint16_t freq10_dl;
57
58         if (arfcn & ARFCN_PCS) {
59                 /* DCS 1900 */
60                 arfcn &= ~ARFCN_PCS;
61                 freq10_ul = 18502 + 2 * (arfcn-512);
62                 freq10_dl = freq10_ul + 800;
63         } else if (arfcn <= 124) {
64                 /* Primary GSM + ARFCN 0 of E-GSM */
65                 freq10_ul = 8900 + 2 * arfcn;
66                 freq10_dl = freq10_ul + 450;
67         } else if (arfcn >= 955 && arfcn <= 1023) {
68                 /* E-GSM and R-GSM */
69                 freq10_ul = 8900 + 2 * (arfcn - 1024);
70                 freq10_dl = freq10_ul + 450;
71         } else if (arfcn >= 128 && arfcn <= 251) {
72                 /* GSM 850 */
73                 freq10_ul = 8242 + 2 * (arfcn - 128);
74                 freq10_dl = freq10_ul + 450;
75         } else if (arfcn >= 512 && arfcn <= 885) {
76                 /* DCS 1800 */
77                 freq10_ul = 17102 + 2 * (arfcn - 512);
78                 freq10_dl = freq10_ul + 950;
79         } else if (arfcn >= 259 && arfcn <= 293) {
80                 /* GSM 450 */
81                 freq10_ul = 4506 + 2 * (arfcn - 259);
82                 freq10_dl = freq10_ul + 100;
83         } else if (arfcn >= 306 && arfcn <= 340) {
84                 /* GSM 480 */
85                 freq10_ul = 4790 + 2 * (arfcn - 306);
86                 freq10_dl = freq10_ul + 100;
87         } else if (arfcn >= 350 && arfcn <= 425) {
88                 /* GSM 810 */
89                 freq10_ul = 8060 + 2 * (arfcn - 350);
90                 freq10_dl = freq10_ul + 450;
91         } else if (arfcn >= 438 && arfcn <= 511) {
92                 /* GSM 750 */
93                 freq10_ul = 7472 + 2 * (arfcn - 438);
94                 freq10_dl = freq10_ul + 300;
95         } else
96                 return 0xffff;
97
98         if (uplink)
99                 return freq10_ul;
100         else
101                 return freq10_dl;
102 }
103
104 void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn)
105 {
106         time->fn = fn;
107         time->t1 = time->fn / (26*51);
108         time->t2 = time->fn % 26;
109         time->t3 = time->fn % 51;
110         time->tc = (time->fn / 51) % 8;
111 }
112
113 uint32_t gsm_gsmtime2fn(struct gsm_time *time)
114 {
115         /* TS 05.02 Chapter 4.3.3 TDMA frame number */
116         return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1));
117 }