fw/layer1: Add support CCCH combined/non-combined
authorSylvain Munaut <tnt@246tNt.com>
Sun, 20 Jun 2010 20:40:03 +0000 (22:40 +0200)
committerHarald Welte <laforge@gnumonks.org>
Tue, 22 Jun 2010 04:37:09 +0000 (06:37 +0200)
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>
include/l1a_l23_interface.h
src/host/layer23/include/osmocom/l1ctl.h
src/host/layer23/src/app_phone.c
src/host/layer23/src/bcch_scan.c
src/host/layer23/src/gsm322.c
src/host/layer23/src/l1ctl.c
src/target/firmware/include/layer1/sync.h
src/target/firmware/layer1/l23_api.c
src/target/firmware/layer1/prim_fbsb.c

index 95ec82b..741221b 100644 (file)
 #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;
index 48aeaad..2bcbdb3 100644 (file)
@@ -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);
 
index 17083d7..7258f56 100644 (file)
@@ -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;
index a8bd11c..c542129 100644 (file)
@@ -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;
 
index 8536a10..9ffc769 100644 (file)
@@ -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)
index 63628b0..1239b99 100644 (file)
@@ -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);
 }
index 171fb3b..137ea9f 100644 (file)
@@ -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;
index 72995c2..90aef76 100644 (file)
@@ -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:
index 0333017..fe87996 100644 (file)
@@ -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);