int dci_format1Cs_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb) { uint16_t L_p, RB_p; /* pack bits */ char *y = msg->data; if (msg->location.nof_bits != dci_format_sizeof(Format1C, nof_prb)) { fprintf(stderr, "Invalid message length for format 1C\n"); return -1; } data->alloc_type = alloc_type2; data->type2_alloc.mode = t2_dist; if (nof_prb >= 50) { data->type2_alloc.n_gap = *y++; } int n_step = ra_type2_n_rb_step(nof_prb); int n_vrb_dl = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == t2_ng1); uint32_t riv = bit_unpack(&y, riv_nbits((int) n_vrb_dl / n_step)); int n_vrb_p = (int) n_vrb_dl / n_step; ra_type2_from_riv(riv, &L_p, &RB_p, n_vrb_p, n_vrb_p); data->type2_alloc.L_crb = L_p * n_step; data->type2_alloc.RB_start = RB_p * n_step; data->type2_alloc.riv = riv; data->mcs.mcs_idx = bit_unpack(&y, 5); data->mcs.tbs_idx = data->mcs.mcs_idx; data->mcs.tbs = ra_tbs_from_idx_format1c(data->mcs.tbs_idx); data->mcs.mod = QPSK; msg->location.nof_bits = (y - msg->data); return 0; }
int mod_modulate(modem_table_t* q, const uint8_t *bits, cf* symbols, int nbits) { int i,j,idx; uint8_t *b_ptr=(uint8_t*) bits; j=0; for (i=0;i<nbits;i+=q->nbits_x_symbol) { idx = bit_unpack(&b_ptr,q->nbits_x_symbol); symbols[j] = q->symbol_table[idx]; j++; } return j; }
/** Unpacks MIB from PBCH message. * msg buffer must be 24 byte length at least */ void pbch_mib_unpack(char *msg, pbch_mib_t *mib) { int bw, phich_res; bw = bit_unpack(&msg, 3); switch (bw) { case 0: mib->nof_prb = 6; break; case 1: mib->nof_prb = 15; break; default: mib->nof_prb = (bw - 1) * 25; break; } if (*msg) { mib->phich_length = PHICH_EXT; } else { mib->phich_length = PHICH_NORM; } msg++; phich_res = bit_unpack(&msg, 2); switch (phich_res) { case 0: mib->phich_resources = R_1_6; break; case 1: mib->phich_resources = R_1_2; break; case 2: mib->phich_resources = R_1; break; case 3: mib->phich_resources = R_2; break; } mib->sfn = bit_unpack(&msg, 8) << 2; }
int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb) { /* pack bits */ char *y = msg->data; /* Make sure it's a Format1 message */ if (msg->location.nof_bits != dci_format_sizeof(Format1, nof_prb)) { fprintf(stderr, "Invalid message length for format 1\n"); return -1; } if (nof_prb > 10) { data->alloc_type = *y++; } else { data->alloc_type = alloc_type0; } /* Resource allocation: type0 or type 1 */ int P = ra_type0_P(nof_prb); int alloc_size = (int) ceilf((float) nof_prb / P); switch (data->alloc_type) { case alloc_type0: data->type0_alloc.rbg_bitmask = bit_unpack(&y, alloc_size); break; case alloc_type1: data->type1_alloc.rbg_subset = bit_unpack(&y, (int) ceilf(log2f(P))); data->type1_alloc.shift = *y++ ? true : false; data->type1_alloc.vrb_bitmask = bit_unpack(&y, alloc_size - (int) ceilf(log2f(P)) - 1); break; default: fprintf(stderr, "Format 1 accepts type0 or type1 resource allocation only\n"); return -1; } /* pack MCS according to 7.1.7 of 36.213 */ uint32_t mcs = bit_unpack(&y, 5); data->mcs.mcs_idx = mcs; ra_mcs_from_idx_dl(mcs, &data->mcs); data->mcs.tbs = ra_tbs_from_idx(data->mcs.tbs_idx, ra_nprb_dl(data, nof_prb)); /* harq process number */ data->harq_process = bit_unpack(&y, 3); data->ndi = *y++ ? true : false; // rv version data->rv_idx = bit_unpack(&y, 2); // TPC not implemented return 0; }
/* Unpacks DCI format 1A for compact scheduling of PDSCH words according to 36.212 5.3.3.1.3 * */ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb, bool crc_is_crnti) { /* pack bits */ char *y = msg->data; /* Make sure it's a Format0 message */ if (msg->location.nof_bits != dci_format_sizeof(Format1A, nof_prb)) { fprintf(stderr, "Invalid message length for format 1A\n"); return -1; } if (*y++ != 1) { fprintf(stderr, "Invalid format differentiation field value. This is Format0\n"); return -1; } data->alloc_type = alloc_type2; data->type2_alloc.mode = *y++; // by default, set N_gap to 1 data->type2_alloc.n_gap = t2_ng1; /* unpack RIV according to 7.1.6.3 of 36.213 */ int nb_gap = 0; if (crc_is_crnti && data->type2_alloc.mode == t2_dist && nof_prb >= 50) { nb_gap = 1; data->type2_alloc.n_gap = *y++; } int nof_vrb; if (data->type2_alloc.mode == t2_loc) { nof_vrb = nof_prb; } else { nof_vrb = ra_type2_n_vrb_dl(nof_prb, data->type2_alloc.n_gap == t2_ng1); } uint32_t riv = bit_unpack(&y, riv_nbits(nof_prb) - nb_gap); ra_type2_from_riv(riv, &data->type2_alloc.L_crb, &data->type2_alloc.RB_start, nof_prb, nof_vrb); data->type2_alloc.riv = riv; // unpack MCS data->mcs.mcs_idx = bit_unpack(&y, 5); data->harq_process = bit_unpack(&y, 3); if (!crc_is_crnti && nof_prb >= 50 && data->type2_alloc.mode == t2_dist) { data->type2_alloc.n_gap = *y++; } else { y++; // bit reserved } // rv version bit_pack(data->rv_idx, &y, 2); if (crc_is_crnti) { // TPC not implemented y++; y++; } else { y++; // MSB of TPC is reserved data->type2_alloc.n_prb1a = *y++; // LSB indicates N_prb_1a for TBS } data->mcs.tbs_idx = data->mcs.mcs_idx; int n_prb; if (crc_is_crnti) { n_prb = ra_nprb_dl(data, nof_prb); } else { n_prb = data->type2_alloc.n_prb1a == nprb1a_2 ? 2 : 3; } data->mcs.tbs = ra_tbs_from_idx(data->mcs.tbs_idx, n_prb); data->mcs.mod = QPSK; return 0; }
/* Unpacks DCI format 0 data and store result in msg according * to 36.212 5.3.3.1.1 * * TODO: TPC and cyclic shift for DM RS not implemented */ int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, int nof_prb) { /* pack bits */ char *y = msg->data; int n_ul_hop; /* Make sure it's a Format0 message */ if (msg->location.nof_bits != dci_format_sizeof(Format0, nof_prb)) { fprintf(stderr, "Invalid message length for format 0\n"); return -1; } if (*y++ != 0) { fprintf(stderr, "Invalid format differentiation field value. This is Format1A\n"); return -1; } if (*y++ == 0) { data->freq_hop_fl = hop_disabled; n_ul_hop = 0; } else { if (nof_prb < 50) { n_ul_hop = 1; // Table 8.4-1 of 36.213 data->freq_hop_fl = *y++; } else { n_ul_hop = 2; // Table 8.4-1 of 36.213 data->freq_hop_fl = y[0] << 1 | y[1]; y += 2; } } /* unpack RIV according to 8.1 of 36.213 */ uint32_t riv = bit_unpack(&y, riv_nbits(nof_prb) - n_ul_hop); ra_type2_from_riv(riv, &data->type2_alloc.L_crb, &data->type2_alloc.RB_start, nof_prb, nof_prb); bit_pack(riv, &y, riv_nbits(nof_prb) - n_ul_hop); data->type2_alloc.riv = riv; /* unpack MCS according to 8.6 of 36.213 */ uint32_t mcs = bit_unpack(&y, 5); data->ndi = *y++ ? true : false; // TCP and DM RS commands not implemented y += 5; // CQI request data->cqi_request = *y++ ? true : false; // 8.6.2 First paragraph if (mcs <= 28) { ra_mcs_from_idx_ul(mcs, &data->mcs); data->mcs.tbs = ra_tbs_from_idx(data->mcs.tbs_idx, ra_nprb_ul(data, nof_prb)); } // 8.6.1 and 8.6.2 36.213 second paragraph if (mcs == 29 && data->cqi_request && ra_nprb_ul(data, nof_prb) <= 4) { data->mcs.mod = QPSK; } if (mcs > 29) { // Else leave MOD_NULL and use the previously used PUSCH modulation data->mcs.mod = MOD_NULL; data->rv_idx = mcs - 28; } return 0; }