#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
/* 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];
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)
#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;
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);
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;
/* 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;
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)
/* 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;
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);
}
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;
}
}
+/* 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)
{
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;
case L1CTL_RESET_REQ:
l1ctl_rx_reset_req(msg);
break;
+ case L1CTL_CCCH_MODE_REQ:
+ l1ctl_rx_ccch_mode_req(msg);
+ break;
}
exit_msgbfree:
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);