diff options
-rw-r--r-- | src/target/firmware/apps/rssi/main.c | 330 |
1 files changed, 296 insertions, 34 deletions
diff --git a/src/target/firmware/apps/rssi/main.c b/src/target/firmware/apps/rssi/main.c index ea8bbb49..a8a4b1ac 100644 --- a/src/target/firmware/apps/rssi/main.c +++ b/src/target/firmware/apps/rssi/main.c @@ -62,6 +62,7 @@ enum mode { MODE_SPECTRUM, MODE_ARFCN, MODE_SYNC, + MODE_RACH, } mode = MODE_MAIN; enum mode last_mode; /* where to return after entering ARFCN */ @@ -110,7 +111,7 @@ int pm_max = 2; uint8_t pm_spectrum[1024]; int pm_scale = 1; /* scale measured power level */ -#define TONE_JIFFIES 4 +#define TONE_JIFFIES ((HZ < 25) ? 1 : HZ / 25) int tone = 0; unsigned long tone_time; int tone_on = 0; @@ -125,6 +126,7 @@ 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 ccch_conf; int nb_num; struct gsm_sysinfo_freq freq[1024]; #define NEIGH_LINES ((framebuffer->height - 25) / 8) @@ -135,6 +137,20 @@ struct gsm_sysinfo_freq freq[1024]; #define FREQ_TYPE_NCELL_2bis 0x08 /* sub channel of SI 2bis */ #define FREQ_TYPE_NCELL_2ter 0x10 /* sub channel of SI 2ter */ +int rach = 0; +struct gsm48_req_ref rach_ref; +uint8_t rach_ra; +unsigned long rach_when; +uint8_t ta; + +enum assign { + ASSIGN_NONE, + ASSIGN_NO_TX, + ASSIGN_RESULT, + ASSIGN_REJECT, + ASSIGN_TIMEOUT, +} assign; + /* UI */ static void print_display(char *text, int *y, int c) @@ -163,7 +179,7 @@ static void refresh_display(void) fb_setfg(FB_COLOR_BLUE); fb_setfont(FB_FONT_HELVR08); fb_gotoxy(0, 7); - fb_putstr("Osmocom Monitor Tool",-1); + fb_putstr("Osmocom Monitor Tool", -1); fb_gotoxy(0, 10); fb_setfg(FB_COLOR_GREEN); fb_boxto(framebuffer->width - 1, 10); @@ -171,6 +187,44 @@ static void refresh_display(void) fb_setfg(FB_COLOR_BLACK); fb_setfont(FB_FONT_C64); + /* RACH */ + if (mode == MODE_RACH) { + unsigned long elapsed = jiffies - rach_when; + + fb_gotoxy(0,28); + switch (assign) { + case ASSIGN_NONE: + fb_putstr("Rach sent...", -1); + break; + case ASSIGN_RESULT: + sprintf(text, "TA = %d", ta); + fb_putstr(text, -1); + fb_gotoxy(0,36); + sprintf(text, "(%dm)", ta * 554); + fb_putstr(text, -1); + break; + case ASSIGN_REJECT: + fb_putstr("Rejected!", -1); + break; + case ASSIGN_NO_TX: + fb_putstr("TX disabled", -1); + break; + case ASSIGN_TIMEOUT: + fb_putstr("Timeout", -1); + break; + } + switch (assign) { + case ASSIGN_RESULT: + case ASSIGN_REJECT: + fb_gotoxy(0,44); + sprintf(text, "Delay:%ldms", elapsed * 1000 / HZ); + fb_putstr(text, -1); + break; + default: + break; + } + } + /* SYNC / UL levels */ if (mode == MODE_SYNC && cursor < 0) { int i, tn, l; @@ -190,7 +244,7 @@ static void refresh_display(void) if (l >= 100) l -= 100; sprintf(text, "%02d", l); - fb_putstr(text,framebuffer->width); + 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); @@ -434,7 +488,7 @@ static void refresh_display(void) else if (mode == MODE_SYNC && cursor < 0) sprintf(text, "%s %s", "back", (uplink) ? "UL" : "DL"); - else if (mode == MODE_SYNC) + else if (mode == MODE_SYNC || mode == MODE_RACH) sprintf(text, "%s ", "back"); else sprintf(text, "%s %s", (pcs) ? "PCS" : "DCS", @@ -692,6 +746,9 @@ static int inc_dec_spectrum(int inc) static void enter_sync(void); static void exit_sync(void); +static void enter_rach(void); +static void exit_rach(void); + static void handle_key_code() { /* key repeat */ @@ -699,7 +756,7 @@ static void handle_key_code() unsigned long elapsed = jiffies - key_pressed_when; if (elapsed > key_pressed_delay) { key_pressed_when = jiffies; - key_pressed_delay = 10; + key_pressed_delay = HZ / 10; /* only repeat these keys */ if (key_pressed_code == KEY_LEFT || key_pressed_code == KEY_RIGHT) @@ -763,6 +820,8 @@ static void handle_key_code() enter_arfcn(key_code); else if (mode == MODE_SYNC) exit_sync(); + else if (mode == MODE_RACH) + exit_rach(); break; case KEY_RIGHT_SB: if (mode == MODE_MAIN || mode == MODE_SPECTRUM) @@ -775,8 +834,8 @@ static void handle_key_code() case KEY_OK: if (mode == MODE_MAIN || mode == MODE_SPECTRUM) enter_sync(); - else if (mode == MODE_SYNC) - exit_sync(); + else if (mode == MODE_SYNC || mode == MODE_RACH) + enter_rach(); break; case KEY_MENU: hold_max(); @@ -786,6 +845,8 @@ static void handle_key_code() exit_arfcn(); else if (mode == MODE_SYNC) exit_sync(); + else if (mode == MODE_RACH) + exit_rach(); else if (mode == MODE_SPECTRUM) toggle_spectrum(); break; @@ -947,6 +1008,7 @@ static void enter_sync(void) si_3[2] = 0; si_4[2] = 0; mcc = mnc = lac = 0; + ccch_conf = -1; memset(freq, 0, sizeof(freq)); cursor = 0; nb_num = 0; @@ -1069,6 +1131,21 @@ static void handle_sync(void) si3 = (struct gsm48_system_information_type_3 *)si_3; gsm48_decode_lai(&si3->lai, &mcc, &mnc, &lac); cell_id = ntohs(si3->cell_identity); + if (ccch_conf < 0) { + struct msgb *msg = + l1ctl_msgb_alloc(L1CTL_CCCH_MODE_REQ); + struct l1ctl_ccch_mode_req *req = + (struct l1ctl_ccch_mode_req *) + msgb_put(msg, sizeof(*req)); + + ccch_conf = si3->control_channel_desc.ccch_conf; + req->ccch_mode = (ccch_conf == 1) + ? CCCH_MODE_COMBINED + : CCCH_MODE_NON_COMBINED; + printf("ccch_mode=%d\n", ccch_conf); + + l1a_l23_rx(SC_DLCI_L1A_L23, msg); + } break; case GSM48_MT_RR_SYSINFO_4: si4 = (struct gsm48_system_information_type_4 *)si_4; @@ -1090,9 +1167,200 @@ static void handle_sync(void) si_new = 0; } +static void enter_rach(void) +{ + if (ccch_conf < 0) + return; + + if (rach) + return; + +#ifndef CONFIG_TX_ENABLE + assign = ASSIGN_NO_TX; + mode = MODE_RACH; + /* display refresh is done by rach handler */ +#else + struct msgb *msg1 = l1ctl_msgb_alloc(L1CTL_NEIGH_PM_REQ); + struct msgb *msg2 = l1ctl_msgb_alloc(L1CTL_RACH_REQ); + struct l1ctl_neigh_pm_req *pm_req = (struct l1ctl_neigh_pm_req *) + msgb_put(msg1, sizeof(*pm_req)); + struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) + msgb_put(msg2, sizeof(*ul));; + struct l1ctl_rach_req *rach_req = (struct l1ctl_rach_req *) + msgb_put(msg2, sizeof(*rach_req)); + + l1s.tx_power = 0; + + pm_req->n = 0; /* disable */ + + rach_ra = 0x00; + rach_req->ra = rach_ra; + rach_req->offset = 0; + rach_req->combined = (ccch_conf == 1); + + l1a_l23_rx(SC_DLCI_L1A_L23, msg1); + l1a_l23_rx(SC_DLCI_L1A_L23, msg2); + rach = 1; + rach_when = jiffies; + assign = ASSIGN_NONE; + mode = MODE_RACH; + refresh_display(); +#endif + +} + +static void exit_rach(void) +{ + rach = 0; + + request_ul_levels(ul_arfcn); + + mode = MODE_SYNC; + refresh_display(); +} + +static void handle_assign(void) +{ + if (mode != MODE_RACH) + return; + + if (assign == ASSIGN_NONE) { + unsigned long elapsed = jiffies - rach_when; + + if (!rach) + return; + if (elapsed < HZ * 2) + return; + assign = ASSIGN_TIMEOUT; + rach = 0; + } + + refresh_display(); + assign = ASSIGN_NONE; +} + /* Main Program */ const char *hr = "======================================================================\n"; +/* match request reference agains request history */ +static int gsm48_match_ra(struct gsm48_req_ref *ref) +{ + uint8_t ia_t1, ia_t2, ia_t3; + uint8_t cr_t1, cr_t2, cr_t3; + + if (rach && ref->ra == rach_ra) { + ia_t1 = ref->t1; + ia_t2 = ref->t2; + ia_t3 = (ref->t3_high << 3) | ref->t3_low; + ref = &rach_ref; + cr_t1 = ref->t1; + cr_t2 = ref->t2; + cr_t3 = (ref->t3_high << 3) | ref->t3_low; + if (ia_t1 == cr_t1 && ia_t2 == cr_t2 && ia_t3 == cr_t3) + return 1; + } + + return 0; +} + + +/* note: called from IRQ context */ +static void rx_imm_ass(struct msgb *msg) +{ + struct gsm48_imm_ass *ia = msgb_l3(msg); + + if (gsm48_match_ra(&ia->req_ref)) { + assign = ASSIGN_RESULT; + ta = ia->timing_advance; + rach = 0; + } +} + +/* note: called from IRQ context */ +static void rx_imm_ass_ext(struct msgb *msg) +{ + struct gsm48_imm_ass_ext *ia = msgb_l3(msg); + + if (gsm48_match_ra(&ia->req_ref1)) { + assign = ASSIGN_RESULT; + ta = ia->timing_advance1; + rach = 0; + } + if (gsm48_match_ra(&ia->req_ref2)) { + assign = ASSIGN_RESULT; + ta = ia->timing_advance2; + rach = 0; + } +} + +/* note: called from IRQ context */ +static void rx_imm_ass_rej(struct msgb *msg) +{ + struct gsm48_imm_ass_rej *ia = msgb_l3(msg); + struct gsm48_req_ref *req_ref; + int i; + + for (i = 0; i < 4; i++) { + /* request reference */ + req_ref = (struct gsm48_req_ref *) + (((uint8_t *)&ia->req_ref1) + i * 4); + if (gsm48_match_ra(req_ref)) { + assign = ASSIGN_REJECT; + rach = 0; + } + } +} + +/* note: called from IRQ context */ +static void rx_pch_agch(struct msgb *msg) +{ + struct gsm48_system_information_type_header *sih; + + /* store SI */ + sih = msgb_l3(msg); + switch (sih->system_information) { + case GSM48_MT_RR_IMM_ASS: + rx_imm_ass(msg); + break; + case GSM48_MT_RR_IMM_ASS_EXT: + rx_imm_ass_ext(msg); + break; + case GSM48_MT_RR_IMM_ASS_REJ: + rx_imm_ass_rej(msg); + break; + } +} + +/* note: called from IRQ context */ +static void rx_bcch(struct msgb *msg) +{ + struct gsm48_system_information_type_header *sih; + + /* 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; +} + /* note: called from IRQ context */ static void l1a_l23_tx(struct msgb *msg) { @@ -1101,8 +1369,8 @@ static void l1a_l23_tx(struct msgb *msg) 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; + struct gsm_time tm; switch (l1h->msg_type) { case L1CTL_PM_CONF: @@ -1136,39 +1404,24 @@ static void l1a_l23_tx(struct msgb *msg) 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; + if (chan_type == RSL_CHAN_BCCH) + si_new = 0x1ff; /* error frame indication */ + break; /* free, but don't send to sercom */ } - /* 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)); + switch (chan_type) { + case RSL_CHAN_BCCH: + msg->l3h = msg->l2h; + rx_bcch(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)); + case RSL_CHAN_PCH_AGCH: + msg->l3h = msg->l2h; + rx_pch_agch(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: @@ -1182,6 +1435,14 @@ static void l1a_l23_tx(struct msgb *msg) ul_new = 1; } break; + case L1CTL_RACH_CONF: + dl = (struct l1ctl_info_dl *) l1h->data; + gsm_fn2gsmtime(&tm, ntohl(dl->frame_nr)); + rach_ref.t1 = tm.t1; + rach_ref.t2 = tm.t2; + rach_ref.t3_low = tm.t3 & 0x7; + rach_ref.t3_high = tm.t3 >> 3; + break; } msgb_free(msg); @@ -1219,7 +1480,7 @@ static void key_handler(enum key_codes code, enum key_states state) key_pressed = 1; key_pressed_when = jiffies; key_pressed_code = code; - key_pressed_delay = 60; + key_pressed_delay = HZ * 6 / 10; } key_code = code; @@ -1272,6 +1533,7 @@ int main(void) l1a_l23_handler(); handle_pm(); handle_sync(); + handle_assign(); handle_tone(); } |