From 728ccad44871d238c957710a1fd43ba2f72f776f Mon Sep 17 00:00:00 2001 From: ismagom Date: Fri, 18 Sep 2015 22:47:37 +0200 Subject: [PATCH] PUSCH working with matlab --- matlab/tests/pusch_test.m | 63 ++++++++++---------- srslte/include/srslte/modem/mod.h | 5 ++ srslte/include/srslte/modem/modem_table.h | 27 +++++++-- srslte/lib/modem/src/mod.c | 49 +++++++++++++++ srslte/lib/modem/src/modem_table.c | 42 ++++++++++++- srslte/lib/modem/test/modem_test.c | 32 +++++++++- srslte/lib/phch/src/pdsch.c | 10 ---- srslte/lib/phch/src/pusch.c | 21 ++++--- srslte/lib/phch/test/pusch_encode_test_mex.c | 8 +-- srslte/lib/phch/test/pusch_test.c | 10 ++-- 10 files changed, 197 insertions(+), 70 deletions(-) diff --git a/matlab/tests/pusch_test.m b/matlab/tests/pusch_test.m index 35c03499b..fdcd3a76d 100644 --- a/matlab/tests/pusch_test.m +++ b/matlab/tests/pusch_test.m @@ -1,44 +1,47 @@ -ueConfig=struct('NCellID',1,'NULRB',6,'RNTI',64,'CyclicPrefixUL','Normal','NTxAnts',1,'Shortened',0,'Hopping','Off','SeqGroup',0,'CyclicShift',0); -puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',0,'Shortened',0,'DynCyclicShift',0); +ueConfig=struct('NCellID',1,'NULRB',25,'CyclicPrefixUL','Normal','NTxAnts',1,'RNTI',64); +puschConfig=struct('NLayers',1,'OrthCover','Off','Shortened',0,'NBundled',0); -addpath('../../build/srslte/lib/phch/test') +addpath('/home/ismael/work/srsLTE/debug/srslte/lib/phch/test') -TBs=336; -cqilen=0; +cqilen=[0 20]; +mods={'QPSK','16QAM', '64QAM'}; rvs=0; -mods={'16QAM'}; -betas=5; -subf=0; - -for i=1:length(TBs) - for m=1:length(mods) - for r=1:length(rvs) - for bcqi=1:length(betas) +betas=[0 2.0 2.5 5.0, 20.0]; +for p=1:ueConfig.NULRB + for i=0:26 + for m=1:length(mods) + for r=1:length(rvs) for bri=1:length(betas) for back=1:length(betas) for c=1:length(cqilen) - for s=1:length(subf) - fprintf('Subf=%d, RV=%d\n', subf(s), rvs(r)); - trblkin=mod(0:TBs(i)-1,2); - ueConfig.NSubframe=subf(s); + for s=0 + ueConfig.NSubframe=s; + puschConfig.PRBSet=(0:p-1)'; + + TBs=lteTBS(length(puschConfig.PRBSet),i); + %TBs=256; + %trblkin=randi(2,TBs,1)-1; + trblkin=ones(1,TBs); + puschConfig.Modulation = mods{m}; puschConfig.RV = rvs(r); - puschConfig.BetaCQI = betas(bcqi); + puschConfig.BetaCQI = 5; puschConfig.BetaRI = betas(bri); puschConfig.BetaACK = betas(back); - if (betas(bri)>0) + if (betas(bri)>0) ri_bit=randi(2,1,1)-1; - else - ri_bit=[]; - end - if (betas(back)>0) - ack_bit=randi(2,1,1)-1; - else - ack_bit=[]; - end + else + ri_bit=[]; + end + if (betas(back)>0) + ack_bit=randi(2,1,1)-1; + else + ack_bit=[]; + end + - if (cqilen(c)>0 || TBs(i)>0) + if (cqilen(c)>0 || TBs>0) [enc, info]=lteULSCH(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit); cw_mat=ltePUSCH(ueConfig,puschConfig,enc); %[drs, infodrs]=ltePUSCHDRS(ueConfig,puschConfig); @@ -48,9 +51,7 @@ for i=1:length(TBs) subframe_mat(idx)=cw_mat; %subframe_mat(drs_idx)=drs; waveform = lteSCFDMAModulate(ueConfig,subframe_mat,0); - - cw_scram=lteULScramble(enc,0,1,64); -% + [waveform_lib, subframe_lib, cwlib, bits]=srslte_pusch_encode(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit); err=max(abs(waveform-waveform_lib)); if (err > 10^-5) diff --git a/srslte/include/srslte/modem/mod.h b/srslte/include/srslte/modem/mod.h index 612d76186..a7097a436 100644 --- a/srslte/include/srslte/modem/mod.h +++ b/srslte/include/srslte/modem/mod.h @@ -48,6 +48,11 @@ SRSLTE_API int srslte_mod_modulate(srslte_modem_table_t* table, cf_t* symbols, uint32_t nbits); +SRSLTE_API int srslte_mod_modulate_bytes(srslte_modem_table_t* q, + uint8_t *bits, + cf_t* symbols, + uint32_t nbits); + /* High-level API */ typedef struct SRSLTE_API { srslte_modem_table_t obj; diff --git a/srslte/include/srslte/modem/modem_table.h b/srslte/include/srslte/modem/modem_table.h index e72db2bc4..6f980bff0 100644 --- a/srslte/include/srslte/modem/modem_table.h +++ b/srslte/include/srslte/modem/modem_table.h @@ -46,16 +46,29 @@ typedef struct SRSLTE_API { uint32_t idx[2][6][32]; - uint32_t min_idx[2][64][6]; /* NEW: for each constellation point zone (2, 4, 16, 64 for BPSK, QPSK, 16QAM, 64QAM) the 2x(1, 2, 4, and 6 closest constellation points) for each bit, respectively. */ - uint32_t d_idx[64][7]; /* NEW: for each constellation point zone (2, 4, 16, 64 for BPSK, QPSK, 16QAM, 64QAM) the 2, 3, 5 and 7 indices to constellation points that need to be computed for any recevied symbol modulated as BPSK, QPSK, 16QAM, and 64QAM, respectively. */ + uint32_t min_idx[2][64][6]; /* NEW: for each constellation point zone (2, 4, 16, 64 for BPSK, QPSK, 16QAM, 64QAM) the 2x(1, 2, 4, and 6 closest constellation points) for each bit, respectively. */ + uint32_t d_idx[64][7]; /* NEW: for each constellation point zone (2, 4, 16, 64 for BPSK, QPSK, 16QAM, 64QAM) the 2, 3, 5 and 7 indices to constellation points that need to be computed for any recevied symbol modulated as BPSK, QPSK, 16QAM, and 64QAM, respectively. */ }srslte_soft_table_t; + +typedef struct { + cf_t symbol[4]; +} qpsk_packed_t; + +typedef struct { + cf_t symbol[2]; +} qam16_packed_t; + typedef struct SRSLTE_API { - cf_t* symbol_table; // bit-to-symbol mapping - srslte_soft_table_t soft_table; // symbol-to-bit mapping (used in soft demodulating) - uint32_t nsymbols; // number of modulation symbols - uint32_t nbits_x_symbol; // number of bits per symbol + cf_t* symbol_table; // bit-to-symbol mapping + srslte_soft_table_t soft_table; // symbol-to-bit mapping (used in soft demodulating) + uint32_t nsymbols; // number of modulation symbols + uint32_t nbits_x_symbol; // number of bits per symbol + + bool byte_tables_init; + qpsk_packed_t *symbol_table_qpsk; + qam16_packed_t *symbol_table_16qam; }srslte_modem_table_t; @@ -75,4 +88,6 @@ SRSLTE_API int srslte_modem_table_lte(srslte_modem_table_t* q, srslte_mod_t modulation, bool compute_soft_demod); +SRSLTE_API void srslte_modem_table_bytes(srslte_modem_table_t* q); + #endif // MODEM_TABLE_ diff --git a/srslte/lib/modem/src/mod.c b/srslte/lib/modem/src/mod.c index 97a30c4f5..bf3b0accd 100644 --- a/srslte/lib/modem/src/mod.c +++ b/srslte/lib/modem/src/mod.c @@ -27,6 +27,7 @@ #include +#include #include #include @@ -51,6 +52,54 @@ int srslte_mod_modulate(srslte_modem_table_t* q, uint8_t *bits, cf_t* symbols, u return j; } +/* Assumes packet bits as input */ +int srslte_mod_modulate_bytes(srslte_modem_table_t* q, uint8_t *bits, cf_t* symbols, uint32_t nbits) { + if (nbits%8) { + fprintf(stderr, "Warning: srslte_mod_modulate_bytes() accepts byte-aligned inputs only\n"); + } + if (!q->byte_tables_init) { + fprintf(stderr, "Error need to initiated modem tables for packeted bits before calling srslte_mod_modulate_bytes()\n"); + return -1; + } + switch(q->nbits_x_symbol) { + case 2: + for (int i=0;isymbol_table_qpsk[bits[i]], sizeof(qpsk_packed_t)); + } + break; + case 4: + for (int i=0;isymbol_table_16qam[bits[i]], sizeof(qam16_packed_t)); + } + break; + case 6: + if (nbits%24) { + fprintf(stderr, "Warning: for 64QAM srslte_mod_modulate_bytes() accepts 24-bit aligned inputs only\n"); + } + + for (int i=0;i>2; + uint8_t in1 = (in80&0x03)<<4 | ((in81&0xf0)>>4); + uint8_t in2 = (in81&0x0f)<<2 | ((in82&0xc0)>>6); + uint8_t in3 = in82&0x3f; + + symbols[i*4+0] = q->symbol_table[in0]; + symbols[i*4+1] = q->symbol_table[in1]; + symbols[i*4+2] = q->symbol_table[in2]; + symbols[i*4+3] = q->symbol_table[in3]; + } + break; + default: + fprintf(stderr, "srslte_mod_modulate_bytes() accepts QPSK/16QAM/64QAM modulations only\n"); + return -1; + } + return nbits/q->nbits_x_symbol; +} + /* High-Level API */ int mod_initialize(srslte_mod_hl* hl) { diff --git a/srslte/lib/modem/src/modem_table.c b/srslte/lib/modem/src/modem_table.c index 6761e728a..5f54cc48e 100644 --- a/srslte/lib/modem/src/modem_table.c +++ b/srslte/lib/modem/src/modem_table.c @@ -35,11 +35,12 @@ #include "srslte/common/phy_common.h" #include "srslte/modem/modem_table.h" +#include "srslte/utils/vector.h" #include "lte_tables.h" /** Internal functions */ static int table_create(srslte_modem_table_t* q) { - q->symbol_table = malloc(q->nsymbols*sizeof(cf_t)); + q->symbol_table = srslte_vec_malloc(q->nsymbols*sizeof(cf_t)); return q->symbol_table==NULL; } @@ -50,6 +51,12 @@ void srslte_modem_table_free(srslte_modem_table_t* q) { if (q->symbol_table) { free(q->symbol_table); } + if (q->symbol_table_qpsk) { + free(q->symbol_table_qpsk); + } + if (q->symbol_table_16qam) { + free(q->symbol_table_16qam); + } bzero(q, sizeof(srslte_modem_table_t)); } void srslte_modem_table_reset(srslte_modem_table_t* q) { @@ -72,6 +79,7 @@ int srslte_modem_table_set(srslte_modem_table_t* q, cf_t* table, srslte_soft_tab } int srslte_modem_table_lte(srslte_modem_table_t* q, srslte_mod_t modulation, bool compute_soft_demod) { + srslte_modem_table_init(q); switch(modulation) { case SRSLTE_MOD_BPSK: q->nbits_x_symbol = 1; @@ -108,3 +116,35 @@ int srslte_modem_table_lte(srslte_modem_table_t* q, srslte_mod_t modulation, boo } return SRSLTE_SUCCESS; } + +void srslte_modem_table_bytes(srslte_modem_table_t* q) { + uint8_t mask_qpsk[4] = {0xc0, 0x30, 0xc, 0x3}; + uint8_t mask_16qam[2] = {0xf0, 0xf}; + + switch(q->nbits_x_symbol) { + case 2: + q->symbol_table_qpsk = srslte_vec_malloc(sizeof(qpsk_packed_t)*256); + for (uint32_t i=0;i<256;i++) { + for (int j=0;j<4;j++) { + q->symbol_table_qpsk[i].symbol[j] = q->symbol_table[(i&mask_qpsk[j])>>(6-j*2)]; + } + } + q->byte_tables_init = true; + break; + case 4: + q->symbol_table_16qam = srslte_vec_malloc(sizeof(qam16_packed_t)*256); + for (uint32_t i=0;i<256;i++) { + for (int j=0;j<2;j++) { + q->symbol_table_16qam[i].symbol[j] = q->symbol_table[(i&mask_16qam[j])>>(4-j*4)]; + } + } + q->byte_tables_init = true; + break; + case 6: + q->byte_tables_init = true; + break; + } +} + + + diff --git a/srslte/lib/modem/test/modem_test.c b/srslte/lib/modem/test/modem_test.c index 624fcc93f..f349d2393 100644 --- a/srslte/lib/modem/test/modem_test.c +++ b/srslte/lib/modem/test/modem_test.c @@ -97,8 +97,8 @@ int main(int argc, char **argv) { srslte_modem_table_t mod; srslte_demod_hard_t demod_hard; srslte_demod_soft_t demod_soft; - uint8_t *input, *output; - cf_t *symbols; + uint8_t *input, *input_bytes, *output; + cf_t *symbols, *symbols_bytes; float *llr; // unsigned long strt, fin; @@ -112,6 +112,8 @@ int main(int argc, char **argv) { fprintf(stderr, "Error initializing modem table\n"); exit(-1); } + + srslte_modem_table_bytes(&mod); /* check that num_bits is multiple of num_bits x symbol */ if (num_bits % mod.nbits_x_symbol) { @@ -134,6 +136,11 @@ int main(int argc, char **argv) { perror("malloc"); exit(-1); } + input_bytes = malloc(sizeof(uint8_t) * num_bits/8); + if (!input_bytes) { + perror("malloc"); + exit(-1); + } output = malloc(sizeof(uint8_t) * num_bits); if (!output) { perror("malloc"); @@ -144,6 +151,11 @@ int main(int argc, char **argv) { perror("malloc"); exit(-1); } + symbols_bytes = malloc(sizeof(cf_t) * num_bits / mod.nbits_x_symbol); + if (!symbols_bytes) { + perror("malloc"); + exit(-1); + } llr = malloc(sizeof(float) * num_bits); if (!llr) { @@ -152,7 +164,6 @@ int main(int argc, char **argv) { } /* generate random data */ - srand(time(NULL)); for (i=0;isf_idx, rnti, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, cfg->nbits.nof_re, cfg->nbits.nof_bits, cfg->rv); - if (cfg->grant.mcs.tbs > cfg->nbits.nof_bits) { - fprintf(stderr, "Invalid code rate %d/%d=%.2f\n", cfg->grant.mcs.tbs, cfg->nbits.nof_bits, (float) cfg->grant.mcs.tbs / cfg->nbits.nof_bits); - return SRSLTE_ERROR_INVALID_INPUTS; - } - /* number of layers equals number of ports */ for (i = 0; i < q->cell.nof_ports; i++) { x[i] = q->x[i]; @@ -493,11 +488,6 @@ int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, return SRSLTE_ERROR_INVALID_INPUTS; } - if (cfg->grant.mcs.tbs > cfg->nbits.nof_bits) { - fprintf(stderr, "Invalid code rate %d/%d=%.2f\n", cfg->grant.mcs.tbs, cfg->nbits.nof_bits, (float) cfg->grant.mcs.tbs / cfg->nbits.nof_bits); - return SRSLTE_ERROR_INVALID_INPUTS; - } - if (cfg->nbits.nof_re > q->max_re) { fprintf(stderr, "Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n", diff --git a/srslte/lib/phch/src/pusch.c b/srslte/lib/phch/src/pusch.c index a2066a236..d6487a6ae 100644 --- a/srslte/lib/phch/src/pusch.c +++ b/srslte/lib/phch/src/pusch.c @@ -203,6 +203,7 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) { if (srslte_modem_table_lte(&q->mod[i], modulations[i], true)) { goto clean; } + srslte_modem_table_bytes(&q->mod[i]); } /* Precompute sequence for type2 frequency hopping */ @@ -501,6 +502,8 @@ int srslte_pusch_uci_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_s } } +uint8_t temp[1024*1024]; + /** Converts the PUSCH data bits to symbols mapped to the slot ready for transmission */ int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, @@ -512,10 +515,6 @@ int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srs if (q != NULL && cfg != NULL) { - if (cfg->grant.mcs.tbs > cfg->nbits.nof_bits) { - fprintf(stderr, "Invalid code rate %.2f\n", (float) cfg->grant.mcs.tbs / cfg->nbits.nof_bits); - return SRSLTE_ERROR_INVALID_INPUTS; - } if (cfg->nbits.nof_re > q->max_re) { fprintf(stderr, "Error too many RE per subframe (%d). PUSCH configured for %d RE (%d PRB)\n", @@ -538,31 +537,31 @@ int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srs if (srslte_sequence_pusch(&seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { return SRSLTE_ERROR; } - srslte_scrambling_b_offset(&seq, (uint8_t*) q->q, 0, cfg->nbits.nof_bits); + srslte_scrambling_bytes_offset(&seq, (uint8_t*) q->q, 0, cfg->nbits.nof_bits/8); srslte_sequence_free(&seq); } else { - srslte_scrambling_b_offset(&q->seq[cfg->sf_idx], (uint8_t*) q->q, 0, cfg->nbits.nof_bits); + srslte_scrambling_bytes_offset(&q->seq[cfg->sf_idx], (uint8_t*) q->q, 0, cfg->nbits.nof_bits/8); } // Correct UCI placeholder bits uint8_t *d = q->q; for (int i = 0; i < q->dl_sch.nof_ri_ack_bits; i++) { if (q->dl_sch.ack_ri_bits[i].type == UCI_BIT_PLACEHOLDER) { - d[q->dl_sch.ack_ri_bits[i].position/8] |= (1<<(q->dl_sch.ack_ri_bits[i].position%8)); + d[q->dl_sch.ack_ri_bits[i].position/8] |= (1<<(7-q->dl_sch.ack_ri_bits[i].position%8)); } else if (q->dl_sch.ack_ri_bits[i].type == UCI_BIT_REPETITION) { if (q->dl_sch.ack_ri_bits[i].position > 1) { uint32_t p=q->dl_sch.ack_ri_bits[i].position; - uint8_t bit = d[(p-1)/8] & (1<<((p-1)%8)); + uint8_t bit = d[(p-1)/8] & (1<<(7-(p-1)%8)); if (bit) { - d[p/8] |= 1<<(p%8); + d[p/8] |= 1<<(7-p%8); } else { - d[p/8] &= ~(1<<(p%8)); + d[p/8] &= ~(1<<(7-p%8)); } } } } - srslte_mod_modulate(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->q, q->d, cfg->nbits.nof_bits); + srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->q, q->d, cfg->nbits.nof_bits); srslte_dft_precoding(&q->dft_precoding, q->d, q->z, cfg->grant.L_prb, cfg->nbits.nof_symb); /* mapping to resource elements */ diff --git a/srslte/lib/phch/test/pusch_encode_test_mex.c b/srslte/lib/phch/test/pusch_encode_test_mex.c index a3e7b8a80..172c656c1 100644 --- a/srslte/lib/phch/test/pusch_encode_test_mex.c +++ b/srslte/lib/phch/test/pusch_encode_test_mex.c @@ -54,7 +54,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) help(); return; } - srslte_verbose = SRSLTE_VERBOSE_DEBUG; + srslte_verbose = SRSLTE_VERBOSE_NONE; srslte_cell_t cell; bzero(&cell, sizeof(srslte_cell_t)); @@ -193,12 +193,12 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) } else { cfg.uci_cfg.I_offset_ack = srslte_sch_find_Ioffset_ack(beta); } - mexPrintf("TRBL_len: %d, CQI_len: %d, ACK_len: %d (%d), RI_len: %d (%d)\n", grant.mcs.tbs, + mexPrintf("TRBL_len: %d, CQI_len: %2d, ACK_len: %d (%d), RI_len: %d (%d)\n", grant.mcs.tbs, uci_data.uci_cqi_len, uci_data.uci_ack_len, uci_data.uci_ack, uci_data.uci_ri_len, uci_data.uci_ri); - mexPrintf("I_cqi: %d, I_ri: %d, I_ack=%d\n", cfg.uci_cfg.I_offset_cqi, cfg.uci_cfg.I_offset_ri, cfg.uci_cfg.I_offset_ack); + mexPrintf("I_cqi: %2d, I_ri: %2d, I_ack=%2d\n", cfg.uci_cfg.I_offset_cqi, cfg.uci_cfg.I_offset_ri, cfg.uci_cfg.I_offset_ack); - mexPrintf("NofRE: %d, NofBits: %d, TBS: %d, N_srs=%d\n", cfg.nbits.nof_re, cfg.nbits.nof_bits, grant.mcs.tbs, N_srs); + mexPrintf("NofRE: %3d, NofBits: %3d, TBS: %3d, N_srs=%d\n", cfg.nbits.nof_re, cfg.nbits.nof_bits, grant.mcs.tbs, N_srs); int r = srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer, trblkin, uci_data, sf_symbols); if (r < 0) { mexErrMsgTxt("Error encoding PUSCH\n"); diff --git a/srslte/lib/phch/test/pusch_test.c b/srslte/lib/phch/test/pusch_test.c index a08ef8f9e..3b2eede43 100644 --- a/srslte/lib/phch/test/pusch_test.c +++ b/srslte/lib/phch/test/pusch_test.c @@ -167,7 +167,7 @@ int main(int argc, char **argv) { srslte_uci_data_t uci_data; bzero(&uci_data, sizeof(srslte_uci_data_t)); - uci_data.uci_cqi_len = 20; + uci_data.uci_cqi_len = 0; uci_data.uci_ri_len = 0; uci_data.uci_ack_len = 0; @@ -206,9 +206,11 @@ int main(int argc, char **argv) { fprintf(stderr, "Error initiating soft buffer\n"); goto quit; } + + uint32_t ntrials = 100; gettimeofday(&t[1], NULL); - for (int i=0;i<10;i++) { + for (int i=0;i