summaryrefslogtreecommitdiffstats
path: root/src/target/firmware/apps
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2012-01-31 08:13:06 +0100
committerHarald Welte <laforge@gnumonks.org>2012-02-07 20:03:02 +0100
commitd0985a7ff217f7fe928500ad761af3a45f271b73 (patch)
treed9fde56a21c4c309a0cc6910526d8b6217fa1ded /src/target/firmware/apps
parent0cb791a125bcd1b152bdede5f82d6906031c30e8 (diff)
firmware/monitor: Added channel request to measure distance from cell
When synced, press the green button to request channel from cell. The result, timing advance, distance and response delay is printed on the display. It only works, if TX is enabled and SI 3 has been received.
Diffstat (limited to 'src/target/firmware/apps')
-rw-r--r--src/target/firmware/apps/rssi/main.c330
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();
}