summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylvain Munaut <tnt@246tNt.com>2010-06-20 22:40:03 +0200
committerHarald Welte <laforge@gnumonks.org>2010-06-22 06:37:09 +0200
commit38c6b4b35a4400a62b0e534c9326154bb4f232f9 (patch)
tree56d898f68fced20858b998571c8885e7b23a8831
parenta3e0c559a45f3c719082acf9eb2f7657ea4e35b5 (diff)
fw/layer1: Add support CCCH combined/non-combined
We introduce the concept of CCCH mode. It can be either - NONE: receive BCCCH only - COMBINED: CCCH on a BCCH/CCCH+SDDCH/4 - NON_COMBINED: CCCH on a BCCH/CCCH There is also a new command to change the mode without having to do the resync. Currently, we keep the previous default behavior of requesting a combined CCCH by default Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
-rw-r--r--include/l1a_l23_interface.h25
-rw-r--r--src/host/layer23/include/osmocom/l1ctl.h5
-rw-r--r--src/host/layer23/src/app_phone.c4
-rw-r--r--src/host/layer23/src/bcch_scan.c3
-rw-r--r--src/host/layer23/src/gsm322.c3
-rw-r--r--src/host/layer23/src/l1ctl.c20
-rw-r--r--src/target/firmware/include/layer1/sync.h2
-rw-r--r--src/target/firmware/layer1/l23_api.c41
-rw-r--r--src/target/firmware/layer1/prim_fbsb.c5
9 files changed, 101 insertions, 7 deletions
diff --git a/include/l1a_l23_interface.h b/include/l1a_l23_interface.h
index 95ec82b2..741221bc 100644
--- a/include/l1a_l23_interface.h
+++ b/include/l1a_l23_interface.h
@@ -39,6 +39,14 @@
#define L1CTL_RESET_REQ 14
#define L1CTL_RESET_CONF 15
#define L1CTL_DATA_CONF 16
+#define L1CTL_CCCH_MODE_REQ 17
+#define L1CTL_CCCH_MODE_CONF 18
+
+enum ccch_mode {
+ CCCH_MODE_NONE = 0,
+ CCCH_MODE_NON_COMBINED,
+ CCCH_MODE_COMBINED,
+};
/*
* NOTE: struct size. We do add manual padding out of the believe
@@ -84,6 +92,12 @@ struct l1ctl_fbsb_conf {
/* FIXME: contents of cell_info ? */
} __attribute__((packed));
+/* CCCH mode was changed */
+struct l1ctl_ccch_mode_conf {
+ uint8_t ccch_mode; /* enum ccch_mode */
+ uint8_t padding[3];
+} __attribute__((packed));
+
/* data on the CCCH was found. This is following the header */
struct l1ctl_data_ind {
uint8_t data[23];
@@ -117,7 +131,7 @@ struct l1ctl_fbsb_req {
uint8_t num_freqerr_avg;
uint8_t flags; /* L1CTL_FBSB_F_* */
uint8_t sync_info_idx;
- uint8_t reserved;
+ uint8_t ccch_mode; /* enum ccch_mode */
} __attribute__((packed));
#define L1CTL_FBSB_F_FB0 (1 << 0)
@@ -125,6 +139,15 @@ struct l1ctl_fbsb_req {
#define L1CTL_FBSB_F_SB (1 << 2)
#define L1CTL_FBSB_F_FB01SB (L1CTL_FBSB_F_FB0|L1CTL_FBSB_F_FB1|L1CTL_FBSB_F_SB)
+/*
+ * msg for CCCH_MODE_REQ
+ * the l1_info_ul header is in front
+ */
+struct l1ctl_ccch_mode_req {
+ uint8_t ccch_mode; /* enum ccch_mode */
+ uint8_t padding[3];
+} __attribute__((packed));
+
/* the l1_info_ul header is in front */
struct l1ctl_rach_req {
uint8_t ra;
diff --git a/src/host/layer23/include/osmocom/l1ctl.h b/src/host/layer23/include/osmocom/l1ctl.h
index 48aeaadd..2bcbdb32 100644
--- a/src/host/layer23/include/osmocom/l1ctl.h
+++ b/src/host/layer23/include/osmocom/l1ctl.h
@@ -20,7 +20,10 @@ int tx_ph_rach_req(struct osmocom_ms *ms);
int tx_ph_dm_est_req(struct osmocom_ms *ms, uint16_t band_arfcn, uint8_t chan_nr);
/* Transmit FBSB_REQ */
int l1ctl_tx_fbsb_req(struct osmocom_ms *ms, uint16_t arfcn,
- uint8_t flags, uint16_t timeout, uint8_t sync_info_idx);
+ uint8_t flags, uint16_t timeout, uint8_t sync_info_idx,
+ uint8_t ccch_mode);
+
+int l1ctl_tx_ccch_mode_req(struct osmocom_ms *ms, uint8_t ccch_mode);
int l1ctl_tx_echo_req(struct osmocom_ms *ms, unsigned int len);
diff --git a/src/host/layer23/src/app_phone.c b/src/host/layer23/src/app_phone.c
index 17083d78..7258f569 100644
--- a/src/host/layer23/src/app_phone.c
+++ b/src/host/layer23/src/app_phone.c
@@ -44,7 +44,9 @@ static int signal_cb(unsigned int subsys, unsigned int signal,
switch (signal) {
case S_L1CTL_RESET:
ms = signal_data;
- return l1ctl_tx_fbsb_req(ms, ms->test_arfcn, L1CTL_FBSB_F_FB01SB, 100, 0);
+ return l1ctl_tx_fbsb_req(ms, ms->test_arfcn,
+ L1CTL_FBSB_F_FB01SB, 100, 0,
+ CCCH_MODE_COMBINED);
break;
}
return 0;
diff --git a/src/host/layer23/src/bcch_scan.c b/src/host/layer23/src/bcch_scan.c
index a8bd11cf..c542129a 100644
--- a/src/host/layer23/src/bcch_scan.c
+++ b/src/host/layer23/src/bcch_scan.c
@@ -154,7 +154,8 @@ static int _cinfo_start_arfcn(unsigned int band_arfcn)
/* ask L1 to try to tune to new ARFCN */
/* FIXME: decode band */
- rc = l1ctl_tx_fbsb_req(fps.ms, band_arfcn, L1CTL_FBSB_F_FB01SB, 100, 0);
+ rc = l1ctl_tx_fbsb_req(fps.ms, band_arfcn,
+ L1CTL_FBSB_F_FB01SB, 100, 0, CCCH_MODE_COMBINED);
if (rc < 0)
return rc;
diff --git a/src/host/layer23/src/gsm322.c b/src/host/layer23/src/gsm322.c
index 8536a103..9ffc7693 100644
--- a/src/host/layer23/src/gsm322.c
+++ b/src/host/layer23/src/gsm322.c
@@ -222,7 +222,8 @@ int gsm322_cs_sendmsg(struct osmocom_ms *ms, struct msgb *msg)
static int gsm322_sync_to_cell(struct osmocom_ms *ms, struct gsm322_cellsel *cs)
{
return l1ctl_tx_fbsb_req(ms, cs->arfcn,
- L1CTL_FBSB_F_FB01SB, 100, 0);
+ L1CTL_FBSB_F_FB01SB, 100, 0,
+ CCCH_MODE_COMBINED);
}
static void gsm322_unselect_cell(struct gsm322_cellsel *cs)
diff --git a/src/host/layer23/src/l1ctl.c b/src/host/layer23/src/l1ctl.c
index 63628b0f..1239b99c 100644
--- a/src/host/layer23/src/l1ctl.c
+++ b/src/host/layer23/src/l1ctl.c
@@ -233,7 +233,8 @@ int tx_ph_data_req(struct osmocom_ms *ms, struct msgb *msg,
/* Transmit FBSB_REQ */
int l1ctl_tx_fbsb_req(struct osmocom_ms *ms, uint16_t arfcn,
- uint8_t flags, uint16_t timeout, uint8_t sync_info_idx)
+ uint8_t flags, uint16_t timeout, uint8_t sync_info_idx,
+ uint8_t ccch_mode)
{
struct msgb *msg;
struct l1ctl_fbsb_req *req;
@@ -253,6 +254,23 @@ int l1ctl_tx_fbsb_req(struct osmocom_ms *ms, uint16_t arfcn,
req->num_freqerr_avg = 3;
req->flags = flags;
req->sync_info_idx = sync_info_idx;
+ req->ccch_mode = ccch_mode;
+
+ return osmo_send_l1(ms, msg);
+}
+
+/* Transmit L1CTL_CCCH_MODE_REQ */
+int l1ctl_tx_ccch_mode_req(struct osmocom_ms *ms, uint8_t ccch_mode)
+{
+ struct msgb *msg;
+ struct l1ctl_ccch_mode_req *req;
+
+ msg = osmo_l1_alloc(L1CTL_CCCH_MODE_REQ);
+ if (!msg)
+ return -1;
+
+ req = (struct l1ctl_ccch_mode_req *) msgb_put(msg, sizeof(*req));
+ req->ccch_mode = ccch_mode;
return osmo_send_l1(ms, msg);
}
diff --git a/src/target/firmware/include/layer1/sync.h b/src/target/firmware/include/layer1/sync.h
index 171fb3bb..137ea9f8 100644
--- a/src/target/firmware/include/layer1/sync.h
+++ b/src/target/firmware/include/layer1/sync.h
@@ -13,6 +13,8 @@ struct l1_cell_info {
uint16_t arfcn;
/* what's the BSIC of the cell (from SCH burst decoding) */
uint8_t bsic;
+ /* Combined or non-combined CCCH */
+ uint8_t ccch_mode; /* enum ccch_mode */
/* whats the delta of the cells current GSM frame number
* compared to our current local frame number */
int32_t fn_offset;
diff --git a/src/target/firmware/layer1/l23_api.c b/src/target/firmware/layer1/l23_api.c
index 72995c2e..90aef764 100644
--- a/src/target/firmware/layer1/l23_api.c
+++ b/src/target/firmware/layer1/l23_api.c
@@ -170,6 +170,41 @@ static void l1ctl_rx_reset_req(struct msgb *msg)
}
}
+/* Transmit a L1CTL_CCCH_MODE_CONF */
+static void l1ctl_tx_ccch_mode_conf(uint8_t ccch_mode)
+{
+ struct msgb *msg = l1ctl_msgb_alloc(L1CTL_CCCH_MODE_CONF);
+ struct l1ctl_ccch_mode_conf *mode_conf;
+ mode_conf = (struct l1ctl_ccch_mode_conf *)
+ msgb_put(msg, sizeof(*mode_conf));
+ mode_conf->ccch_mode = ccch_mode;
+
+ l1_queue_for_l2(msg);
+}
+
+/* receive a L1CTL_CCCH_MODE_REQ from L23 */
+static void l1ctl_rx_ccch_mode_req(struct msgb *msg)
+{
+ struct l1ctl_hdr *l1h = (struct l1ctl_hdr *) msg->data;
+ struct l1ctl_ccch_mode_req *ccch_mode_req =
+ (struct l1ctl_ccch_mode_req *) l1h->data;
+ uint8_t ccch_mode = ccch_mode_req->ccch_mode;
+
+ /* pre-set the CCCH mode */
+ l1s.serving_cell.ccch_mode = ccch_mode;
+
+ /* Update task */
+ mframe_disable(MF_TASK_CCCH_COMB);
+ mframe_disable(MF_TASK_CCCH);
+
+ if (ccch_mode == CCCH_MODE_COMBINED)
+ mframe_enable(MF_TASK_CCCH_COMB);
+ else if (ccch_mode == CCCH_MODE_NON_COMBINED)
+ mframe_enable(MF_TASK_CCCH);
+
+ l1ctl_tx_ccch_mode_conf(ccch_mode);
+}
+
/* callback from SERCOMM when L2 sends a message to L1 */
static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
{
@@ -214,6 +249,9 @@ static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
trf6151_rx_window(0, ntohs(sync_req->band_arfcn), 40, 0);
tpu_end_scenario();
+ /* pre-set the CCCH mode */
+ l1s.serving_cell.ccch_mode = sync_req->ccch_mode;
+
printd("Starting FCCH Recognition\n");
l1s_fbsb_req(1, sync_req);
break;
@@ -263,6 +301,9 @@ static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
case L1CTL_RESET_REQ:
l1ctl_rx_reset_req(msg);
break;
+ case L1CTL_CCCH_MODE_REQ:
+ l1ctl_rx_ccch_mode_req(msg);
+ break;
}
exit_msgbfree:
diff --git a/src/target/firmware/layer1/prim_fbsb.c b/src/target/firmware/layer1/prim_fbsb.c
index 0333017f..fe87996c 100644
--- a/src/target/firmware/layer1/prim_fbsb.c
+++ b/src/target/firmware/layer1/prim_fbsb.c
@@ -257,7 +257,10 @@ static int l1s_sbdet_resp(__unused uint8_t p1, uint8_t attempt,
l1s_reset_hw();
/* enable the MF Task for BCCH reading */
mframe_enable(MF_TASK_BCCH_NORM);
- mframe_enable(MF_TASK_CCCH_COMB);
+ if (l1s.serving_cell.ccch_mode == CCCH_MODE_COMBINED)
+ mframe_enable(MF_TASK_CCCH_COMB);
+ else if (l1s.serving_cell.ccch_mode == CCCH_MODE_NON_COMBINED)
+ mframe_enable(MF_TASK_CCCH);
l1s_compl_sched(L1_COMPL_FB);