summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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();
}