diff --git a/include/osmocore/gsm_utils.h b/include/osmocore/gsm_utils.h index b611050d3..25360459a 100644 --- a/include/osmocore/gsm_utils.h +++ b/include/osmocore/gsm_utils.h @@ -27,6 +27,14 @@ #include +struct gsm_time { + uint32_t fn; /* FN count */ + uint16_t t1; /* FN div (26*51) */ + uint8_t t2; /* FN modulo 26 */ + uint8_t t3; /* FN modulo 51 */ + uint8_t tc; +}; + enum gsm_band { GSM_BAND_850 = 1, GSM_BAND_900 = 2, @@ -58,5 +66,19 @@ static inline int rach_max_trans_raw2val(int raw) { return tbl[raw & 3]; } +#define ARFCN_PCS 0x8000 +#define ARFCN_UPLINK 0x4000 + +enum gsm_band gsm_arfcn2band(uint16_t arfcn); + +/* Convert an ARFCN to the frequency in MHz * 10 */ +uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink); + +/* Convert from frame number to GSM time */ +void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn); + +/* Convert from GSM time to frame number */ +uint32_t gsm_gsmtime2fn(struct gsm_time *time); + void generate_backtrace(); #endif diff --git a/src/gsm_utils.c b/src/gsm_utils.c index 174b2d499..4ee137c3c 100644 --- a/src/gsm_utils.c +++ b/src/gsm_utils.c @@ -1,7 +1,7 @@ /* * (C) 2008 by Daniel Willmann * (C) 2009 by Holger Hans Peter Freyther - * (C) 2009 by Harald Welte + * (C) 2009-2010 by Harald Welte * * All Rights Reserved * @@ -268,3 +268,94 @@ void generate_backtrace() free(strings); } #endif + +enum gsm_band gsm_arfcn2band(uint16_t arfcn) +{ + if (arfcn & ARFCN_PCS) + return GSM_BAND_1900; + else if (arfcn <= 124) + return GSM_BAND_900; + else if (arfcn >= 955 && arfcn <= 1023) + return GSM_BAND_900; + else if (arfcn >= 128 && arfcn <= 251) + return GSM_BAND_850; + else if (arfcn >= 512 && arfcn <= 885) + return GSM_BAND_1800; + else if (arfcn >= 259 && arfcn <= 293) + return GSM_BAND_450; + else if (arfcn >= 306 && arfcn <= 340) + return GSM_BAND_480; + else if (arfcn >= 350 && arfcn <= 425) + return GSM_BAND_810; + else if (arfcn >= 438 && arfcn <= 511) + return GSM_BAND_750; + else + return GSM_BAND_1800; +} + +/* Convert an ARFCN to the frequency in MHz * 10 */ +uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink) +{ + uint16_t freq10_ul; + uint16_t freq10_dl; + + if (arfcn & ARFCN_PCS) { + /* DCS 1900 */ + arfcn &= ~ARFCN_PCS; + freq10_ul = 18502 + 2 * (arfcn-512); + freq10_dl = freq10_ul + 800; + } else if (arfcn <= 124) { + /* Primary GSM + ARFCN 0 of E-GSM */ + freq10_ul = 8900 + 2 * arfcn; + freq10_dl = freq10_ul + 450; + } else if (arfcn >= 955 && arfcn <= 1023) { + /* E-GSM and R-GSM */ + freq10_ul = 8900 + 2 * (arfcn - 1024); + freq10_dl = freq10_ul + 450; + } else if (arfcn >= 128 && arfcn <= 251) { + /* GSM 850 */ + freq10_ul = 8242 + 2 * (arfcn - 128); + freq10_dl = freq10_ul + 450; + } else if (arfcn >= 512 && arfcn <= 885) { + /* DCS 1800 */ + freq10_ul = 17102 + 2 * (arfcn - 512); + freq10_dl = freq10_ul + 950; + } else if (arfcn >= 259 && arfcn <= 293) { + /* GSM 450 */ + freq10_ul = 4506 + 2 * (arfcn - 259); + freq10_dl = freq10_ul + 100; + } else if (arfcn >= 306 && arfcn <= 340) { + /* GSM 480 */ + freq10_ul = 4790 + 2 * (arfcn - 306); + freq10_dl = freq10_ul + 100; + } else if (arfcn >= 350 && arfcn <= 425) { + /* GSM 810 */ + freq10_ul = 8060 + 2 * (arfcn - 350); + freq10_dl = freq10_ul + 450; + } else if (arfcn >= 438 && arfcn <= 511) { + /* GSM 750 */ + freq10_ul = 7472 + 2 * (arfcn - 438); + freq10_dl = freq10_ul + 300; + } else + return 0xffff; + + if (uplink) + return freq10_ul; + else + return freq10_dl; +} + +void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn) +{ + time->fn = fn; + time->t1 = time->fn / (26*51); + time->t2 = time->fn % 26; + time->t3 = time->fn % 51; + time->tc = (time->fn / 51) % 8; +} + +uint32_t gsm_gsmtime2fn(struct gsm_time *time) +{ + /* TS 05.02 Chapter 4.3.3 TDMA frame number */ + return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1)); +}