aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gsm_utils.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2009-08-09 14:45:18 +0200
committerHarald Welte <laforge@gnumonks.org>2009-08-09 14:45:18 +0200
commit66b6a8dde061e16fb2f102eb2de9b884a1941481 (patch)
tree86bed65b3975138d176185bd8fe8aa9e13b5531f /openbsc/src/gsm_utils.c
parent31f03a6df66ccfcaa3ae71663ac53bf7c2b80c59 (diff)
move ms_pwr utility function to gsm_utils.c
also, they should both take the gsm_band parameter, not a BTS
Diffstat (limited to 'openbsc/src/gsm_utils.c')
-rw-r--r--openbsc/src/gsm_utils.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/openbsc/src/gsm_utils.c b/openbsc/src/gsm_utils.c
index 0c25b28c6..185918ef9 100644
--- a/openbsc/src/gsm_utils.c
+++ b/openbsc/src/gsm_utils.c
@@ -21,9 +21,11 @@
*
*/
+#include <openbsc/gsm_data.h>
#include <openbsc/gsm_utils.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
/* GSM 03.38 6.2.1 Charachter packing */
int gsm_7bit_decode(char *text, const u_int8_t *user_data, u_int8_t length)
@@ -71,3 +73,77 @@ int gsm_7bit_encode(u_int8_t *result, const char *data)
return out_length;
}
+
+/* determine power control level for given dBm value, as indicated
+ * by the tables in chapter 4.1.1 of GSM TS 05.05 */
+int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm)
+{
+ switch (band) {
+ case GSM_BAND_400:
+ case GSM_BAND_900:
+ case GSM_BAND_850:
+ if (dbm >= 39)
+ return 0;
+ else if (dbm < 5)
+ return 19;
+ else
+ return 2 + ((39 - dbm) / 2);
+ break;
+ case GSM_BAND_1800:
+ if (dbm >= 36)
+ return 29;
+ else if (dbm >= 34)
+ return 30;
+ else if (dbm >= 32)
+ return 31;
+ else
+ return (30 - dbm) / 2;
+ break;
+ case GSM_BAND_1900:
+ if (dbm >= 33)
+ return 30;
+ else if (dbm >= 32)
+ return 31;
+ else
+ return (30 - dbm) / 2;
+ break;
+ }
+ return -EINVAL;
+}
+
+int ms_pwr_dbm(enum gsm_band band, u_int8_t lvl)
+{
+ lvl &= 0x1f;
+
+ switch (band) {
+ case GSM_BAND_400:
+ case GSM_BAND_900:
+ case GSM_BAND_850:
+ if (lvl < 2)
+ return 39;
+ else if (lvl < 20)
+ return 39 - ((lvl - 2) * 2) ;
+ else
+ return 5;
+ break;
+ case GSM_BAND_1800:
+ if (lvl < 16)
+ return 30 - (lvl * 2);
+ else if (lvl < 29)
+ return 0;
+ else
+ return 36 - ((lvl - 29) * 2);
+ break;
+ case GSM_BAND_1900:
+ if (lvl < 16)
+ return 30 - (lvl * 2);
+ else if (lvl < 30)
+ return -EINVAL;
+ else
+ return 33 - (lvl - 30);
+ break;
+ }
+ return -EINVAL;
+}
+
+