Added PUSCH Type1 Frequency Hopping

master
ismagom 10 years ago
parent e0b0440c77
commit 58ccecc8d7

@ -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);

@ -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])) {

@ -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

@ -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);

@ -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;

@ -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);

@ -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;i<max_prb;i++) {
for (uint32_t i=1;i<max_prb;i++) {
if(dft_precoding_valid_prb(i)) {
DEBUG("Initiating DFT precoding plan for %d PRBs\n", i);
if (dft_plan_c(&q->dft_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;i<q->max_prb;i++) {
for (uint32_t i=1;i<q->max_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;

@ -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 {

@ -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;
}

@ -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 {

@ -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;k<i*10+9;i++) {
sum += (q->seq_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;l<CP_NSYMB(q->cell.cp);l++) {
if (l != L_ref) {
for (uint32_t n=0;n<q->cell.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 {

@ -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;i<nof_prb;i++) {
if (prb->prb_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;i<nof_prb;i++) {
if (prb->prb_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);

@ -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);

@ -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;

@ -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;

@ -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<cell.nof_ports;i++) {

@ -58,7 +58,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
cf_t *input_fft, *input_signal;
int nof_re;
ra_mcs_t mcs;
ra_prb_t prb_alloc;
ra_dl_alloc_t dl_alloc;
harq_t harq_process;
uint32_t rv;
uint32_t rnti32;
@ -146,23 +146,23 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
}
// Only localized PRB supported
prb_alloc.slot[0].nof_prb = mexutils_read_f(p, &prbset);
dl_alloc.slot[0].nof_prb = mexutils_read_f(p, &prbset);
for (i=0;i<cell.nof_prb;i++) {
prb_alloc.slot[0].prb_idx[i] = false;
for (int j=0;j<prb_alloc.slot[0].nof_prb && !prb_alloc.slot[0].prb_idx[i];j++) {
dl_alloc.slot[0].prb_idx[i] = false;
for (int j=0;j<dl_alloc.slot[0].nof_prb && !dl_alloc.slot[0].prb_idx[i];j++) {
if ((int) prbset[j] == i) {
prb_alloc.slot[0].prb_idx[i] = true;
dl_alloc.slot[0].prb_idx[i] = true;
}
}
}
memcpy(&prb_alloc.slot[1], &prb_alloc.slot[0], sizeof(ra_prb_slot_t));
memcpy(&dl_alloc.slot[1], &dl_alloc.slot[0], sizeof(ra_prb_slot_t));
free(prbset);
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(&dl_alloc, cell.nof_prb, cell.nof_ports, cell.nof_prb<10?(cfi+1):cfi, cell.cp);
if (harq_setup_dl(&harq_process, mcs, rv, sf_idx, &prb_alloc)) {
if (harq_setup_dl(&harq_process, mcs, rv, sf_idx, &dl_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");
return;
}
@ -219,13 +219,13 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexutils_write_uint8(data, &plhs[1], mcs.tbs, 1);
}
if (nlhs >= 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);

@ -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<cell.nof_prb;i++) {
prb_alloc.slot[0].prb_idx[i] = false;
for (uint32_t j=0;j<prb_alloc.slot[0].nof_prb && !prb_alloc.slot[0].prb_idx[i];j++) {
if (prbset[j] == i) {
prb_alloc.slot[0].prb_idx[i] = true;
}
}
}
memcpy(&prb_alloc.slot[1], &prb_alloc.slot[0], sizeof(ra_prb_slot_t));
ra_ul_alloc_t prb_alloc;
prb_alloc.L_prb = mexutils_read_f(p, &prbset);
prb_alloc.n_prb[2*sf_idx] = prbset[0];
prb_alloc.n_prb[2*sf_idx+1] = prbset[0];
free(prbset);
mexPrintf("L_prb: %d, n_prb: %d\n", prb_alloc.L_prb, prb_alloc.n_prb[0]);
uint8_t *trblkin = NULL;
mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin);

@ -48,12 +48,20 @@ uint32_t tbs = 0;
uint32_t subframe = 1;
lte_mod_t modulation = LTE_QPSK;
uint32_t rv_idx = 0;
uint32_t L_prb = 2;
uint32_t n_prb = 0;
int freq_hop = -1;
int riv = -1;
void usage(char *prog) {
printf("Usage: %s [csrnfvmt] -l TBS \n", prog);
printf("Usage: %s [csrnfvmtLNF] -l TBS \n", prog);
printf("\t-m modulation (1: BPSK, 2: QPSK, 3: QAM16, 4: QAM64) [Default BPSK]\n");
printf("\t-c cell id [Default %d]\n", cell.id);
printf("\t-s subframe [Default %d]\n", subframe);
printf("\t-L L_prb [Default %d]\n", L_prb);
printf("\t-N n_prb [Default %d]\n", n_prb);
printf("\t-F frequency hopping [Default %d]\n", freq_hop);
printf("\t-R RIV [Default %d]\n", riv);
printf("\t-r rv_idx [Default %d]\n", rv_idx);
printf("\t-f cfi [Default %d]\n", cfi);
printf("\t-n cell.nof_prb [Default %d]\n", cell.nof_prb);
@ -62,7 +70,7 @@ void usage(char *prog) {
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "lcnfvmtsr")) != -1) {
while ((opt = getopt(argc, argv, "lcnfvmtsrLNFR")) != -1) {
switch(opt) {
case 'm':
switch(atoi(argv[optind])) {
@ -87,6 +95,18 @@ void parse_args(int argc, char **argv) {
case 's':
subframe = atoi(argv[optind]);
break;
case 'L':
L_prb = atoi(argv[optind]);
break;
case 'N':
n_prb = atoi(argv[optind]);
break;
case 'R':
riv = atoi(argv[optind]);
break;
case 'F':
freq_hop = atoi(argv[optind]);
break;
case 'r':
rv_idx = atoi(argv[optind]);
break;
@ -116,7 +136,7 @@ int main(int argc, char **argv) {
int ret = -1;
struct timeval t[3];
ra_mcs_t mcs;
ra_prb_t prb_alloc;
ra_ul_alloc_t prb_alloc;
harq_t harq_process;
parse_args(argc,argv);
@ -124,10 +144,8 @@ int main(int argc, char **argv) {
mcs.tbs = tbs;
mcs.mod = modulation;
bzero(&prb_alloc, sizeof(ra_prb_t));
prb_alloc.slot[0].nof_prb = 2;
memcpy(&prb_alloc.slot[1], &prb_alloc.slot[0], sizeof(ra_prb_slot_t));
bzero(&prb_alloc, sizeof(ra_ul_alloc_t));
if (pusch_init(&pusch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto quit;
@ -138,7 +156,7 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error initiating HARQ process\n");
goto quit;
}
printf("Encoding rv_idx=%d\n",rv_idx);
uint8_t tmp[20];
@ -158,12 +176,26 @@ int main(int argc, char **argv) {
uci_data.uci_cqi = tmp;
uci_data.uci_ri = 1;
uci_data.uci_ack = 1;
ra_pusch_t pusch_dci;
pusch_dci.freq_hop_fl = freq_hop;
if (riv < 0) {
pusch_dci.type2_alloc.L_crb = L_prb;
pusch_dci.type2_alloc.RB_start = n_prb;
} else {
ra_type2_from_riv((uint32_t) riv, &pusch_dci.type2_alloc.L_crb, &pusch_dci.type2_alloc.RB_start, cell.nof_prb, cell.nof_prb);
}
ra_ul_alloc(&prb_alloc, &pusch_dci, 0, cell.nof_prb);
if (harq_setup_ul(&harq_process, mcs, 0, subframe, &prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
goto quit;
}
harq_process.ul_hopping.n_sb = 1;
harq_process.ul_hopping.hopping_offset = 0;
harq_process.ul_hopping.hop_mode = hop_mode_inter_sf;
harq_process.ul_hopping.current_tx_nb = 0;
uint32_t nof_re = RE_X_RB*cell.nof_prb*2*CP_NSYMB(cell.cp);
sf_symbols = vec_malloc(sizeof(cf_t) * nof_re);
if (!sf_symbols) {

@ -46,11 +46,10 @@ void help()
/* the gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
int i;
sch_t ulsch;
uint8_t *trblkin;
ra_mcs_t mcs;
ra_prb_t prb_alloc;
ra_ul_alloc_t prb_alloc;
harq_t harq_process;
uint32_t rv;
uci_data_t uci_data;
@ -131,20 +130,12 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return;
}
prb_alloc.slot[0].nof_prb = mexutils_read_f(p, &prbset);
for (i=0;i<MAX_PRB;i++) {
prb_alloc.slot[0].prb_idx[i] = false;
for (int j=0;j<prb_alloc.slot[0].nof_prb && !prb_alloc.slot[0].prb_idx[i];j++) {
if ((int) prbset[j] == i) {
prb_alloc.slot[0].prb_idx[i] = true;
}
}
}
memcpy(&prb_alloc.slot[1], &prb_alloc.slot[0], sizeof(ra_prb_slot_t));
prb_alloc.L_prb = mexutils_read_f(p, &prbset);
prb_alloc.n_prb[0] = prbset[0];
prb_alloc.n_prb[1] = prbset[0];
free(prbset);
mexPrintf("Q_m: %d, NPRB: %d, RV: %d\n", lte_mod_bits_x_symbol(mcs.mod), prb_alloc.slot[0].nof_prb, rv);
mexPrintf("Q_m: %d, NPRB: %d, RV: %d\n", lte_mod_bits_x_symbol(mcs.mod), prb_alloc.L_prb, rv);
if (harq_setup_ul(&harq_process, mcs, 0, 0, &prb_alloc)) {
mexErrMsgTxt("Error configuring HARQ process\n");

Binary file not shown.

@ -1,6 +1,6 @@
clear
ueConfig=struct('NCellID',3,'NULRB',6,'NSubframe',0,'RNTI',1,'CyclicPrefixUL','Normal','NTxAnts',1);
puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',[0 2 4 5]','Modulation','QPSK','RV',0,'Shortened',0);
puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',[0 1]','Modulation','QPSK','RV',0,'Shortened',0);
addpath('../../debug/lte/phy/lib/phch/test')

Loading…
Cancel
Save