summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte2010-03-01 11:08:38 +0100
committerHarald Welte2010-03-01 23:48:45 +0100
commit43dd25c49355212a589be9784dd43fa11f626103 (patch)
tree4197455107e977f79d657452e943fc021b4a5e11
parentextend TDMA scheduler functions to use third parameter (p3) (diff)
downloadosmocom-43dd25c49355212a589be9784dd43fa11f626103.tar.gz
osmocom-43dd25c49355212a589be9784dd43fa11f626103.tar.xz
osmocom-43dd25c49355212a589be9784dd43fa11f626103.zip
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.h8
-rw-r--r--src/host/layer2/src/osmocom_layer2.c58
-rw-r--r--src/target/firmware/include/layer1/mframe_sched.h6
-rw-r--r--src/target/firmware/layer1/mframe_sched.c67
-rw-r--r--src/target/firmware/layer1/sync.c23
5 files changed, 146 insertions, 16 deletions
diff --git a/include/l1a_l23_interface.h b/include/l1a_l23_interface.h
index 6e94ebc..01fcf9f 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 66cb181..877ce4a 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 019d31b..bd75254 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 502d102..61fbe48 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 1f01158..c71caaf 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)