diff --git a/lte/examples/pdsch_enodeb.c b/lte/examples/pdsch_enodeb.c index 2b11b7d52..8c862faef 100644 --- a/lte/examples/pdsch_enodeb.c +++ b/lte/examples/pdsch_enodeb.c @@ -313,7 +313,7 @@ uint32_t prbset_to_bitmask() { } int update_radl(uint32_t sf_idx) { - ra_prb_t prb_alloc; + ra_dl_alloc_t prb_alloc; bzero(&ra_dl, sizeof(ra_pdsch_t)); ra_dl.harq_process = 0; @@ -323,8 +323,8 @@ int update_radl(uint32_t sf_idx) { ra_dl.alloc_type = alloc_type0; ra_dl.type0_alloc.rbg_bitmask = prbset_to_bitmask(); - ra_prb_get_dl(&prb_alloc, &ra_dl, cell.nof_prb); - ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, 1, cell.nof_prb<10?(cfi+1):cfi, CPNORM); + ra_dl_alloc(&prb_alloc, &ra_dl, cell.nof_prb); + ra_dl_alloc_re(&prb_alloc, cell.nof_prb, 1, cell.nof_prb<10?(cfi+1):cfi, CPNORM); ra_mcs_from_idx_dl(mcs_idx, prb_alloc.slot[0].nof_prb, &ra_dl.mcs); ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb); diff --git a/lte/examples/pdsch_ue.c b/lte/examples/pdsch_ue.c index 9a4ce7236..bfa045a1e 100644 --- a/lte/examples/pdsch_ue.c +++ b/lte/examples/pdsch_ue.c @@ -524,7 +524,7 @@ void *plot_thread_run(void *arg) { while(1) { sem_wait(&plot_sem); - uint32_t nof_symbols = ue_dl.harq_process[0].prb_alloc.re_sf[plot_sf_idx]; + uint32_t nof_symbols = ue_dl.harq_process[0].dl_alloc.re_sf[plot_sf_idx]; for (i = 0; i < nof_re; i++) { tmp_plot[i] = 20 * log10f(cabsf(ue_dl.sf_symbols[i])); if (isinf(tmp_plot[i])) { diff --git a/lte/phy/include/liblte/phy/common/phy_common.h b/lte/phy/include/liblte/phy/common/phy_common.h index 7ea25dae0..3fc45a2ef 100644 --- a/lte/phy/include/liblte/phy/common/phy_common.h +++ b/lte/phy/include/liblte/phy/common/phy_common.h @@ -141,7 +141,7 @@ typedef enum LIBLTE_API { typedef struct LIBLTE_API { int id; float fd; -}lte_earfcn_t; +} lte_earfcn_t; LIBLTE_API enum band_geographical_area { ALL, NAR, APAC, EMEA, JAPAN, CALA, NA diff --git a/lte/phy/include/liblte/phy/phch/harq.h b/lte/phy/include/liblte/phy/phch/harq.h index c1ec7a022..a960ba9ef 100644 --- a/lte/phy/include/liblte/phy/phch/harq.h +++ b/lte/phy/include/liblte/phy/phch/harq.h @@ -47,9 +47,12 @@ typedef struct LIBLTE_API { ra_mcs_t mcs; uint32_t rv; uint32_t sf_idx; - ra_prb_t prb_alloc; + ra_dl_alloc_t dl_alloc; + ra_ul_alloc_t ul_alloc; lte_cell_t cell; + ra_ul_hopping_t ul_hopping; + uint32_t nof_re; // Number of RE per subframe uint32_t nof_bits; // Number of bits per subframe uint32_t nof_symb; // Number of symbols per subframe @@ -71,13 +74,13 @@ LIBLTE_API int harq_setup_dl(harq_t *p, ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx, - ra_prb_t *prb_alloc); + ra_dl_alloc_t *prb_alloc); LIBLTE_API int harq_setup_ul(harq_t *p, ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx, - ra_prb_t *prb_alloc); + ra_ul_alloc_t *prb_alloc); LIBLTE_API void harq_reset(harq_t *p); diff --git a/lte/phy/include/liblte/phy/phch/pusch.h b/lte/phy/include/liblte/phy/phch/pusch.h index d77eaa63b..b898d8fa5 100644 --- a/lte/phy/include/liblte/phy/phch/pusch.h +++ b/lte/phy/include/liblte/phy/phch/pusch.h @@ -70,7 +70,8 @@ typedef struct LIBLTE_API { modem_table_t mod[4]; demod_soft_t demod; sequence_t seq_pusch[NSUBFRAMES_X_FRAME]; - + sequence_t seq_type2_fo; + sch_t dl_sch; }pusch_t; diff --git a/lte/phy/include/liblte/phy/phch/ra.h b/lte/phy/include/liblte/phy/phch/ra.h index 816600466..6f6aacd8d 100644 --- a/lte/phy/include/liblte/phy/phch/ra.h +++ b/lte/phy/include/liblte/phy/phch/ra.h @@ -80,7 +80,23 @@ typedef struct LIBLTE_API { ra_prb_slot_t slot[2]; uint32_t lstart; uint32_t re_sf[NSUBFRAMES_X_FRAME]; -} ra_prb_t; +} ra_dl_alloc_t; + +typedef struct LIBLTE_API { + uint32_t n_prb[2]; + uint32_t L_prb; + uint32_t freq_hopping; +} ra_ul_alloc_t; + +typedef struct { + enum { + hop_mode_inter_sf = 1, + hop_mode_intra_sf = 0 + } hop_mode; + uint32_t current_tx_nb; + uint32_t hopping_offset; + uint32_t n_sb; +} ra_ul_hopping_t; typedef struct LIBLTE_API { uint16_t rnti; @@ -90,7 +106,7 @@ typedef struct LIBLTE_API { ra_type1_t type1_alloc; ra_type2_t type2_alloc; }; - ra_prb_t prb_alloc; + ra_dl_alloc_t prb_alloc; uint32_t mcs_idx; ra_mcs_t mcs; uint32_t harq_process; @@ -110,7 +126,7 @@ typedef struct LIBLTE_API { hop_type_2 = 3 } freq_hop_fl; - ra_prb_t prb_alloc; + ra_ul_alloc_t prb_alloc; ra_type2_t type2_alloc; uint32_t mcs_idx; @@ -126,19 +142,20 @@ LIBLTE_API void ra_prb_fprint(FILE *f, ra_prb_slot_t *prb, uint32_t nof_prb); -LIBLTE_API int ra_prb_get_dl(ra_prb_t *prb, +LIBLTE_API int ra_dl_alloc(ra_dl_alloc_t *prb, ra_pdsch_t *ra, uint32_t nof_prb); -LIBLTE_API int ra_prb_get_ul(ra_prb_t *prb, - ra_pusch_t *ra, - uint32_t nof_prb); +LIBLTE_API int ra_ul_alloc(ra_ul_alloc_t *prb, + ra_pusch_t *ra, + uint32_t n_rb_ho, + uint32_t nof_prb); -LIBLTE_API void ra_prb_get_re_dl(ra_prb_t *prb_dist, - uint32_t nof_prb, - uint32_t nof_ports, - uint32_t nof_ctrl_symbols, - lte_cp_t cp); +LIBLTE_API void ra_dl_alloc_re(ra_dl_alloc_t *prb_dist, + uint32_t nof_prb, + uint32_t nof_ports, + uint32_t nof_ctrl_symbols, + lte_cp_t cp); LIBLTE_API uint32_t ra_nprb_dl(ra_pdsch_t *ra, uint32_t nof_prb); diff --git a/lte/phy/lib/filter/src/dft_precoding.c b/lte/phy/lib/filter/src/dft_precoding.c index de3500028..8874f7f33 100644 --- a/lte/phy/lib/filter/src/dft_precoding.c +++ b/lte/phy/lib/filter/src/dft_precoding.c @@ -48,7 +48,7 @@ int dft_precoding_init(dft_precoding_t *q, uint32_t max_prb) if (max_prb <= MAX_PRB) { ret = LIBLTE_ERROR; - for (uint32_t i=2;idft_plan[i], i*RE_X_RB, FORWARD)) { @@ -77,7 +77,7 @@ clean_exit: /* Free DFT plans for transform precoding */ void dft_precoding_free(dft_precoding_t *q) { - for (uint32_t i=2;imax_prb;i++) { + for (uint32_t i=1;imax_prb;i++) { if(dft_precoding_valid_prb(i)) { DEBUG("Freeing DFT precoding plan for %d PRBs\n", i); dft_plan_free(&q->dft_plan[i]); @@ -88,7 +88,7 @@ void dft_precoding_free(dft_precoding_t *q) } bool dft_precoding_valid_prb(uint32_t nof_prb) { - if ((nof_prb%2) == 0 || (nof_prb%3) == 0 || (nof_prb%5) == 0) { + if (nof_prb == 1 || (nof_prb%2) == 0 || (nof_prb%3) == 0 || (nof_prb%5) == 0) { return true; } else { return false; diff --git a/lte/phy/lib/phch/src/dci.c b/lte/phy/lib/phch/src/dci.c index 4c29a4fb6..87e7a6615 100644 --- a/lte/phy/lib/phch/src/dci.c +++ b/lte/phy/lib/phch/src/dci.c @@ -77,12 +77,12 @@ int dci_msg_to_ra_dl(dci_msg_t *msg, uint16_t msg_rnti, uint16_t c_rnti, ra_pdsch_fprint(stdout, ra_dl, cell.nof_prb); } - if (ra_prb_get_dl(&ra_dl->prb_alloc, ra_dl, cell.nof_prb)) { + if (ra_dl_alloc(&ra_dl->prb_alloc, ra_dl, cell.nof_prb)) { fprintf(stderr, "Error computing resource allocation\n"); return ret; } - ra_prb_get_re_dl(&ra_dl->prb_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, cell.cp); + ra_dl_alloc_re(&ra_dl->prb_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, cell.cp); ret = LIBLTE_SUCCESS; } else { diff --git a/lte/phy/lib/phch/src/harq.c b/lte/phy/lib/phch/src/harq.c index 1fafcdd67..139ee7bad 100644 --- a/lte/phy/lib/phch/src/harq.c +++ b/lte/phy/lib/phch/src/harq.c @@ -180,10 +180,10 @@ void harq_reset(harq_t *q) { } bzero(&q->mcs, sizeof(ra_mcs_t)); bzero(&q->cb_segm, sizeof(struct cb_segm)); - bzero(&q->prb_alloc, sizeof(ra_prb_t)); + bzero(&q->dl_alloc, sizeof(ra_dl_alloc_t)); } -static int harq_setup_common(harq_t *q, ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx, ra_prb_t *prb_alloc) { +static int harq_setup_common(harq_t *q, ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx) { if (mcs.tbs != q->mcs.tbs) { codeblock_segmentation(&q->cb_segm, mcs.tbs); if (q->cb_segm.C > q->max_cb) { @@ -193,53 +193,54 @@ static int harq_setup_common(harq_t *q, ra_mcs_t mcs, uint32_t rv, uint32_t sf_i } } - memcpy(&q->prb_alloc, prb_alloc, sizeof(ra_prb_t)); q->mcs = mcs; q->sf_idx = sf_idx; q->rv = rv; return LIBLTE_SUCCESS; } -int harq_setup_dl(harq_t *q, ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx, ra_prb_t *prb_alloc) { +int harq_setup_dl(harq_t *q, ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx, ra_dl_alloc_t *dl_alloc) { int ret = LIBLTE_ERROR_INVALID_INPUTS; if (q != NULL && rv < 4 && sf_idx < 10) { - ret = harq_setup_common(q, mcs, rv, sf_idx, prb_alloc); + ret = harq_setup_common(q, mcs, rv, sf_idx); if (ret) { return ret; } - + memcpy(&q->dl_alloc, dl_alloc, sizeof(ra_dl_alloc_t)); + // Number of symbols, RE and bits per subframe for DL - q->nof_re = q->prb_alloc.re_sf[q->sf_idx]; - q->nof_symb = 2*CP_NSYMB(q->cell.cp)-q->prb_alloc.lstart; + q->nof_re = q->dl_alloc.re_sf[q->sf_idx]; + q->nof_symb = 2*CP_NSYMB(q->cell.cp)-q->dl_alloc.lstart; q->nof_bits = q->nof_re * lte_mod_bits_x_symbol(q->mcs.mod); - q->nof_prb = q->prb_alloc.slot[0].nof_prb; + q->nof_prb = q->dl_alloc.slot[0].nof_prb; ret = LIBLTE_SUCCESS; } return ret; } -int harq_setup_ul(harq_t *q, ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx, ra_prb_t *prb_alloc) { +int harq_setup_ul(harq_t *q, ra_mcs_t mcs, uint32_t rv, uint32_t sf_idx, ra_ul_alloc_t *ul_alloc) { int ret = LIBLTE_ERROR_INVALID_INPUTS; if (q != NULL && rv < 4 && sf_idx < 10) { - ret = harq_setup_common(q, mcs, rv, sf_idx, prb_alloc); + ret = harq_setup_common(q, mcs, rv, sf_idx); if (ret) { return ret; } - + memcpy(&q->ul_alloc, ul_alloc, sizeof(ra_ul_alloc_t)); + // Number of symbols, RE and bits per subframe for UL q->nof_symb = 2*(CP_NSYMB(q->cell.cp)-1); - q->nof_re = q->nof_symb*q->prb_alloc.slot[0].nof_prb*RE_X_RB; + q->nof_re = q->nof_symb*q->ul_alloc.L_prb*RE_X_RB; q->nof_bits = q->nof_re * lte_mod_bits_x_symbol(q->mcs.mod); - q->nof_prb = q->prb_alloc.slot[0].nof_prb; + q->nof_prb = q->ul_alloc.L_prb; ret = LIBLTE_SUCCESS; } diff --git a/lte/phy/lib/phch/src/pdsch.c b/lte/phy/lib/phch/src/pdsch.c index 0a9e480a4..a7ef6e539 100644 --- a/lte/phy/lib/phch/src/pdsch.c +++ b/lte/phy/lib/phch/src/pdsch.c @@ -58,7 +58,7 @@ extern int indices_ptr; #endif -int pdsch_cp(pdsch_t *q, cf_t *input, cf_t *output, ra_prb_t *prb_alloc, +int pdsch_cp(pdsch_t *q, cf_t *input, cf_t *output, ra_dl_alloc_t *prb_alloc, uint32_t nsubframe, bool put) { uint32_t s, n, l, lp, lstart, lend, nof_refs; bool is_pbch, is_sss; @@ -179,7 +179,7 @@ int pdsch_cp(pdsch_t *q, cf_t *input, cf_t *output, ra_prb_t *prb_alloc, * 36.211 10.3 section 6.3.5 */ int pdsch_put(pdsch_t *q, cf_t *pdsch_symbols, cf_t *sf_symbols, - ra_prb_t *prb_alloc, uint32_t subframe) { + ra_dl_alloc_t *prb_alloc, uint32_t subframe) { return pdsch_cp(q, pdsch_symbols, sf_symbols, prb_alloc, subframe, true); } @@ -191,7 +191,7 @@ int pdsch_put(pdsch_t *q, cf_t *pdsch_symbols, cf_t *sf_symbols, * 36.211 10.3 section 6.3.5 */ int pdsch_get(pdsch_t *q, cf_t *sf_symbols, cf_t *pdsch_symbols, - ra_prb_t *prb_alloc, uint32_t subframe) { + ra_dl_alloc_t *prb_alloc, uint32_t subframe) { return pdsch_cp(q, sf_symbols, pdsch_symbols, prb_alloc, subframe, false); } @@ -343,7 +343,7 @@ int pdsch_decode(pdsch_t *q, harq_t *harq, cf_t *sf_symbols, cf_t *ce[MAX_PORTS] memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports)); /* extract symbols */ - n = pdsch_get(q, sf_symbols, q->pdsch_symbols[0], &harq->prb_alloc, harq->sf_idx); + n = pdsch_get(q, sf_symbols, q->pdsch_symbols[0], &harq->dl_alloc, harq->sf_idx); if (n != harq->nof_re) { fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n); return LIBLTE_ERROR; @@ -351,7 +351,7 @@ int pdsch_decode(pdsch_t *q, harq_t *harq, cf_t *sf_symbols, cf_t *ce[MAX_PORTS] /* extract channel estimates */ for (i = 0; i < q->cell.nof_ports; i++) { - n = pdsch_get(q, ce[i], q->ce[i], &harq->prb_alloc, harq->sf_idx); + n = pdsch_get(q, ce[i], q->ce[i], &harq->dl_alloc, harq->sf_idx); if (n != harq->nof_re) { fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n); return LIBLTE_ERROR; @@ -459,7 +459,7 @@ int pdsch_encode(pdsch_t *q, harq_t *harq, uint8_t *data, cf_t *sf_symbols[MAX_P /* mapping to resource elements */ for (i = 0; i < q->cell.nof_ports; i++) { - pdsch_put(q, q->pdsch_symbols[i], sf_symbols[i], &harq->prb_alloc, harq->sf_idx); + pdsch_put(q, q->pdsch_symbols[i], sf_symbols[i], &harq->dl_alloc, harq->sf_idx); } ret = LIBLTE_SUCCESS; } else { diff --git a/lte/phy/lib/phch/src/pusch.c b/lte/phy/lib/phch/src/pusch.c index 8d282f28a..0346ef5ed 100644 --- a/lte/phy/lib/phch/src/pusch.c +++ b/lte/phy/lib/phch/src/pusch.c @@ -49,47 +49,113 @@ const static lte_mod_t modulations[4] = { LTE_BPSK, LTE_QPSK, LTE_QAM16, LTE_QAM64 }; -int pusch_cp(pusch_t *q, ra_prb_t *prb_alloc, cf_t *input, cf_t *output, bool advance_input) +static int f_hop_sum(pusch_t *q, uint32_t i) { + uint32_t sum = 0; + for (uint32_t k=i*10+1;kseq_type2_fo.c[k]<<(k-(i*10+1))); + } + return sum; +} + +static int f_hop(pusch_t *q, ra_ul_hopping_t *hopping, int i) { + if (i == -1) { + return 0; + } else { + if (hopping->n_sb == 1) { + return 0; + } else if (hopping->n_sb == 2) { + return (f_hop(q, hopping, i-1) + f_hop_sum(q, i))%2; + } else { + return (f_hop(q, hopping, i-1) + f_hop_sum(q, i)%(hopping->n_sb-1)+1)%hopping->n_sb; + } + } +} + +static int f_m(pusch_t *q, ra_ul_hopping_t *hopping, uint32_t i) { + if (hopping->n_sb == 1) { + if (hopping->hop_mode == hop_mode_inter_sf) { + return hopping->current_tx_nb%2; + } else { + return i%2; + } + } else { + return q->seq_type2_fo.c[i*10]; + } +} + +int pusch_cp(pusch_t *q, harq_t *harq, cf_t *input, cf_t *output, bool advance_input) { cf_t *in_ptr = input; cf_t *out_ptr = output; + ra_ul_hopping_t *hopping = &harq->ul_hopping; uint32_t L_ref = 3; if (CP_ISEXT(q->cell.cp)) { L_ref = 2; } - + INFO("PUSCH Freq hopping: %d\n", harq->ul_alloc.freq_hopping); for (uint32_t slot=0;slot<2;slot++) { + uint32_t n_prb_tilde = harq->ul_alloc.n_prb[slot]; + if (harq->ul_alloc.freq_hopping == 1) { + if (hopping->hop_mode == hop_mode_inter_sf) { + n_prb_tilde = harq->ul_alloc.n_prb[hopping->current_tx_nb%2]; + } else { + n_prb_tilde = harq->ul_alloc.n_prb[slot]; + } + } + if (harq->ul_alloc.freq_hopping == 2) { + /* Freq hopping type 2 as defined in 5.3.4 of 36.211 */ + uint32_t n_vrb_tilde = harq->ul_alloc.n_prb[0]; + if (hopping->n_sb > 1) { + n_vrb_tilde -= (hopping->hopping_offset-1)/2+1; + } + int i=0; + if (hopping->hop_mode == hop_mode_inter_sf) { + i = harq->sf_idx; + } else { + i = 2*harq->sf_idx+slot; + } + uint32_t n_rb_sb = q->cell.nof_prb; + if (hopping->n_sb > 1) { + n_rb_sb = (n_rb_sb-hopping->hopping_offset-hopping->hopping_offset%2)/hopping->n_sb; + } + n_prb_tilde = (n_vrb_tilde+f_hop(q, hopping, i)*n_rb_sb+ + (n_rb_sb-1)-2*(n_vrb_tilde%n_rb_sb)*f_m(q, hopping, i))%(n_rb_sb*hopping->n_sb); + + INFO("n_prb_tilde: %d, n_vrb_tilde: %d, n_rb_sb: %d, n_sb: %d\n", n_prb_tilde, n_vrb_tilde, n_rb_sb, hopping->n_sb); + if (hopping->n_sb > 1) { + n_prb_tilde += (hopping->hopping_offset-1)/2+1; + } + + } + INFO("Allocating PUSCH %d PRB to index %d at slot %d\n",harq->ul_alloc.L_prb, n_prb_tilde,slot); for (uint32_t l=0;lcell.cp);l++) { if (l != L_ref) { - for (uint32_t n=0;ncell.nof_prb;n++) { - if (prb_alloc->slot[slot].prb_idx[n]) { - uint32_t idx = RE_IDX(q->cell.nof_prb, l+slot*CP_NSYMB(q->cell.cp), n*RE_X_RB); - if (advance_input) { - out_ptr = &output[idx]; - } else { - in_ptr = &input[idx]; - } - memcpy(out_ptr, in_ptr, RE_X_RB * sizeof(cf_t)); - if (advance_input) { - in_ptr += RE_X_RB; - } else { - out_ptr += RE_X_RB; - } - } + uint32_t idx = RE_IDX(q->cell.nof_prb, l+slot*CP_NSYMB(q->cell.cp), + n_prb_tilde*RE_X_RB); + if (advance_input) { + out_ptr = &output[idx]; + } else { + in_ptr = &input[idx]; + } + memcpy(out_ptr, in_ptr, harq->ul_alloc.L_prb * RE_X_RB * sizeof(cf_t)); + if (advance_input) { + in_ptr += harq->ul_alloc.L_prb*RE_X_RB; + } else { + out_ptr += harq->ul_alloc.L_prb*RE_X_RB; } } } } - return RE_X_RB*prb_alloc->slot[0].nof_prb; + return RE_X_RB*harq->ul_alloc.L_prb; } -int pusch_put(pusch_t *q, ra_prb_t *prb_alloc, cf_t *input, cf_t *output) { - return pusch_cp(q, prb_alloc, input, output, true); +int pusch_put(pusch_t *q, harq_t *harq, cf_t *input, cf_t *output) { + return pusch_cp(q, harq, input, output, true); } -int pusch_get(pusch_t *q, ra_prb_t *prb_alloc, cf_t *input, cf_t *output) { - return pusch_cp(q, prb_alloc, input, output, false); +int pusch_get(pusch_t *q, harq_t *harq, cf_t *input, cf_t *output) { + return pusch_cp(q, harq, input, output, false); } @@ -116,6 +182,12 @@ int pusch_init(pusch_t *q, lte_cell_t cell) { goto clean; } } + + /* Precompute sequence for type2 frequency hopping */ + if (sequence_LTE_pr(&q->seq_type2_fo, 210, q->cell.id)) { + fprintf(stderr, "Error initiating type2 frequency hopping sequence\n"); + goto clean; + } demod_soft_init(&q->demod, q->max_re); demod_soft_alg_set(&q->demod, APPROX); @@ -239,14 +311,14 @@ int pusch_decode(pusch_t *q, harq_t *harq, cf_t *sf_symbols, cf_t *ce, float noi harq->sf_idx, lte_mod_string(harq->mcs.mod), harq->mcs.tbs, harq->nof_re, harq->nof_bits, harq->rv); /* extract symbols */ - n = pusch_get(q, &harq->prb_alloc, sf_symbols, q->pusch_d); + n = pusch_get(q, harq, sf_symbols, q->pusch_d); if (n != harq->nof_re) { fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n); return LIBLTE_ERROR; } /* extract channel estimates */ - n = pusch_get(q, &harq->prb_alloc, ce, q->ce); + n = pusch_get(q, harq, ce, q->ce); if (n != harq->nof_re) { fprintf(stderr, "Error expecting %d symbols but got %d\n", harq->nof_re, n); return LIBLTE_ERROR; @@ -256,7 +328,7 @@ int pusch_decode(pusch_t *q, harq_t *harq, cf_t *sf_symbols, cf_t *ce, float noi harq->nof_re, noise_estimate); dft_predecoding(&q->dft_precoding, q->pusch_z, q->pusch_d, - harq->prb_alloc.slot[0].nof_prb, harq->nof_symb); + harq->ul_alloc.L_prb, harq->nof_symb); /* demodulate symbols * The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation, @@ -322,10 +394,10 @@ int pusch_uci_encode(pusch_t *q, harq_t *harq, uint8_t *data, uci_data_t uci_dat mod_modulate(&q->mod[harq->mcs.mod], (uint8_t*) q->pusch_q, q->pusch_d, harq->nof_bits); dft_precoding(&q->dft_precoding, q->pusch_d, q->pusch_z, - harq->prb_alloc.slot[0].nof_prb, harq->nof_symb); + harq->ul_alloc.L_prb, harq->nof_symb); /* mapping to resource elements */ - pusch_put(q, &harq->prb_alloc, q->pusch_z, sf_symbols); + pusch_put(q, harq, q->pusch_z, sf_symbols); ret = LIBLTE_SUCCESS; } else { diff --git a/lte/phy/lib/phch/src/ra.c b/lte/phy/lib/phch/src/ra.c index de1a015a6..3a416dacc 100644 --- a/lte/phy/lib/phch/src/ra.c +++ b/lte/phy/lib/phch/src/ra.c @@ -108,8 +108,83 @@ uint32_t ra_re_x_prb(uint32_t subframe, uint32_t slot, uint32_t prb_idx, uint32_ return re; } +void ra_prb_fprint(FILE *f, ra_prb_slot_t *prb, uint32_t nof_prb) { + int i; + if (prb->nof_prb > 0) { + for (i=0;iprb_idx[i]) { + fprintf(f, "%d, ", i); + } + } + fprintf(f, "\n"); + } + +} + +/** Compute PRB allocation for Uplink as defined in 8.1 and 8.4 of 36.213 */ +int ra_ul_alloc(ra_ul_alloc_t *prb_dist, ra_pusch_t *ra, uint32_t n_rb_ho, uint32_t nof_prb) { + + bzero(prb_dist, sizeof(ra_ul_alloc_t)); + prb_dist->L_prb = ra->type2_alloc.L_crb; + uint32_t n_prb_1 = ra->type2_alloc.RB_start; + uint32_t n_rb_pusch = 0; + + if (n_rb_ho%2) { + n_rb_ho++; + } + + if (ra->freq_hop_fl == hop_disabled || ra->freq_hop_fl == hop_type_2) { + /* For no freq hopping or type2 freq hopping, n_prb is the same + * n_prb_tilde is calculated during resource mapping + */ + for (uint32_t i=0;i<2;i++) { + prb_dist->n_prb[i] = n_prb_1; + } + if (ra->freq_hop_fl == hop_disabled) { + prb_dist->freq_hopping = 0; + } else { + prb_dist->freq_hopping = 2; + } + INFO("prb1: %d, prb2: %d, L: %d\n", prb_dist->n_prb[0], prb_dist->n_prb[1], prb_dist->L_prb); + } else { + /* Type1 frequency hopping as defined in 8.4.1 of 36.213 + * frequency offset between 1st and 2nd slot is fixed. + */ + n_rb_pusch = nof_prb - n_rb_ho - (nof_prb%2); + + // starting prb idx for slot 0 is as given by resource grant + prb_dist->n_prb[0] = n_prb_1; + if (n_prb_1 < n_rb_ho/2) { + fprintf(stderr, "Invalid Frequency Hopping parameters. Offset: %d, n_prb_1: %d\n", n_rb_ho, n_prb_1); + } + uint32_t n_prb_1_tilde = n_prb_1; + + // prb idx for slot 1 + switch(ra->freq_hop_fl) { + case hop_quart: + prb_dist->n_prb[1] = (n_rb_pusch/4+ n_prb_1_tilde)%n_rb_pusch; + break; + case hop_quart_neg: + if (n_prb_1 < n_rb_pusch/4) { + prb_dist->n_prb[1] = (n_rb_pusch+ n_prb_1_tilde -n_rb_pusch/4); + } else { + prb_dist->n_prb[1] = (n_prb_1_tilde -n_rb_pusch/4); + } + break; + case hop_half: + prb_dist->n_prb[1] = (n_rb_pusch/2+ n_prb_1_tilde)%n_rb_pusch; + break; + default: + break; + } + INFO("n_rb_pusch: %d, prb1: %d, prb2: %d, L: %d\n", n_rb_pusch, prb_dist->n_prb[0], prb_dist->n_prb[1], prb_dist->L_prb); + prb_dist->freq_hopping = 1; + } + return LIBLTE_SUCCESS; +} + /* Computes the number of RE for each PRB in the prb_dist structure */ -void ra_prb_get_re_dl(ra_prb_t *prb_dist, uint32_t nof_prb, uint32_t nof_ports, +void ra_dl_alloc_re(ra_dl_alloc_t *prb_dist, uint32_t nof_prb, uint32_t nof_ports, uint32_t nof_ctrl_symbols, lte_cp_t cp) { uint32_t i, j, s; @@ -129,49 +204,14 @@ void ra_prb_get_re_dl(ra_prb_t *prb_dist, uint32_t nof_prb, uint32_t nof_ports, } } -void ra_prb_fprint(FILE *f, ra_prb_slot_t *prb, uint32_t nof_prb) { - int i; - if (prb->nof_prb > 0) { - for (i=0;iprb_idx[i]) { - fprintf(f, "%d, ", i); - } - } - fprintf(f, "\n"); - } - -} - -/** Compute PRB allocation for Uplink as defined in 8.1 of 36.213 */ -int ra_prb_get_ul(ra_prb_t *prb_dist, ra_pusch_t *ra, uint32_t nof_prb) { - int i; - if (ra->type2_alloc.mode != t2_loc) { - fprintf(stderr, "Uplink only accepts type2 localized scheduling\n"); - return LIBLTE_ERROR; - } - bzero(prb_dist, sizeof(ra_prb_t)); - - switch (ra->freq_hop_fl) { - case hop_disabled: - for (i = 0; i < ra->type2_alloc.L_crb; i++) { - prb_dist->slot[0].prb_idx[i + ra->type2_alloc.RB_start] = true; - prb_dist->slot[0].nof_prb++; - } - memcpy(&prb_dist->slot[1], &prb_dist->slot[0], sizeof(ra_prb_slot_t)); - break; - - } - return LIBLTE_SUCCESS; -} - /** Compute PRB allocation for Downlink as defined in 7.1.6 of 36.213 */ -int ra_prb_get_dl(ra_prb_t *prb_dist, ra_pdsch_t *ra, uint32_t nof_prb) { +int ra_dl_alloc(ra_dl_alloc_t *prb_dist, ra_pdsch_t *ra, uint32_t nof_prb) { int i, j; uint32_t bitmask; uint32_t P = ra_type0_P(nof_prb); uint32_t n_rb_rbg_subset, n_rb_type1; - bzero(prb_dist, sizeof(ra_prb_t)); + bzero(prb_dist, sizeof(ra_dl_alloc_t)); switch (ra->alloc_type) { case alloc_type0: bitmask = ra->type0_alloc.rbg_bitmask; @@ -540,8 +580,8 @@ void ra_pdsch_fprint(FILE *f, ra_pdsch_t *ra, uint32_t nof_prb) { break; } - ra_prb_t alloc; - ra_prb_get_dl(&alloc, ra, nof_prb); + ra_dl_alloc_t alloc; + ra_dl_alloc(&alloc, ra, nof_prb); for (int s = 0; s < 2; s++) { fprintf(f, " - PRB Bitmap Assignment %dst slot:\n", s); ra_prb_fprint(f, &alloc.slot[s], nof_prb); diff --git a/lte/phy/lib/phch/src/sch.c b/lte/phy/lib/phch/src/sch.c index 7bab60c94..cd1f0fce6 100644 --- a/lte/phy/lib/phch/src/sch.c +++ b/lte/phy/lib/phch/src/sch.c @@ -439,7 +439,7 @@ int ulsch_uci_encode(sch_t *q, harq_t *harq, uint8_t *data, uci_data_t uci_data, uint32_t Q_prime_ri = 0; uint32_t Q_m = lte_mod_bits_x_symbol(harq->mcs.mod); - uint32_t nof_symbols = 12*harq->prb_alloc.slot[0].nof_prb*RE_X_RB; + uint32_t nof_symbols = 12*harq->ul_alloc.L_prb*RE_X_RB; uint32_t nb_q = nof_symbols * Q_m; bzero(q_bits, sizeof(uint8_t) * nb_q); diff --git a/lte/phy/lib/phch/src/uci.c b/lte/phy/lib/phch/src/uci.c index 38d7b8d58..da6198254 100644 --- a/lte/phy/lib/phch/src/uci.c +++ b/lte/phy/lib/phch/src/uci.c @@ -115,7 +115,7 @@ void uci_cqi_free(uci_cqi_pusch_t *q) { } static uint32_t Q_prime_cqi(uint32_t O, float beta, uint32_t Q_prime_ri, harq_t *harq) { - uint32_t M_sc = harq->prb_alloc.slot[0].nof_prb * RE_X_RB; + uint32_t M_sc = harq->ul_alloc.L_prb * RE_X_RB; uint32_t K = harq->cb_segm.C1*harq->cb_segm.K1 + harq->cb_segm.C2*harq->cb_segm.K2; @@ -128,7 +128,7 @@ static uint32_t Q_prime_cqi(uint32_t O, float beta, uint32_t Q_prime_ri, harq_t Q_prime = MIN(x, M_sc * harq->nof_symb - Q_prime_ri); } else { - Q_prime = 12*harq->prb_alloc.slot[0].nof_prb*RE_X_RB - Q_prime_ri; + Q_prime = 12*harq->ul_alloc.L_prb*RE_X_RB - Q_prime_ri; } return Q_prime; @@ -287,7 +287,7 @@ static int uci_ulsch_interleave_ri(uint8_t ri_coded_bits[6], uint32_t ri_q_bit_i } static uint32_t Q_prime_ri_ack(uint32_t O, uint32_t O_cqi, float beta, harq_t *harq) { - uint32_t M_sc = harq->prb_alloc.slot[0].nof_prb * RE_X_RB; + uint32_t M_sc = harq->ul_alloc.L_prb * RE_X_RB; uint32_t K = harq->cb_segm.C1*harq->cb_segm.K1 + harq->cb_segm.C2*harq->cb_segm.K2; diff --git a/lte/phy/lib/phch/test/dlsch_encode_test_mex.c b/lte/phy/lib/phch/test/dlsch_encode_test_mex.c index c9fd94227..e597fc51f 100644 --- a/lte/phy/lib/phch/test/dlsch_encode_test_mex.c +++ b/lte/phy/lib/phch/test/dlsch_encode_test_mex.c @@ -47,7 +47,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) sch_t dlsch; uint8_t *trblkin; ra_mcs_t mcs; - ra_prb_t prb_alloc; + ra_dl_alloc_t prb_alloc; harq_t harq_process; uint32_t rv; diff --git a/lte/phy/lib/phch/test/pdsch_test.c b/lte/phy/lib/phch/test/pdsch_test.c index adbbc4057..5ba1dda21 100644 --- a/lte/phy/lib/phch/test/pdsch_test.c +++ b/lte/phy/lib/phch/test/pdsch_test.c @@ -132,7 +132,7 @@ int main(int argc, char **argv) { int ret = -1; struct timeval t[3]; ra_mcs_t mcs; - ra_prb_t prb_alloc; + ra_dl_alloc_t prb_alloc; harq_t harq_process; uint32_t rv; @@ -153,7 +153,7 @@ int main(int argc, char **argv) { } memcpy(&prb_alloc.slot[1], &prb_alloc.slot[0], sizeof(ra_prb_slot_t)); - ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, cell.cp); + ra_dl_alloc_re(&prb_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, cell.cp); /* init memory */ for (i=0;i= 3) { - mexutils_write_cf(pdsch.pdsch_symbols[0], &plhs[2], harq_process.prb_alloc.re_sf[sf_idx], 1); + mexutils_write_cf(pdsch.pdsch_symbols[0], &plhs[2], harq_process.dl_alloc.re_sf[sf_idx], 1); } if (nlhs >= 4) { - mexutils_write_cf(pdsch.pdsch_d, &plhs[3], harq_process.prb_alloc.re_sf[sf_idx], 1); + mexutils_write_cf(pdsch.pdsch_d, &plhs[3], harq_process.dl_alloc.re_sf[sf_idx], 1); } if (nlhs >= 5) { - mexutils_write_f(pdsch.pdsch_e, &plhs[4], harq_process.prb_alloc.re_sf[sf_idx] * lte_mod_bits_x_symbol(mcs.mod), 1); + mexutils_write_f(pdsch.pdsch_e, &plhs[4], harq_process.dl_alloc.re_sf[sf_idx] * lte_mod_bits_x_symbol(mcs.mod), 1); } chest_dl_free(&chest); diff --git a/lte/phy/lib/phch/test/pusch_encode_test_mex.c b/lte/phy/lib/phch/test/pusch_encode_test_mex.c index 7c5d2785e..17fadeb98 100644 --- a/lte/phy/lib/phch/test/pusch_encode_test_mex.c +++ b/lte/phy/lib/phch/test/pusch_encode_test_mex.c @@ -109,22 +109,14 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) return; } - ra_prb_t prb_alloc; - // Only localized PRB supported - prb_alloc.slot[0].nof_prb = mexutils_read_f(p, &prbset); - - for (uint32_t i=0;i