summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2012-01-29 11:32:14 +0100
committerHarald Welte <laforge@gnumonks.org>2012-02-04 00:04:58 +0100
commit284cf9a34c692e1bb1285d4740a48ef90754436c (patch)
tree0f7d43004c98e35873e512ac524662ae9067bfc9
parent0fd73c5e0f69e528689617837864fc69ff6d59a6 (diff)
firmware/monitor: Improvements and sync support
By pressing the green button, the sync mode is entered. The screen show some informations about the cell. The beep indicates, if the received BCCH was valid or not. By pressing the Down button, the list of channels of the serving cell and neighbour cells can be viewed and scrolled through. By pressing the Up button, the levels (downlink or uplink) of the serving cell can be viewed. Also it is possible to select one of the serving cell's frequencies by pressing the Left/Right button.
-rw-r--r--src/target/firmware/apps/rssi/main.c580
1 files changed, 544 insertions, 36 deletions
diff --git a/src/target/firmware/apps/rssi/main.c b/src/target/firmware/apps/rssi/main.c
index 5d247958..ea8bbb49 100644
--- a/src/target/firmware/apps/rssi/main.c
+++ b/src/target/firmware/apps/rssi/main.c
@@ -47,6 +47,9 @@
#include <layer1/sync.h>
#include <layer1/async.h>
#include <layer1/l23_api.h>
+#include <osmocom/gsm/rsl.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/gsm48_ie.h>
enum key_codes key_code = KEY_INV;
int key_pressed = 0;
@@ -58,10 +61,11 @@ enum mode {
MODE_MAIN,
MODE_SPECTRUM,
MODE_ARFCN,
+ MODE_SYNC,
} mode = MODE_MAIN;
enum mode last_mode; /* where to return after entering ARFCN */
-static uint16_t arfcn = 0;
+static uint16_t arfcn = 0, ul_arfcn;
int pcs = 0;
int uplink = 0;
int max = 0;
@@ -69,6 +73,9 @@ uint8_t power, max_power;
char input[5];
int cursor;
+char *sync_result = NULL;
+char *sync_msg = "";
+
static struct band {
int min, max, prev, next, freq_ul, freq_dl;
} bands[] = {
@@ -108,8 +115,42 @@ int tone = 0;
unsigned long tone_time;
int tone_on = 0;
+uint8_t bsic;
+uint8_t ul_levels[8], ul_max[8]; /* 8 uplink levels */
+uint8_t si_1[23];
+uint8_t si_2[23];
+uint8_t si_2bis[23];
+uint8_t si_2ter[23];
+uint8_t si_3[23];
+uint8_t si_4[23];
+uint16_t si_new = 0, ul_new;
+uint16_t mcc, mnc, lac, cell_id;
+int nb_num;
+struct gsm_sysinfo_freq freq[1024];
+#define NEIGH_LINES ((framebuffer->height - 25) / 8)
+
+#define FREQ_TYPE_SERV 0x01 /* frequency of the serving cell */
+#define FREQ_TYPE_NCELL 0x1c /* frequency of the neighbor cell */
+#define FREQ_TYPE_NCELL_2 0x04 /* sub channel of SI 2 */
+#define FREQ_TYPE_NCELL_2bis 0x08 /* sub channel of SI 2bis */
+#define FREQ_TYPE_NCELL_2ter 0x10 /* sub channel of SI 2ter */
+
/* UI */
+static void print_display(char *text, int *y, int c)
+{
+ /* skip lines, given by cursor */
+ (*y)++;
+ if (c >= (*y))
+ return;
+ /* skip, if end of display area is reached */
+ if ((*y) - c > NEIGH_LINES)
+ return;
+
+ fb_gotoxy(0, 20 + (((*y) - c - 1) << 3));
+ fb_putstr(text, framebuffer->width);
+}
+
static void refresh_display(void)
{
char text[16];
@@ -118,21 +159,149 @@ static void refresh_display(void)
/* header */
fb_setbg(FB_COLOR_WHITE);
- if (mode != MODE_SPECTRUM) {
+ if (mode != MODE_SPECTRUM && !(mode == MODE_SYNC && cursor < 0)) {
fb_setfg(FB_COLOR_BLUE);
fb_setfont(FB_FONT_HELVR08);
- fb_gotoxy(0,6);
+ fb_gotoxy(0, 7);
fb_putstr("Osmocom Monitor Tool",-1);
- fb_gotoxy(0,10);
- fb_setfg(FB_COLOR_BLACK);
- fb_boxto(framebuffer->width-1,10);
+ fb_gotoxy(0, 10);
+ fb_setfg(FB_COLOR_GREEN);
+ fb_boxto(framebuffer->width - 1, 10);
}
fb_setfg(FB_COLOR_BLACK);
fb_setfont(FB_FONT_C64);
+ /* SYNC / UL levels */
+ if (mode == MODE_SYNC && cursor < 0) {
+ int i, tn, l;
+ int offset = (framebuffer->width - 96) >> 2;
+ int height = framebuffer->height - 25;
+
+ fb_setfont(FB_FONT_HELVR08);
+ for (i = 0; i < 8; i++) {
+ if (uplink)
+ tn = (i + 3) & 7; /* UL is shifted by 3 */
+ else
+ tn = i;
+ fb_setbg(FB_COLOR_WHITE);
+ fb_gotoxy(offset + 12 * i, 7);
+ l = (max) ? ul_max[tn] : ul_levels[tn];
+ l = 110 - l;
+ if (l >= 100)
+ l -= 100;
+ sprintf(text, "%02d", l);
+ fb_putstr(text,framebuffer->width);
+ fb_setbg(FB_COLOR_BLACK);
+ fb_gotoxy(offset + 3 + 12 * i, height + 10);
+ fb_boxto(offset + 3 + 12 * i + 5, height + 10 - ul_levels[tn] * height / 64);
+ if (max) {
+ fb_gotoxy(offset + 3 + 12 * i, height + 10 - ul_max[tn] * height / 64);
+ fb_boxto(offset + 3 + 12 * i + 5, height + 10 - ul_max[tn] * height / 64);
+ }
+ }
+ fb_setbg(FB_COLOR_TRANSP);
+ if (max) {
+ fb_setfg(FB_COLOR_RED);
+ fb_gotoxy(framebuffer->width - 16, 15);
+ fb_putstr("max", framebuffer->width);
+ }
+ fb_setfont(FB_FONT_C64);
+ fb_setfg(FB_COLOR_BLUE);
+ fb_gotoxy(0, 16);
+ if (pcs && ul_arfcn >= PCS_MIN && ul_arfcn <= PCS_MAX)
+ sprintf(text, "%4dP", ul_arfcn);
+ else if (ul_arfcn >= DCS_MIN && ul_arfcn <= DCS_MAX)
+ sprintf(text, "%4dD", ul_arfcn);
+ else
+ sprintf(text, "%4d ", ul_arfcn);
+ fb_putstr(text, framebuffer->width);
+ fb_setbg(FB_COLOR_WHITE);
+ fb_setfg(FB_COLOR_BLACK);
+ }
+
+ /* SYNC / SI */
+ if (mode == MODE_SYNC && cursor == 0) {
+ fb_gotoxy(0, 20);
+ if (sync_msg[0] == 'o')
+ sprintf(text, "BSIC%d/%d %4d", bsic >> 3, bsic & 7,
+ power - 110);
+ else
+ sprintf(text, "Sync %s", sync_msg);
+ fb_putstr(text, -1);
+
+ fb_gotoxy(0,28);
+ text[0] = si_1[2] ? '1' : '-';
+ text[1] = ' ';
+ text[2] = si_2[2] ? '2' : '-';
+ text[3] = ' ';
+ text[4] = si_2bis[2] ? '2' : '-';
+ text[5] = si_2bis[2] ? 'b' : ' ';
+ text[6] = si_2ter[2] ? '2' : '-';
+ text[7] = si_2ter[2] ? 't' : ' ';
+ text[8] = ' ';
+ text[9] = si_3[2] ? '3' : '-';
+ text[10] = ' ';
+ text[11] = si_4[2] ? '4' : '-';
+ text[12] = '\0';
+ fb_putstr(text, -1);
+
+ fb_gotoxy(0, 36);
+ fb_putstr("MCC MNC LAC ", -1);
+ fb_gotoxy(0, 44);
+ if (mcc) {
+ if ((mnc & 0x00f) == 0x00f)
+ sprintf(text, "%3x %02x %04x", mcc, mnc >> 4, lac);
+ else
+ sprintf(text, "%3x %03x %04x", mcc, mnc, lac);
+ fb_putstr(text, -1);
+ } else
+ fb_putstr("--- --- ----", -1);
+ fb_gotoxy(0, 52);
+ if (si_3[2]) {
+ sprintf(text, "cell id:%04x", cell_id);
+ fb_putstr(text, -1);
+ } else
+ fb_putstr("cell id:----", -1);
+ }
+
+ /* SYNC / neighbour cells */
+ if (mode == MODE_SYNC && cursor > 0) {
+ int i, y = 0;
+
+ text[0] = '\0';
+ for (i = 0; i < 1024; i++) {
+ if (freq[i].mask & FREQ_TYPE_SERV) {
+ if (!text[0])
+ sprintf(text, "S: %4d", i);
+ else {
+ sprintf(text + 7, " %4d", i);
+ print_display(text, &y, cursor - 1);
+ text[0] = '\0';
+ }
+ }
+ }
+ if (text[0])
+ print_display(text, &y, cursor - 1);
+ text[0] = '\0';
+ for (i = 0; i < 1024; i++) {
+ if (freq[i].mask & FREQ_TYPE_NCELL) {
+ if (!text[0])
+ sprintf(text, "N: %4d", i);
+ else {
+ sprintf(text + 7, " %4d", i);
+ print_display(text, &y, cursor - 1);
+ text[0] = '\0';
+ }
+ }
+ }
+ if (text[0])
+ print_display(text, &y, cursor - 1);
+ nb_num = y;
+ }
+
/* ARFCN */
if (mode == MODE_MAIN || mode == MODE_ARFCN) {
- fb_gotoxy(0,20);
+ fb_gotoxy(0, 20);
if (mode == MODE_ARFCN)
sprintf(text, "ARFCN %s", input);
else if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX)
@@ -156,7 +325,7 @@ static void refresh_display(void)
/* Frequency / power */
if (mode == MODE_MAIN) {
int f;
-
+
if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX) {
if (uplink)
f = PCS_UL;
@@ -168,21 +337,23 @@ static void refresh_display(void)
f = band->freq_dl;
f += ((arfcn - band->min) & 1023) << 1;
- fb_gotoxy(0,30);
+ fb_gotoxy(0, 30);
sprintf(text, "Freq. %d.%d", f / 10, f % 10);
fb_putstr(text,framebuffer->width);
- fb_gotoxy(0,40);
+ fb_gotoxy(0, 40);
sprintf(text, "Power %d", ((max) ? max_power : power) - 110);
- fb_putstr(text,framebuffer->width);
+ fb_putstr(text, framebuffer->width);
if (max) {
fb_setfont(FB_FONT_HELVR08);
- fb_gotoxy(80,39);
- fb_putstr("max",framebuffer->width);
+ fb_setfg(FB_COLOR_RED);
+ fb_gotoxy(framebuffer->width - 16, 39);
+ fb_putstr("max", framebuffer->width);
fb_setfont(FB_FONT_C64);
+ fb_setfg(FB_COLOR_BLACK);
}
fb_setbg(FB_COLOR_BLACK);
- fb_gotoxy(0,45);
+ fb_gotoxy(0, 45);
fb_boxto(framebuffer->width * power / 64, 50);
if (max) {
fb_gotoxy(framebuffer->width * max_power / 64 ,45);
@@ -195,29 +366,32 @@ static void refresh_display(void)
if (mode == MODE_SPECTRUM) {
int i;
uint16_t a, e, p;
+ int height = framebuffer->height - 25;
- fb_gotoxy(0,8);
+ fb_gotoxy(0, 8);
if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX)
sprintf(text, "%4dP", arfcn);
else if (arfcn >= DCS_MIN && arfcn <= DCS_MAX)
sprintf(text, "%4dD", arfcn);
else
sprintf(text, "%4d ", arfcn);
- sprintf(text + 5, " %d", pm_spectrum[arfcn & 1023] - 110);
- fb_putstr(text,framebuffer->width);
+ sprintf(text + 5, " %4d", pm_spectrum[arfcn & 1023] - 110);
+ fb_putstr(text, -1);
+ fb_setfg(FB_COLOR_RED);
if (max) {
fb_setfont(FB_FONT_HELVR08);
- fb_gotoxy(80,15);
- fb_putstr("max",framebuffer->width);
+ fb_gotoxy(framebuffer->width - 16,15);
+ fb_putstr("max", framebuffer->width);
fb_setfont(FB_FONT_C64);
}
if (pm_scale != 1) {
fb_setfont(FB_FONT_HELVR08);
- fb_gotoxy(1,15);
+ fb_gotoxy(1, 15);
sprintf(text, "x%d", pm_scale);
- fb_putstr(text,framebuffer->width);
+ fb_putstr(text, framebuffer->width);
fb_setfont(FB_FONT_C64);
}
+ fb_setfg(FB_COLOR_BLACK);
if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX) {
a = PCS_MIN;
e = PCS_MAX;
@@ -225,40 +399,52 @@ static void refresh_display(void)
a = band->min;
e = band->max;
}
- for (i = 0; i < framebuffer->width - 1; i++) {
+ for (i = 0; i < framebuffer->width; i++) {
p = (arfcn + i - (framebuffer->width >> 1)) & 1023;
if ((((p - a) & 1023) & 512))
continue;
if ((((e - p) & 1023) & 512))
continue;
- p = (pm_spectrum[p] * pm_scale * 40 / 64);
- if (p > 40)
- p = 40;
- fb_gotoxy(i, 50 - p);
- fb_boxto(i, 50);
+ p = (pm_spectrum[p] * pm_scale * height / 64);
+ if (p > height)
+ p = height;
+ if (i == (framebuffer->width >> 1))
+ fb_setfg(FB_COLOR_RED);
+ fb_gotoxy(i, height + 10 - p);
+ fb_boxto(i, height + 10);
+ if (i == (framebuffer->width >> 1))
+ fb_setfg(FB_COLOR_BLACK);
}
i = framebuffer->width >> 1;
fb_gotoxy(i, 0);
fb_boxto(i, 4);
- fb_gotoxy(i, 50);
- fb_boxto(i, 54);
+ fb_gotoxy(i, height + 10);
+ fb_boxto(i, height + 14);
}
/* footer */
- fb_gotoxy(0,55);
- fb_boxto(framebuffer->width-1,55);
- fb_gotoxy(0,64);
+ fb_setfg(FB_COLOR_GREEN);
+ fb_gotoxy(0, framebuffer->height - 10);
+ fb_boxto(framebuffer->width-1, framebuffer->height - 10);
+ fb_gotoxy(0, framebuffer->height - 1);
+ fb_setfg(FB_COLOR_RED);
if (mode == MODE_ARFCN)
sprintf(text, "%s %s", (cursor) ? "del " : "back",
(cursor) ? "enter" : " ");
+ else if (mode == MODE_SYNC && cursor < 0)
+ sprintf(text, "%s %s", "back",
+ (uplink) ? "UL" : "DL");
+ else if (mode == MODE_SYNC)
+ sprintf(text, "%s ", "back");
else
sprintf(text, "%s %s", (pcs) ? "PCS" : "DCS",
(uplink) ? "UL" : "DL");
- fb_putstr(text,framebuffer->width);
+ fb_putstr(text, -1);
+ fb_setfg(FB_COLOR_BLACK);
fb_setfont(FB_FONT_HELVR08);
- fb_gotoxy(0,63);
+ fb_gotoxy(0, framebuffer->height - 2);
sprintf(text, "%d", tone / 25);
- fb_putstr(text,-1);
+ fb_putstr(text, -1);
fb_flush();
}
@@ -294,7 +480,7 @@ static void enter_arfcn(enum key_codes code)
refresh_display();
return;
}
-
+
if (code == KEY_RIGHT_SB) {
int check = 0;
int i;
@@ -390,6 +576,35 @@ static int inc_dec_arfcn(int inc)
return 0;
}
+static void request_ul_levels(uint16_t a);
+
+static int inc_dec_ul_arfcn(int inc)
+{
+ uint16_t a;
+
+ /* loop until we hit a serving cell or our current bcch arfcn */
+ if (inc) {
+ for (a = (ul_arfcn + 1) & 1023; a != (arfcn & 1023);
+ a = (a + 1) & 1023) {
+ if ((freq[a].mask & FREQ_TYPE_SERV))
+ break;
+ }
+ } else {
+ for (a = (ul_arfcn - 1) & 1023; a != (arfcn & 1023);
+ a = (a - 1) & 1023) {
+ if ((freq[a].mask & FREQ_TYPE_SERV))
+ break;
+ }
+ }
+ ul_arfcn = a;
+
+ refresh_display();
+
+ request_ul_levels(a);
+
+ return 0;
+}
+
static void toggle_dcs_pcs(void)
{
pcs = !pcs;
@@ -400,6 +615,9 @@ static void toggle_up_down(void)
{
uplink = !uplink;
refresh_display();
+
+ if (mode == MODE_SYNC && cursor < 0)
+ request_ul_levels(ul_arfcn);
}
static void toggle_spectrum(void)
@@ -437,6 +655,23 @@ static void hold_max(void)
refresh_display();
}
+static int inc_dec_neighbour(int inc)
+{
+ if (inc) {
+ if (cursor > 0 && cursor - 1 >= (nb_num - NEIGH_LINES))
+ return -EINVAL;
+ cursor++;
+ } else {
+ if (cursor < 0)
+ return -EINVAL;
+ cursor--;
+ }
+
+ refresh_display();
+
+ return 0;
+}
+
static int inc_dec_spectrum(int inc)
{
if (inc) {
@@ -454,6 +689,9 @@ static int inc_dec_spectrum(int inc)
return 0;
}
+static void enter_sync(void);
+static void exit_sync(void);
+
static void handle_key_code()
{
/* key repeat */
@@ -493,34 +731,52 @@ static void handle_key_code()
case KEY_UP:
if (mode == MODE_MAIN)
tone_inc_dec(1);
+ else if (mode == MODE_SYNC)
+ inc_dec_neighbour(0);
else if (mode == MODE_SPECTRUM)
inc_dec_spectrum(1);
break;
case KEY_DOWN:
if (mode == MODE_MAIN)
tone_inc_dec(0);
+ else if (mode == MODE_SYNC)
+ inc_dec_neighbour(1);
else if (mode == MODE_SPECTRUM)
inc_dec_spectrum(0);
break;
case KEY_RIGHT:
if (mode == MODE_MAIN || mode == MODE_SPECTRUM)
inc_dec_arfcn(1);
+ else if (mode == MODE_SYNC && cursor < 0)
+ inc_dec_ul_arfcn(1);
break;
case KEY_LEFT:
if (mode == MODE_MAIN || mode == MODE_SPECTRUM)
inc_dec_arfcn(0);
+ else if (mode == MODE_SYNC && cursor < 0)
+ inc_dec_ul_arfcn(0);
break;
case KEY_LEFT_SB:
if (mode == MODE_MAIN || mode == MODE_SPECTRUM)
toggle_dcs_pcs();
else if (mode == MODE_ARFCN)
enter_arfcn(key_code);
+ else if (mode == MODE_SYNC)
+ exit_sync();
break;
case KEY_RIGHT_SB:
if (mode == MODE_MAIN || mode == MODE_SPECTRUM)
toggle_up_down();
else if (mode == MODE_ARFCN)
enter_arfcn(key_code);
+ else if (mode == MODE_SYNC && cursor < 0)
+ toggle_up_down();
+ break;
+ case KEY_OK:
+ if (mode == MODE_MAIN || mode == MODE_SPECTRUM)
+ enter_sync();
+ else if (mode == MODE_SYNC)
+ exit_sync();
break;
case KEY_MENU:
hold_max();
@@ -528,6 +784,8 @@ static void handle_key_code()
case KEY_POWER:
if (mode == MODE_ARFCN)
exit_arfcn();
+ else if (mode == MODE_SYNC)
+ exit_sync();
else if (mode == MODE_SPECTRUM)
toggle_spectrum();
break;
@@ -648,6 +906,190 @@ static void handle_pm(void)
}
}
+/* sync / SI */
+
+static void enter_sync(void)
+{
+ struct msgb *msg = l1ctl_msgb_alloc(L1CTL_FBSB_REQ);
+ struct l1ctl_fbsb_req *req;
+ uint16_t a = arfcn;
+
+ l1s_reset();
+ l1s_reset_hw();
+ pm_count = 0;
+ pm_mode = PM_IDLE;
+
+ req = (struct l1ctl_fbsb_req *) msgb_put(msg, sizeof(*req));
+ if (pcs && arfcn >= PCS_MIN && arfcn <= PCS_MAX)
+ a |= ARFCN_PCS;
+ req->band_arfcn = htons(a);
+ req->timeout = htons(100);
+ /* Threshold when to consider FB_MODE1: 4kHz - 1kHz */
+ req->freq_err_thresh1 = htons(11000 - 1000);
+ /* Threshold when to consider SCH: 1kHz - 200Hz */
+ req->freq_err_thresh2 = htons(1000 - 200);
+ /* not used yet! */
+ req->num_freqerr_avg = 3;
+ req->flags = L1CTL_FBSB_F_FB01SB;
+ req->sync_info_idx = 0;
+ req->ccch_mode = CCCH_MODE_NONE;
+ l1a_l23_rx(SC_DLCI_L1A_L23, msg);
+
+ mode = MODE_SYNC;
+ memset(ul_levels, 0, sizeof(ul_levels));
+ si_new = 0;
+ ul_new = 0;
+ ul_arfcn = arfcn;
+ si_1[2] = 0;
+ si_2[2] = 0;
+ si_2bis[2] = 0;
+ si_2ter[2] = 0;
+ si_3[2] = 0;
+ si_4[2] = 0;
+ mcc = mnc = lac = 0;
+ memset(freq, 0, sizeof(freq));
+ cursor = 0;
+ nb_num = 0;
+ sync_msg = "trying";
+ refresh_display();
+}
+
+static void exit_sync(void)
+{
+ l1s_reset();
+ l1s_reset_hw();
+ pm_count = 0;
+ pm_mode = PM_IDLE;
+ mode = MODE_MAIN;
+}
+
+int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *_mcc,
+uint16_t *_mnc, uint16_t *_lac)
+{
+ *_mcc = ((lai->digits[0] & 0x0f) << 8)
+ | (lai->digits[0] & 0xf0)
+ | (lai->digits[1] & 0x0f);
+ *_mnc = ((lai->digits[2] & 0x0f) << 8)
+ | (lai->digits[2] & 0xf0)
+ | ((lai->digits[1] & 0xf0) >> 4);
+ *_lac = ntohs(lai->lac);
+
+ return 0;
+}
+
+static void request_ul_levels(uint16_t a)
+{
+ struct msgb *msg = l1ctl_msgb_alloc(L1CTL_NEIGH_PM_REQ);
+ struct l1ctl_neigh_pm_req *pm_req =
+ (struct l1ctl_neigh_pm_req *) msgb_put(msg, sizeof(*pm_req));
+ int i;
+
+ if (pcs && a >= PCS_MIN && a <= PCS_MAX)
+ a |= ARFCN_PCS;
+ if (uplink)
+ a |= ARFCN_UPLINK;
+ pm_req->n = 8;
+ for (i = 0; i < 8; i++) {
+ pm_req->band_arfcn[i] = htons(a);
+ pm_req->tn[i] = i;
+ }
+ l1a_l23_rx(SC_DLCI_L1A_L23, msg);
+}
+
+static void handle_sync(void)
+{
+ struct gsm48_system_information_type_1 *si1;
+ struct gsm48_system_information_type_2 *si2;
+ struct gsm48_system_information_type_2bis *si2bis;
+ struct gsm48_system_information_type_2ter *si2ter;
+ struct gsm48_system_information_type_3 *si3;
+ struct gsm48_system_information_type_4 *si4;
+
+ if (mode != MODE_SYNC)
+ return;
+
+ /* once we synced, we take the result and request UL measurement */
+ if (sync_result) {
+ uint16_t a = ul_arfcn;
+
+ sync_msg = sync_result;
+ sync_result = NULL;
+ refresh_display();
+
+ if (sync_msg[0] != 'o')
+ return;
+
+ request_ul_levels(a);
+
+ return;
+ }
+
+ if (tone_on)
+ return;
+
+ /* no UL result, no SI result */
+ if (!ul_new && !(si_new & 0x100))
+ return;
+
+ /* new UL result */
+ if (ul_new) {
+ ul_new = 0;
+ if (cursor < 0)
+ refresh_display();
+ return;
+ }
+
+ /* decode si */
+ switch (si_new & 0xff) {
+ case GSM48_MT_RR_SYSINFO_1:
+ si1 = (struct gsm48_system_information_type_1 *)si_1;
+ gsm48_decode_freq_list(freq, si1->cell_channel_description,
+ sizeof(si1->cell_channel_description), 0xce,
+ FREQ_TYPE_SERV);
+ break;
+ case GSM48_MT_RR_SYSINFO_2:
+ si2 = (struct gsm48_system_information_type_2 *)si_2;
+ gsm48_decode_freq_list(freq, si2->bcch_frequency_list,
+ sizeof(si2->bcch_frequency_list), 0xce,
+ FREQ_TYPE_NCELL_2);
+ break;
+ case GSM48_MT_RR_SYSINFO_2bis:
+ si2bis = (struct gsm48_system_information_type_2bis *)si_2bis;
+ gsm48_decode_freq_list(freq, si2bis->bcch_frequency_list,
+ sizeof(si2bis->bcch_frequency_list), 0xce,
+ FREQ_TYPE_NCELL_2bis);
+ break;
+ case GSM48_MT_RR_SYSINFO_2ter:
+ si2ter = (struct gsm48_system_information_type_2ter *)si_2ter;
+ gsm48_decode_freq_list(freq, si2ter->ext_bcch_frequency_list,
+ sizeof(si2ter->ext_bcch_frequency_list), 0x8e,
+ FREQ_TYPE_NCELL_2ter);
+ break;
+ case GSM48_MT_RR_SYSINFO_3:
+ si3 = (struct gsm48_system_information_type_3 *)si_3;
+ gsm48_decode_lai(&si3->lai, &mcc, &mnc, &lac);
+ cell_id = ntohs(si3->cell_identity);
+ break;
+ case GSM48_MT_RR_SYSINFO_4:
+ si4 = (struct gsm48_system_information_type_4 *)si_4;
+ gsm48_decode_lai(&si4->lai, &mcc, &mnc, &lac);
+ break;
+ }
+
+ if (cursor >= 0)
+ refresh_display();
+
+ /* tone depends on successfully received BCCH */
+ buzzer_volume(tone);
+ tone_time = jiffies;
+ tone_on = 1;
+ if ((si_new & 0xff) == 0xff)
+ buzzer_note(NOTE(NOTE_C, OCTAVE_2));
+ else
+ buzzer_note(NOTE(NOTE_C, OCTAVE_5));
+ si_new = 0;
+}
+
/* Main Program */
const char *hr = "======================================================================\n";
@@ -656,6 +1098,11 @@ static void l1a_l23_tx(struct msgb *msg)
{
struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->l1h;
struct l1ctl_pm_conf *pmr;
+ struct l1ctl_info_dl *dl;
+ struct l1ctl_fbsb_conf *sb;
+ uint8_t chan_type, chan_ts, chan_ss;
+ struct gsm48_system_information_type_header *sih;
+ struct l1ctl_neigh_pm_ind *pm_ind;
switch (l1h->msg_type) {
case L1CTL_PM_CONF:
@@ -676,6 +1123,65 @@ static void l1a_l23_tx(struct msgb *msg)
}
l1s.tpu_offset_correction += 5000 / NUM_PM_UL;
break;
+ case L1CTL_FBSB_CONF:
+ dl = (struct l1ctl_info_dl *) l1h->data;
+ sb = (struct l1ctl_fbsb_conf *) dl->payload;
+ if (sb->result == 0)
+ sync_result = "ok";
+ else
+ sync_result = "error";
+ bsic = sb->bsic;
+ break;
+ case L1CTL_DATA_IND:
+ dl = (struct l1ctl_info_dl *) l1h->data;
+ msg->l2h = dl->payload;
+ rsl_dec_chan_nr(dl->chan_nr, &chan_type, &chan_ss, &chan_ts);
+ if (chan_type != RSL_CHAN_BCCH)
+ break;
+ msg->l3h = msg->l2h;
+
+ power = dl->rx_level;
+ if (dl->fire_crc >= 2) {
+ si_new = 0x1ff; /* error frame indication */
+ break;
+ }
+
+ /* store SI */
+ sih = msgb_l3(msg);
+ switch (sih->system_information) {
+ case GSM48_MT_RR_SYSINFO_1:
+ memcpy(si_1, msgb_l3(msg), msgb_l3len(msg));
+ break;
+ case GSM48_MT_RR_SYSINFO_2:
+ memcpy(si_2, msgb_l3(msg), msgb_l3len(msg));
+ break;
+ case GSM48_MT_RR_SYSINFO_2bis:
+ memcpy(si_2bis, msgb_l3(msg), msgb_l3len(msg));
+ break;
+ case GSM48_MT_RR_SYSINFO_2ter:
+ memcpy(si_2ter, msgb_l3(msg), msgb_l3len(msg));
+ break;
+ case GSM48_MT_RR_SYSINFO_3:
+ memcpy(si_3, msgb_l3(msg), msgb_l3len(msg));
+ break;
+ case GSM48_MT_RR_SYSINFO_4:
+ memcpy(si_4, msgb_l3(msg), msgb_l3len(msg));
+ break;
+ }
+ si_new = sih->system_information | 0x100;
+ sercomm_sendmsg(SC_DLCI_L1A_L23, msg);
+ return; /* msg is freed by sercom */
+ case L1CTL_NEIGH_PM_IND:
+ for (pm_ind = (struct l1ctl_neigh_pm_ind *) l1h->data;
+ (uint8_t *) pm_ind < msg->tail; pm_ind++) {
+ ul_levels[pm_ind->tn] = pm_ind->pm[0];
+ /* hold max only, if max enabled and level is lower */
+ if (!max || ul_levels[pm_ind->tn] > ul_max[pm_ind->tn])
+ ul_max[pm_ind->tn] = ul_levels[pm_ind->tn];
+ if (pm_ind->tn == 7)
+ ul_new = 1;
+ }
+ break;
}
msgb_free(msg);
@@ -754,6 +1260,7 @@ int main(void)
buzzer_volume(0);
memset(pm_spectrum, 0, sizeof(pm_spectrum));
+ memset(ul_max, 0, sizeof(ul_max));
/* inc 0 to 1 and refresh */
inc_dec_arfcn(1);
@@ -764,6 +1271,7 @@ int main(void)
handle_key_code();
l1a_l23_handler();
handle_pm();
+ handle_sync();
handle_tone();
}