struct l1s_rxnb_state {
struct l1s_meas_hdr meas[4];
- uint16_t crc;
- uint16_t fire;
- uint16_t num_biterr;
- uint8_t frame[24]
+
+ struct msgb *msg;
+ struct l1ctl_info_dl *dl;
+ struct l1ctl_data_ind *di;
};
static struct l1s_rxnb_state rxnb;
{
uint8_t mf_task_id = p3 & 0xff;
uint8_t mf_task_flags = p3 >> 8;
- struct msgb *msg;
uint16_t rf_arfcn = l1s.serving_cell.arfcn;
putchart('n');
/* 4th burst, get frame data */
if (dsp_api.db_r->d_burst_d == 3) {
- struct l1ctl_hdr *l1h;
- struct l1ctl_info_dl *dl;
- struct l1ctl_data_ind *di;
+ uint8_t i, j;
+ uint16_t num_biterr;
uint32_t avg_snr = 0;
int32_t avg_dbm8 = 0;
- uint8_t i, j;
-
- rxnb.num_biterr = dsp_api.ndb->a_cd[2] & 0xffff;
- rxnb.crc = ((dsp_api.ndb->a_cd[0] & 0xffff) & ((1 << B_FIRE1) | (1 << B_FIRE0))) >> B_FIRE0;
- rxnb.fire = ((dsp_api.ndb->a_cd[0] & 0xffff) & (1 << B_FIRE1)) >> B_FIRE1;
-
- /* copy actual data, skipping the information block [0,1,2] */
- for (j = 0,i = 3; i < 15; i++) {
- rxnb.frame[j++] = dsp_api.ndb->a_cd[i] & 0xFF;
- rxnb.frame[j++] = (dsp_api.ndb->a_cd[i] >> 8) & 0xFF;
- }
-
- /* place it in the queue for the layer2 */
- msg = l1_create_l2_msg(L1CTL_DATA_IND, l1s.current_time.fn-4,
- 0, rf_arfcn);
- l1h = (struct l1ctl_hdr *) msg->l1h;
- dl = (struct l1ctl_info_dl *) l1h->data;
- di = (struct l1ctl_data_ind *) msgb_put(msg, sizeof(*di));
/* Set Channel Number depending on MFrame Task ID */
- dl->chan_nr = mframe_task2chan_nr(mf_task_id, 0); /* FIXME: TS */
+ rxnb.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;
+ rxnb.dl->link_id = 0x40;
else
- dl->link_id = 0x00;
+ rxnb.dl->link_id = 0x00;
+
+ rxnb.dl->band_arfcn = htons(rf_arfcn);
+
+ rxnb.dl->frame_nr = htonl(l1s.current_time.fn-4);
/* compute average snr and rx level */
for (i = 0; i < 4; ++i) {
avg_snr += rxnb.meas[i].snr;
avg_dbm8 += rxnb.meas[i].pm_dbm8;
}
- dl->snr = avg_snr / 4;
- dl->rx_level = (avg_dbm8 / (8*4)) + 110;
+ rxnb.dl->snr = avg_snr / 4;
+ rxnb.dl->rx_level = (avg_dbm8 / (8*4)) + 110;
+
+ num_biterr = dsp_api.ndb->a_cd[2] & 0xffff;
+ if (num_biterr > 0xff)
+ rxnb.dl->num_biterr = 0xff;
+ else
+ rxnb.dl->num_biterr = num_biterr;
- /* copy the actual payload data */
- for (i = 0; i < 23; ++i)
- di->data[i] = rxnb.frame[i];
- l1_queue_for_l2(msg);
+ rxnb.dl->fire_crc = ((dsp_api.ndb->a_cd[0] & 0xffff) & ((1 << B_FIRE1) | (1 << B_FIRE0))) >> B_FIRE0;
+
+ /* copy actual data, skipping the information block [0,1,2] */
+ for (j = 0,i = 3; i < 15; i++) {
+ rxnb.di->data[j++] = dsp_api.ndb->a_cd[i] & 0xFF;
+ rxnb.di->data[j++] = (dsp_api.ndb->a_cd[i] >> 8) & 0xFF;
+ }
+
+ l1_queue_for_l2(rxnb.msg);
+ rxnb.msg = NULL; rxnb.dl = NULL; rxnb.di = NULL;
/* clear downlink task */
dsp_api.db_w->d_task_d = 0;
uint8_t tsc = l1s.serving_cell.bsic & 0x7;
putchart('N');
+
+ if (burst_id == 1) {
+ /* allocate message only at 2nd burst in case of
+ * consecutive/overlapping normal burst RX tasks */
+ /* FIXME: we actually want all allocation out of L1S! */
+ if (rxnb.msg)
+ printf("nb_cmd(0) and rxnb.msg != NULL\n");
+ /* allocate msgb as needed. FIXME: from L1A ?? */
+ rxnb.msg = l1ctl_msgb_alloc(L1CTL_DATA_IND);
+ if (!rxnb.msg)
+ printf("nb_cmd(0): unable to allocate msgb\n");
+ rxnb.dl = (struct l1ctl_info_dl *) msgb_put(rxnb.msg, sizeof(*rxnb.dl));
+ rxnb.di = (struct l1ctl_data_ind *) msgb_put(rxnb.msg, sizeof(*rxnb.di));
+ }
+
dsp_load_rx_task(ALLC_DSP_TASK, burst_id, tsc);
dsp_end_scenario();