PUSCH working with matlab

master
ismagom 9 years ago
parent 0a3bd81a28
commit 728ccad448

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

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

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

@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <assert.h>
@ -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;i<nbits/8;i++) {
memcpy(&symbols[4*i], &q->symbol_table_qpsk[bits[i]], sizeof(qpsk_packed_t));
}
break;
case 4:
for (int i=0;i<nbits/8;i++) {
memcpy(&symbols[2*i], &q->symbol_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<nbits/24;i++) {
uint32_t in80 = bits[3*i+0];
uint32_t in81 = bits[3*i+1];
uint32_t in82 = bits[3*i+2];
uint8_t in0 = (in80&0xfc)>>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) {

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

@ -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;i<num_bits;i++) {
input[i] = rand()%2;
}
@ -160,6 +171,19 @@ int main(int argc, char **argv) {
/* modulate */
srslte_mod_modulate(&mod, input, symbols, num_bits);
srslte_vec_fprint_b(stdout, input, num_bits);
/* Test packed implementation */
srslte_bit_pack_vector(input, input_bytes, num_bits);
srslte_mod_modulate_bytes(&mod, input_bytes, symbols_bytes, num_bits);
for (int i=0;i<num_bits/mod.nbits_x_symbol;i++) {
if (symbols[i] != symbols_bytes[i]) {
printf("error in symbol %d\n", i);
exit(-1);
}
}
printf("Symbols OK\n");
/* demodulate */
if (soft_output) {
@ -185,8 +209,10 @@ int main(int argc, char **argv) {
free(llr);
free(symbols);
free(symbols_bytes);
free(output);
free(input);
free(input_bytes);
srslte_modem_table_free(&mod);
if (soft_output) {

@ -382,11 +382,6 @@ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q,
cfg->sf_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",

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

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

@ -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<ntrials;i++) {
if (srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer, data, uci_data, sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
exit(-1);
@ -234,10 +236,10 @@ int main(int argc, char **argv) {
goto quit;
} else {
printf("ENCODED OK in %d:%d (TBS: %d bits, TX: %.2f Mbps, Processing: %.2f Mbps)\n", (int) t[0].tv_sec,
(int) t[0].tv_usec/10,
(int) t[0].tv_usec/ntrials,
cfg.grant.mcs.tbs,
(float) cfg.grant.mcs.tbs/1000,
(float) cfg.grant.mcs.tbs/t[0].tv_usec*10);
(float) cfg.grant.mcs.tbs/t[0].tv_usec*ntrials);
}
ret = 0;

Loading…
Cancel
Save