diff --git a/lte/phy/include/liblte/phy/phch/pusch.h b/lte/phy/include/liblte/phy/phch/pusch.h index ccbb1b386..dbdd12eb6 100644 --- a/lte/phy/include/liblte/phy/phch/pusch.h +++ b/lte/phy/include/liblte/phy/phch/pusch.h @@ -60,8 +60,6 @@ typedef struct LIBLTE_API { cf_t *pusch_d; void *pusch_q; - uint8_t *pusch_g_ri; - uint8_t *pusch_g_ack; void *pusch_g; /* tx & rx objects */ diff --git a/lte/phy/include/liblte/phy/phch/sch.h b/lte/phy/include/liblte/phy/phch/sch.h index 519e3eaea..632c8be23 100644 --- a/lte/phy/include/liblte/phy/phch/sch.h +++ b/lte/phy/include/liblte/phy/phch/sch.h @@ -105,8 +105,6 @@ LIBLTE_API int ulsch_uci_encode(sch_t *q, uint8_t *data, uci_data_t uci_data, uint8_t *g_bits, - uint8_t *g_bits_ack, - uint8_t *g_bits_ri, harq_t *harq_process, uint32_t rv_idx, uint8_t *q_bits); diff --git a/lte/phy/include/liblte/phy/phch/uci.h b/lte/phy/include/liblte/phy/phch/uci.h index b49663d9c..d4390903a 100644 --- a/lte/phy/include/liblte/phy/phch/uci.h +++ b/lte/phy/include/liblte/phy/phch/uci.h @@ -66,11 +66,19 @@ LIBLTE_API int uci_encode_cqi(uci_cqi_t *q, harq_t *harq_process, uint8_t *q_bits); -/* Encode UCI RI and HARQ ACK/NACK bits */ -LIBLTE_API int uci_encode_ri_ack(uint8_t data, - uint32_t O_cqi, - float beta, - harq_t *harq_process, - uint8_t q_bits[6]); +LIBLTE_API int uci_encode_ack(uint8_t data, + uint32_t O_cqi, + float beta, + harq_t *harq_process, + uint32_t H_prime_total, + uint8_t *q_bits); + +LIBLTE_API int uci_encode_ri(uint8_t data, + uint32_t O_cqi, + float beta, + harq_t *harq_process, + uint32_t H_prime_total, + uint8_t *q_bits); + #endif \ No newline at end of file diff --git a/lte/phy/lib/phch/src/pusch.c b/lte/phy/lib/phch/src/pusch.c index a14d2bf1d..6caa342b4 100644 --- a/lte/phy/lib/phch/src/pusch.c +++ b/lte/phy/lib/phch/src/pusch.c @@ -131,17 +131,6 @@ int pusch_init(pusch_t *q, lte_cell_t cell) { if (!q->pusch_g) { goto clean; } - - // Allocate buffers for q bits for coded RI and ACK bits - q->pusch_g_ack = vec_malloc(sizeof(uint8_t) * 4 * q->cell.nof_prb * lte_mod_bits_x_symbol(LTE_QAM64)); - if (!q->pusch_g_ack) { - goto clean; - } - q->pusch_g_ri = vec_malloc(sizeof(uint8_t) * 4 * q->cell.nof_prb * lte_mod_bits_x_symbol(LTE_QAM64)); - if (!q->pusch_g_ri) { - goto clean; - } - q->pusch_d = vec_malloc(sizeof(cf_t) * q->max_symbols); if (!q->pusch_d) { goto clean; @@ -183,12 +172,6 @@ void pusch_free(pusch_t *q) { if (q->pusch_g) { free(q->pusch_g); } - if (q->pusch_g_ack) { - free(q->pusch_g_ack); - } - if (q->pusch_g_ri) { - free(q->pusch_g_ri); - } for (i = 0; i < q->cell.nof_ports; i++) { if (q->ce[i]) { free(q->ce[i]); @@ -363,8 +346,7 @@ int pusch_uci_encode(pusch_t *q, uint8_t *data, uci_data_t uci_data, } memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports)); - if (ulsch_uci_encode(&q->dl_sch, data, uci_data, q->pusch_g, - q->pusch_g_ack, q->pusch_g_ri, harq_process, rv_idx, q->pusch_q)) + if (ulsch_uci_encode(&q->dl_sch, data, uci_data, q->pusch_g, harq_process, rv_idx, q->pusch_q)) { fprintf(stderr, "Error encoding TB\n"); return LIBLTE_ERROR; diff --git a/lte/phy/lib/phch/src/sch.c b/lte/phy/lib/phch/src/sch.c index ca81fc5e3..0544d68c9 100644 --- a/lte/phy/lib/phch/src/sch.c +++ b/lte/phy/lib/phch/src/sch.c @@ -403,192 +403,27 @@ int ulsch_decode(sch_t *q, float *e_bits, uint8_t *data, uint32_t tbs, uint32_t } -uint8_t ulsch_y_idx[10000]; -uint8_t ulsch_y_mat[10000]; - /* UL-SCH channel interleaver according to 5.5.2.8 of 36.212 */ -void ulsch_interleave2(uint8_t *q_bits, uint32_t nb_q, - uint8_t q_bits_ack[6], uint32_t Q_prime_ack, - uint8_t q_bits_ri[6], uint32_t Q_prime_ri, - uint32_t Q_m, uint8_t *g_bits) +void ulsch_interleave(uint8_t *g_bits, uint32_t Q_m, uint32_t H_prime_total, uint32_t N_pusch_symbs, uint8_t *q_bits) { - uint32_t C_mux; - uint32_t H_prime; - uint32_t H_prime_total; - uint32_t R_mux; - uint32_t R_prime_mux; - uint32_t i; - uint32_t j; - uint32_t k; - uint32_t r; - uint32_t idx; - uint32_t ri_column_set[4] = {1, 4, 7, 10}; - uint32_t ack_column_set[4] = {2, 3, 8, 9}; - uint32_t C_ri; - uint32_t C_ack; - uint32_t N_pusch_symbs = 12; - // Step 1: Define C_mux - C_mux = N_pusch_symbs; - - // Step 2: Define R_mux and R_prime_mux - H_prime = nb_q; - H_prime_total = H_prime + Q_prime_ri; - R_mux = (H_prime_total*Q_m)/C_mux; - R_prime_mux = R_mux/Q_m; - - - // Initialize the matricies - printf("Cmux*R_prime=%d*%d=%d, H_prime=%d, H_prime_total=%d\n",C_mux, R_prime_mux, C_mux*R_prime_mux, H_prime, H_prime_total); - for(i=0; i= 10) { - printf("10 at %d is %d\n",idx, q_bits[idx]); - //q_bits[idx] -= 10; - } else { - printf("%d->%d\n", j*C_mux*Q_m + i*Q_m + k,idx); - q_bits[idx] = g_bits[j*C_mux*Q_m + i*Q_m + k]; + uint32_t idx = 0; + for(uint32_t j=0; j= 10) { + q_bits[j*Q_m + i*rows*Q_m + k] -= 10; + } else { + q_bits[j*Q_m + i*rows*Q_m + k] = g_bits[idx]; + idx++; } - idx++; } } } - } int ulsch_encode(sch_t *q, uint8_t *data, uint8_t *g_bits, @@ -596,12 +431,11 @@ int ulsch_encode(sch_t *q, uint8_t *data, uint8_t *g_bits, { uci_data_t uci_data; bzero(&uci_data, sizeof(uci_data_t)); - return ulsch_uci_encode(q, data, uci_data, g_bits, NULL, NULL, harq_process, rv_idx, q_bits); + return ulsch_uci_encode(q, data, uci_data, g_bits, harq_process, rv_idx, q_bits); } int ulsch_uci_encode(sch_t *q, uint8_t *data, uci_data_t uci_data, uint8_t *g_bits, - uint8_t *g_bits_ack, uint8_t *g_bits_ri, harq_t *harq_process, uint32_t rv_idx, uint8_t *q_bits) { int ret; @@ -615,26 +449,15 @@ int ulsch_uci_encode(sch_t *q, uint8_t *data, uci_data_t uci_data, uint8_t *g_bi uint32_t nof_symbols = 12*harq_process->prb_alloc.slot[0].nof_prb*RE_X_RB; uint32_t nb_q = nof_symbols * Q_m; - // Encode ACK - if (uci_data.uci_ack_len > 0) { - float beta = uci_data.beta_ack; - if (harq_process->mcs.tbs == 0) { - beta /= uci_data.beta_cqi; - } - ret = uci_encode_ri_ack(uci_data.uci_ack, uci_data.uci_cqi_len, beta, harq_process, g_bits_ack); - if (ret < 0) { - return ret; - } - Q_prime_ack = (uint32_t) ret; - } - + bzero(q_bits, sizeof(uint8_t) * nb_q); + // Encode RI if (uci_data.uci_ri_len > 0) { float beta = uci_data.beta_ri; if (harq_process->mcs.tbs == 0) { beta /= uci_data.beta_cqi; } - ret = uci_encode_ri_ack(uci_data.uci_ri, uci_data.uci_cqi_len, beta, harq_process, g_bits_ri); + ret = uci_encode_ri(uci_data.uci_ri, uci_data.uci_cqi_len, beta, harq_process, nb_q/Q_m, q_bits); if (ret < 0) { return ret; } @@ -643,6 +466,7 @@ int ulsch_uci_encode(sch_t *q, uint8_t *data, uci_data_t uci_data, uint8_t *g_bi // Encode CQI if (uci_data.uci_cqi_len > 0) { + ret = uci_encode_cqi(&q->uci_cqi, uci_data.uci_cqi, uci_data.uci_cqi_len, uci_data.beta_cqi, Q_prime_ri, harq_process, g_bits); if (ret < 0) { @@ -652,8 +476,7 @@ int ulsch_uci_encode(sch_t *q, uint8_t *data, uci_data_t uci_data, uint8_t *g_bi } e_offset += Q_prime_cqi*Q_m; - - printf("Q_prime_ack=%d, Q_prime_cqi=%d, Q_prime_ri=%d\n",Q_prime_ack, Q_prime_cqi, Q_prime_ri); + // Encode UL-SCH if (harq_process->mcs.tbs > 0) { uint32_t G = nb_q/Q_m - Q_prime_ri - Q_prime_cqi; @@ -663,12 +486,24 @@ int ulsch_uci_encode(sch_t *q, uint8_t *data, uci_data_t uci_data, uint8_t *g_bi return ret; } } - - // Multiplexing and Interleaving - ulsch_interleave(g_bits, nb_q/Q_m-Q_prime_ri, - g_bits_ack, Q_prime_ack, - g_bits_ri, Q_prime_ri, - Q_m, q_bits); + + // Interleave UL-SCH (and RI and CQI) + ulsch_interleave(g_bits, Q_m, nb_q/Q_m, harq_process->N_symb_ul, q_bits); + + // Encode (and interleave) ACK + if (uci_data.uci_ack_len > 0) { + float beta = uci_data.beta_ack; + if (harq_process->mcs.tbs == 0) { + beta /= uci_data.beta_cqi; + } + ret = uci_encode_ack(uci_data.uci_ack, uci_data.uci_cqi_len, beta, harq_process, nb_q/Q_m, q_bits); + if (ret < 0) { + return ret; + } + Q_prime_ack = (uint32_t) ret; + } + + INFO("Q_prime_ack=%d, Q_prime_cqi=%d, Q_prime_ri=%d\n",Q_prime_ack, Q_prime_cqi, Q_prime_ri); diff --git a/lte/phy/lib/phch/src/uci.c b/lte/phy/lib/phch/src/uci.c index 34778e127..750cd9543 100644 --- a/lte/phy/lib/phch/src/uci.c +++ b/lte/phy/lib/phch/src/uci.c @@ -195,6 +195,55 @@ int uci_encode_cqi(uci_cqi_t *q, uint8_t *cqi_data, uint32_t cqi_len, float beta } } +/* Inserts UCI-ACK bits into the correct positions in the g buffer before interleaving */ +static int uci_ulsch_interleave_ack(uint8_t ack_coded_bits[6], uint32_t ack_q_bit_idx, + uint32_t Q_m, uint32_t H_prime_total, uint32_t N_pusch_symbs, lte_cp_t cp, + uint8_t *q_bits) { + + const uint32_t ack_column_set_norm[4] = {2, 3, 8, 9}; + const uint32_t ack_column_set_ext[4] = {1, 2, 6, 7}; + + if (H_prime_total/N_pusch_symbs > 1+ack_q_bit_idx/4) { + uint32_t row = H_prime_total/N_pusch_symbs-1-ack_q_bit_idx/4; + uint32_t colidx = (3*ack_q_bit_idx)%4; + uint32_t col = CP_ISNORM(cp)?ack_column_set_norm[colidx]:ack_column_set_ext[colidx]; + for(uint32_t k=0; k 1+ri_q_bit_idx/4) { + uint32_t row = H_prime_total/N_pusch_symbs-1-ri_q_bit_idx/4; + uint32_t colidx = (3*ri_q_bit_idx)%4; + uint32_t col = CP_ISNORM(cp)?ri_column_set_norm[colidx]:ri_column_set_ext[colidx]; + printf("r=%d-%d\n",H_prime_total/N_pusch_symbs,1+ri_q_bit_idx/4); + for(uint32_t k=0; kprb_alloc.slot[0].nof_prb * RE_X_RB; @@ -219,23 +268,46 @@ static uint32_t Q_prime_ri_ack(uint32_t O, uint32_t O_cqi, float beta, harq_t *h return Q_prime; } -/* Encode UCI RI and HARQ bits as described in 5.2.2.6 of 36.212 - * Currently only supporting 1-bit RI or 1-bit HARQ - */ -int uci_encode_ri_ack(uint8_t data, uint32_t O_cqi, float beta, harq_t *harq_process, uint8_t *q_bits) -{ - uint32_t Q_m = lte_mod_bits_x_symbol(harq_process->mcs.mod); - - q_bits[0] = data; - q_bits[1] = 2; +static void encode_ri_ack(uint8_t data, uint8_t q_encoded_bits[6], uint8_t Q_m) { + q_encoded_bits[0] = data; + q_encoded_bits[1] = 2; for (uint32_t i=2;imcs.mod); + uint32_t Qprime = Q_prime_ri_ack(1, O_cqi, beta, harq_process); + uint8_t q_encoded_bits[6]; + + encode_ri_ack(data, q_encoded_bits, Q_m); + + for (uint32_t i=0;iN_symb_ul, harq_process->cell.cp, q_bits); + } + + return (int) Qprime; +} + + +/* Encode UCI RI bits as described in 5.2.2.6 of 36.212 + * Currently only supporting 1-bit RI + */ +int uci_encode_ri(uint8_t data, uint32_t O_cqi, float beta, harq_t *harq_process, uint32_t H_prime_total, uint8_t *q_bits) +{ + uint32_t Q_m = lte_mod_bits_x_symbol(harq_process->mcs.mod); + uint32_t Qprime = Q_prime_ri_ack(1, O_cqi, beta, harq_process); + uint8_t q_encoded_bits[6]; + + encode_ri_ack(data, q_encoded_bits, Q_m); + + for (uint32_t i=0;iN_symb_ul, harq_process->cell.cp, q_bits); } return (int) Qprime; diff --git a/lte/phy/lib/phch/test/pusch_test.c b/lte/phy/lib/phch/test/pusch_test.c index 06e4ffe53..87231ab6c 100644 --- a/lte/phy/lib/phch/test/pusch_test.c +++ b/lte/phy/lib/phch/test/pusch_test.c @@ -201,8 +201,9 @@ int main(int argc, char **argv) { uci_data.uci_cqi = tmp; uci_data.uci_cqi_len = 0; uci_data.uci_ri_len = 1; - uci_data.uci_ack_len = 0; uci_data.uci_ri = 1; + uci_data.uci_ack_len = 1; + uci_data.uci_ack = 1; uint32_t nof_symbols = 12*harq_process.prb_alloc.slot[0].nof_prb*RE_X_RB; uint32_t nof_bits_e = nof_symbols * lte_mod_bits_x_symbol(harq_process.mcs.mod); @@ -210,8 +211,7 @@ int main(int argc, char **argv) { bzero(pusch.pusch_q, nof_bits_e*sizeof(uint8_t)); - if (ulsch_uci_encode(&pusch.dl_sch, data, uci_data, pusch.pusch_g, - pusch.pusch_g_ack, pusch.pusch_g_ri, &harq_process, rv, pusch.pusch_q)) + if (ulsch_uci_encode(&pusch.dl_sch, data, uci_data, pusch.pusch_g, &harq_process, rv, pusch.pusch_q)) { fprintf(stderr, "Error encoding TB\n"); exit(-1); diff --git a/lte/phy/lib/phch/test/ulsch_encode_test_mex.c b/lte/phy/lib/phch/test/ulsch_encode_test_mex.c index 472472ead..8507f672d 100644 --- a/lte/phy/lib/phch/test/ulsch_encode_test_mex.c +++ b/lte/phy/lib/phch/test/ulsch_encode_test_mex.c @@ -153,8 +153,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) uint32_t nof_symbols = 12*harq_process.prb_alloc.slot[0].nof_prb*RE_X_RB; uint32_t nof_q_bits = nof_symbols * lte_mod_bits_x_symbol(harq_process.mcs.mod); - - printf("alloc for %d bits\n", nof_q_bits); uint8_t *q_bits = vec_malloc(nof_q_bits * sizeof(uint8_t)); if (!q_bits) { @@ -164,17 +162,8 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) if (!g_bits) { return; } - uint8_t *g_bits_ack = vec_malloc(nof_q_bits * sizeof(uint8_t)); - if (!g_bits_ack) { - return; - } - uint8_t *g_bits_ri = vec_malloc(nof_q_bits * sizeof(uint8_t)); - if (!g_bits_ri) { - return; - } - if (ulsch_uci_encode(&ulsch, trblkin, uci_data, g_bits, - g_bits_ack, g_bits_ri, &harq_process, rv, q_bits)) + if (ulsch_uci_encode(&ulsch, trblkin, uci_data, g_bits, &harq_process, rv, q_bits)) { mexErrMsgTxt("Error encoding TB\n"); return; @@ -188,8 +177,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) free(trblkin); free(g_bits); - free(g_bits_ack); - free(g_bits_ri); if (uci_data.uci_cqi_len > 0) { free(uci_data.uci_cqi); diff --git a/matlab/tests/ulsch_test.m b/matlab/tests/ulsch_test.m index 527bd68f7..e1aa28c83 100644 --- a/matlab/tests/ulsch_test.m +++ b/matlab/tests/ulsch_test.m @@ -1,23 +1,23 @@ ueConfig=struct('NCellID',1,'CyclicPrefixUL','Normal','NTxAnts',1); -puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',0,'Modulation','QPSK','RV',0,'Shortened',0); +puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',(0:1)','Modulation','16QAM','RV',0,'Shortened',0); addpath('../../debug/lte/phy/lib/phch/test') -TBs=100; +TBs=200; error=zeros(size(TBs)); for i=1:length(error) - %trblkin=randi(2,TBs(i),1)-1; - trblkin=ones(TBs(i),1); + trblkin=randi(2,TBs(i),1)-1; + %trblkin=ones(TBs(i),1); %trblkin=[]; puschConfig.BetaCQI = 2.0; puschConfig.BetaRI = 2.0; puschConfig.BetaACK = 2.0; - [mat, info]=lteULSCH(ueConfig,puschConfig,trblkin,[],[1],[],[]); + [mat, info]=lteULSCH(ueConfig,puschConfig,trblkin,[ones(1,20)],[1],[1],[]); mat(mat==-2)=2; mat(mat==-1)=3; - [lib]=liblte_ulsch_encode(ueConfig,puschConfig,trblkin,[],[1],[]); + [lib]=liblte_ulsch_encode(ueConfig,puschConfig,trblkin,[ones(1,20)],[1],[1]); error(i)=sum(abs(double(mat)-double(lib))); if (length(TBs) == 1) disp(error(i)) @@ -27,7 +27,8 @@ end if (length(TBs) == 1) %disp(info) n=1:length(mat); - plot(abs(double(mat)-double(lib))) + %plot(abs(double(mat)-double(lib))) + plot(n,lib(n),n,mat(n)) else plot(error) disp(sum(error))