diff options
author | Harald Welte <laforge@gnumonks.org> | 2010-03-01 11:08:38 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2010-03-01 23:48:45 +0100 |
commit | 43dd25c49355212a589be9784dd43fa11f626103 (patch) | |
tree | 4197455107e977f79d657452e943fc021b4a5e11 | |
parent | 2f60aee6d93c509926fc017a80352fff62149992 (diff) |
Include channel number and link identifier in L1 DL info
This enables the layer2 to identify on which channel
(BCCH/CCCH/SDCCH/TCH/...) the respective message was received.
* Encode MFrame Task Number + SACCH info in 'p3' parameter
* Generate channel number and link identifier
* Decode channel number in layer2 program
-rw-r--r-- | include/l1a_l23_interface.h | 8 | ||||
-rw-r--r-- | src/host/layer2/src/osmocom_layer2.c | 58 | ||||
-rw-r--r-- | src/target/firmware/include/layer1/mframe_sched.h | 6 | ||||
-rw-r--r-- | src/target/firmware/layer1/mframe_sched.c | 67 | ||||
-rw-r--r-- | src/target/firmware/layer1/sync.c | 23 |
5 files changed, 146 insertions, 16 deletions
diff --git a/include/l1a_l23_interface.h b/include/l1a_l23_interface.h index 6e94ebc1..01fcf9f7 100644 --- a/include/l1a_l23_interface.h +++ b/include/l1a_l23_interface.h @@ -50,10 +50,16 @@ struct gsm_time { * downlink info ... down from the BTS.. */ struct l1_info_dl { + /* common header, should be its own struct */ uint8_t msg_type; uint8_t padding; - /* the ARFCN and the band. */ + + /* the ARFCN and the band. FIXME: what about MAIO? */ uint16_t band_arfcn; + /* GSM 08.58 channel number (9.3.1) */ + uint8_t chan_nr; + /* GSM 08.58 link identifier (9.3.2) */ + uint8_t link_id; struct gsm_time time; uint8_t rx_level; diff --git a/src/host/layer2/src/osmocom_layer2.c b/src/host/layer2/src/osmocom_layer2.c index 66cb181e..877ce4a6 100644 --- a/src/host/layer2/src/osmocom_layer2.c +++ b/src/host/layer2/src/osmocom_layer2.c @@ -53,6 +53,7 @@ static int osmo_make_band_arfcn(struct osmocom_ms *ms) return ms->arfcn; } +static int l1_rach_req(struct osmocom_ms *ms); static int osmo_l2_ccch_resp(struct osmocom_ms *ms, struct msgb *msg) { struct l1_info_dl *dl; @@ -68,6 +69,7 @@ static int osmo_l2_ccch_resp(struct osmocom_ms *ms, struct msgb *msg) printf("Found sync burst: SNR: %u TDMA: (%.4u/%.2u/%.2u) bsic: %d\n", dl->snr[0], dl->time.t1, dl->time.t2, dl->time.t3, sb->bsic); + return 0; } @@ -158,26 +160,55 @@ static void dump_bcch(u_int8_t tc, const uint8_t *data) fprintf(stderr, "\n"); } +char *chan_nr2string(uint8_t chan_nr) +{ + static char str[20]; + uint8_t cbits = chan_nr >> 3; + + str[0] = '\0'; + + if (cbits == 0x01) + sprintf(str, "TCH/F"); + else if ((cbits & 0x1e) == 0x02) + sprintf(str, "TCH/H(%u)", cbits & 0x01); + else if ((cbits & 0x1c) == 0x04) + sprintf(str, "SDCCH/4(%u)", cbits & 0x03); + else if ((cbits & 0x18) == 0x08) + sprintf(str, "SDCCH/8(%u)", cbits & 0x07); + else if (cbits == 0x10) + sprintf(str, "BCCH"); + else if (cbits == 0x11) + sprintf(str, "RACH"); + else if (cbits == 0x12) + sprintf(str, "PCH/AGCH"); + else + sprintf(str, "UNKNOWN"); + + return str; +} + static int osmo_l2_ccch_data(struct osmocom_ms *ms, struct msgb *msg) { struct l1_info_dl *dl; struct l1_ccch_info_ind *ccch; if (msgb_l3len(msg) < sizeof(*ccch)) { - fprintf(stderr, "MSG too short CCCH Data Ind: %u\n", msgb_l3len(msg)); + fprintf(stderr, "MSG too short DCCH Data Ind: %u\n", msgb_l3len(msg)); return -1; } dl = (struct l1_info_dl *) msg->l2h; ccch = (struct l1_ccch_info_ind *) msg->l3h; - printf("Found CCCH burst(s): TDMA: (%.4u/%.2u/%.2u) tc:%d %s si: 0x%x\n", - dl->time.t1, dl->time.t2, dl->time.t3, dl->time.tc, - hexdump(ccch->data, sizeof(ccch->data)), ccch->data[2]); + printf("Found %s burst(s): TDMA: (%.4u/%.2u/%.2u) tc:%d %s si: 0x%x\n", + chan_nr2string(dl->chan_nr), dl->time.t1, dl->time.t2, + dl->time.t3, dl->time.tc, hexdump(ccch->data, sizeof(ccch->data)), + ccch->data[2]); dump_bcch(dl->time.tc, ccch->data); /* send CCCH data via GSMTAP */ - gsmtap_sendmsg(0, dl->band_arfcn, dl->time.fn, ccch->data, + gsmtap_sendmsg(dl->chan_nr & 0x07, dl->band_arfcn, dl->time.fn, ccch->data, sizeof(ccch->data)); + //l1_rach_req(ms); return 0; } @@ -197,6 +228,23 @@ static int osmo_l1_reset(struct osmocom_ms *ms) return osmo_send_l1(ms, msg); } +static int l1_rach_req(struct osmocom_ms *ms) +{ + struct msgb *msg; + struct l1_rach_req *req; + static uint8_t i = 0; + + msg = osmo_l1_alloc(CCCH_RACH_REQ); + if (!msg) + return -1; + + printf("RACH Req.\n"); + req = (struct l1_rach_req *) msgb_put(msg, sizeof(*req)); + req->ra = i++; + + return osmo_send_l1(ms, msg); +} + int osmo_recv(struct osmocom_ms *ms, struct msgb *msg) { diff --git a/src/target/firmware/include/layer1/mframe_sched.h b/src/target/firmware/include/layer1/mframe_sched.h index 019d31bb..bd752543 100644 --- a/src/target/firmware/include/layer1/mframe_sched.h +++ b/src/target/firmware/include/layer1/mframe_sched.h @@ -25,5 +25,11 @@ enum mframe_task { MF_TASK_UL_ALL_NB, }; +enum mf_sched_item_flag { + MF_F_SACCH = (1 << 0), +}; + +uint8_t mframe_task2chan_nr(enum mframe_task mft, uint8_t ts); + /* Schedule mframe_sched_items according to current MF TASK list */ void mframe_schedule(uint32_t task_bitmask); diff --git a/src/target/firmware/layer1/mframe_sched.c b/src/target/firmware/layer1/mframe_sched.c index 502d102f..61fbe48b 100644 --- a/src/target/firmware/layer1/mframe_sched.c +++ b/src/target/firmware/layer1/mframe_sched.c @@ -31,11 +31,6 @@ #include <layer1/tdma_sched.h> #include <layer1/mframe_sched.h> -enum mf_sched_item_flag { - MF_F_SACCH, - //MF_F_UL_OFFS_15, /* uplink 15 frames after downlink */ -}; - /* A multiframe operation which can be scheduled for a multiframe */ struct mframe_sched_item { /* The TDMA scheduler item that shall be scheduled */ @@ -230,6 +225,61 @@ static const struct mframe_sched_item *sched_set_for_task[32] = { [MF_TASK_UL_ALL_NB] = mf_tx_all_nb, }; +/* encodes a channel number according to 08.58 Chapter 9.3.1 */ +uint8_t mframe_task2chan_nr(enum mframe_task mft, uint8_t ts) +{ + uint8_t cbits; + + switch (mft) { + case MF_TASK_BCCH_NORM: + case MF_TASK_BCCH_EXT: + cbits = 0x10; + break; + case MF_TASK_CCCH: + case MF_TASK_CCCH_COMB: + cbits = 0x12; + break; + case MF_TASK_SDCCH4_0: + cbits = 0x04 + 0; + break; + case MF_TASK_SDCCH4_1: + cbits = 0x04 + 1; + break; + case MF_TASK_SDCCH4_2: + cbits = 0x04 + 2; + break; + case MF_TASK_SDCCH4_3: + cbits = 0x04 + 3; + break; + case MF_TASK_SDCCH8_0: + cbits = 0x08 + 0; + break; + case MF_TASK_SDCCH8_1: + cbits = 0x08 + 1; + break; + case MF_TASK_SDCCH8_2: + cbits = 0x08 + 2; + break; + case MF_TASK_SDCCH8_3: + cbits = 0x08 + 3; + break; + case MF_TASK_SDCCH8_4: + cbits = 0x08 + 4; + break; + case MF_TASK_SDCCH8_5: + cbits = 0x08 + 5; + break; + case MF_TASK_SDCCH8_6: + cbits = 0x08 + 6; + break; + case MF_TASK_SDCCH8_7: + cbits = 0x08 + 7; + break; + } + + return (cbits << 3) | (ts & 0x7); +} + /* how many TDMA frame ticks should we schedule events ahead? */ #define SCHEDULE_AHEAD 2 @@ -237,8 +287,9 @@ static const struct mframe_sched_item *sched_set_for_task[32] = { #define SCHEDULE_LATENCY 1 /* (test and) schedule one particular sched_item_set by means of the TDMA scheduler */ -static void mframe_schedule_set(const struct mframe_sched_item *set) +static void mframe_schedule_set(enum mframe_task task_id) { + const struct mframe_sched_item *set = sched_set_for_task[task_id]; const struct mframe_sched_item *si; for (si = set; si->sched_set != NULL; si++) { @@ -247,7 +298,7 @@ static void mframe_schedule_set(const struct mframe_sched_item *set) if (current == trigger) { /* FIXME: what to do with SACCH Flag etc? */ tdma_schedule_set(SCHEDULE_AHEAD-SCHEDULE_LATENCY, - si->sched_set, si->flags); + si->sched_set, task_id | (si->flags<<8)); } } } @@ -259,6 +310,6 @@ void mframe_schedule(uint32_t tasks_enabled) for (i = 0; i < 32; i++) { if (tasks_enabled & (1 << i)) - mframe_schedule_set(sched_set_for_task[i]); + mframe_schedule_set(i); } } diff --git a/src/target/firmware/layer1/sync.c b/src/target/firmware/layer1/sync.c index 1f01158d..c71caaf4 100644 --- a/src/target/firmware/layer1/sync.c +++ b/src/target/firmware/layer1/sync.c @@ -802,6 +802,8 @@ void l1s_pm_test(uint8_t base_fn, uint16_t arfcn) static int l1s_nb_resp(uint8_t p1, uint8_t burst_id, uint16_t p3) { static struct l1_signal _nb_sig, *sig = &_nb_sig; + uint8_t mf_task_id = p3 & 0xff; + uint8_t mf_task_flags = p3 >> 8; struct msgb *msg; putchart('n'); @@ -855,6 +857,15 @@ static int l1s_nb_resp(uint8_t p1, uint8_t burst_id, uint16_t p3) dl = (struct l1_info_dl *) msg->data; l1 = (struct l1_ccch_info_ind *) msgb_put(msg, sizeof(*l1)); + /* Set Channel Number depending on MFrame Task ID */ + dl->chan_nr = mframe_task2chan_nr(mf_task_id, 0); /* FIXME: TS */ + + /* Set SACCH indication in Link IDentifier */ + if (mf_task_flags & MF_F_SACCH) + dl->link_id = 0x40; + else + dl->link_id = 0x00; + /* copy the snr and data */ for (i = 0; i < 3; ++i) dl->snr[i] = sig->nb.meas[i].snr; @@ -937,6 +948,8 @@ static int l1s_tx_cmd(uint8_t p1, uint8_t burst_id, uint16_t p3) { int i; uint8_t tsc; + uint8_t mf_task_id = p3 & 0xff; + uint8_t mf_task_flags = p3 >> 8; putchart('T'); @@ -968,12 +981,18 @@ static int l1s_tx_cmd(uint8_t p1, uint8_t burst_id, uint16_t p3) if (burst_id == 0) { if (p1 == 0 || p1 == 2) { // DUL_DSP_TASK uint16_t *info_ptr = dsp_api.ndb->a_cu; + struct llist_head *tx_queue; struct msgb *msg; uint8_t *data; uint8_t j; - /* FIXME: distinguish between DCCH and ACCH */ - msg = msgb_dequeue(&l1s.tx_queue[0]); + /* distinguish between DCCH and ACCH */ + if (mf_task_flags & MF_F_SACCH) + tx_queue = &l1s.tx_queue[0]; + else + tx_queue = &l1s.tx_queue[1]; + + msg = msgb_dequeue(tx_queue); /* If the TX queue is empty, send idle pattern */ if (!msg) |