diff --git a/matlab/tests/pdsch_equal.m b/matlab/tests/pdsch_equal.m index f58920f14..e5daaf5cb 100644 --- a/matlab/tests/pdsch_equal.m +++ b/matlab/tests/pdsch_equal.m @@ -8,10 +8,10 @@ recordedSignal=[]; Npackets = 1; -SNR_values = 56;%linspace(2,6,10); +SNR_values = 50;%linspace(8,11,5); %% Choose RMC -[waveform,rgrid,rmccFgOut] = lteRMCDLTool('R.5',[1;0;0;1]); +[waveform,rgrid,rmccFgOut] = lteRMCDLTool('R.12',[1;0;0;1]); waveform = sum(waveform,2); if ~isempty(recordedSignal) @@ -105,9 +105,6 @@ for snr_idx=1:length(SNR_values) subframe_rx); else dec2 = 1; - end - if (~dec2) - fprintf('Error in sf=%d\n',sf_idx); end decoded_srslte(snr_idx) = decoded_srslte(snr_idx)+dec2; end diff --git a/srslte/include/srslte/ch_estimation/chest_dl.h b/srslte/include/srslte/ch_estimation/chest_dl.h index 7d20ecb45..1d37b3aad 100644 --- a/srslte/include/srslte/ch_estimation/chest_dl.h +++ b/srslte/include/srslte/ch_estimation/chest_dl.h @@ -107,8 +107,9 @@ SRSLTE_API void srslte_chest_dl_set_noise_alg(srslte_chest_dl_t *q, SRSLTE_API int srslte_chest_dl_estimate_multi(srslte_chest_dl_t *q, cf_t *input[SRSLTE_MAX_RXANT], - cf_t *ce[SRSLTE_MAX_RXANT][SRSLTE_MAX_PORTS], - uint32_t sf_idx); + cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT], + uint32_t sf_idx, + uint32_t nof_rx_antennas); SRSLTE_API int srslte_chest_dl_estimate(srslte_chest_dl_t *q, cf_t *input, diff --git a/srslte/include/srslte/phch/pdsch.h b/srslte/include/srslte/phch/pdsch.h index 305402de5..dae5f2ec2 100644 --- a/srslte/include/srslte/phch/pdsch.h +++ b/srslte/include/srslte/phch/pdsch.h @@ -55,12 +55,14 @@ typedef struct { typedef struct SRSLTE_API { srslte_cell_t cell; + uint32_t nof_rx_antennas; + uint32_t max_re; /* buffers */ // void buffers are shared for tx and rx - cf_t *ce[SRSLTE_MAX_PORTS]; - cf_t *symbols[SRSLTE_MAX_PORTS]; + cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT]; + cf_t *symbols[SRSLTE_MAX_RXANT]; cf_t *x[SRSLTE_MAX_PORTS]; cf_t *d; void *e; @@ -78,6 +80,10 @@ typedef struct SRSLTE_API { SRSLTE_API int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell); +SRSLTE_API int srslte_pdsch_init_multi(srslte_pdsch_t *q, + srslte_cell_t cell, + uint32_t nof_rx_antennas); + SRSLTE_API void srslte_pdsch_free(srslte_pdsch_t *q); SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q, @@ -112,6 +118,15 @@ SRSLTE_API int srslte_pdsch_decode(srslte_pdsch_t *q, uint16_t rnti, uint8_t *data); +SRSLTE_API int srslte_pdsch_decode_multi(srslte_pdsch_t *q, + srslte_pdsch_cfg_t *cfg, + srslte_softbuffer_rx_t *softbuffer, + cf_t *sf_symbols[SRSLTE_MAX_RXANT], + cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT], + float noise_estimate, + uint16_t rnti, + uint8_t *data); + SRSLTE_API float srslte_pdsch_average_noi(srslte_pdsch_t *q); SRSLTE_API uint32_t srslte_pdsch_last_noi(srslte_pdsch_t *q); diff --git a/srslte/lib/ch_estimation/chest_dl.c b/srslte/lib/ch_estimation/chest_dl.c index 5a1da4736..47e169364 100644 --- a/srslte/lib/ch_estimation/chest_dl.c +++ b/srslte/lib/ch_estimation/chest_dl.c @@ -354,11 +354,12 @@ int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, u return 0; } -int srslte_chest_dl_estimate(srslte_chest_dl_t *q, cf_t *input[SRSLTE_MAX_RXANT], cf_t *ce[SRSLTE_MAX_RXANT][SRSLTE_MAX_PORTS], uint32_t sf_idx, uint32_t nof_rx_antennas) +int srslte_chest_dl_estimate_multi(srslte_chest_dl_t *q, cf_t *input[SRSLTE_MAX_RXANT], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT], uint32_t sf_idx, uint32_t nof_rx_antennas) { for (uint32_t rxant=0;rxantcell.nof_ports;port_id++) { - if (srslte_chest_dl_estimate_port(q, input[rxant], ce[rxant][port_id], sf_idx, port_id)) { + printf("rxant=%d, port=%d, input=0x%x, ce=0x%x\n", rxant, port_id, input[rxant], ce[port_id][rxant]); + if (srslte_chest_dl_estimate_port(q, input[rxant], ce[port_id][rxant], sf_idx, port_id)) { return SRSLTE_ERROR; } } diff --git a/srslte/lib/phch/pdsch.c b/srslte/lib/phch/pdsch.c index b4ae7621f..02f85c5d3 100644 --- a/srslte/lib/phch/pdsch.c +++ b/srslte/lib/phch/pdsch.c @@ -202,13 +202,20 @@ int srslte_pdsch_get(srslte_pdsch_t *q, cf_t *sf_symbols, cf_t *symbols, return srslte_pdsch_cp(q, sf_symbols, symbols, grant, lstart, subframe, false); } +int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell) +{ + return srslte_pdsch_init_multi(q, cell, 1); +} + /** Initializes the PDCCH transmitter and receiver */ -int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell) { +int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_rx_antennas) +{ int ret = SRSLTE_ERROR_INVALID_INPUTS; int i; - if (q != NULL && - srslte_cell_isvalid(&cell)) + if (q != NULL && + srslte_cell_isvalid(&cell) && + nof_rx_antennas <= SRSLTE_MAX_RXANT) { bzero(q, sizeof(srslte_pdsch_t)); @@ -216,7 +223,8 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell) { q->cell = cell; q->max_re = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp); - + q->nof_rx_antennas = nof_rx_antennas; + INFO("Init PDSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports, q->cell.nof_prb, q->max_re); @@ -241,19 +249,23 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell) { } for (i = 0; i < q->cell.nof_ports; i++) { - q->ce[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re); - if (!q->ce[i]) { - goto clean; - } q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re); if (!q->x[i]) { goto clean; } - q->symbols[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re); - if (!q->symbols[i]) { - goto clean; + for (int j=0;jnof_rx_antennas;j++) { + q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re); + if (!q->ce[i][j]) { + goto clean; + } } } + for (int j=0;jnof_rx_antennas;j++) { + q->symbols[j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re); + if (!q->symbols[j]) { + goto clean; + } + } q->users = calloc(sizeof(srslte_pdsch_user_t*), 1+SRSLTE_SIRNTI); if (!q->users) { @@ -280,17 +292,20 @@ void srslte_pdsch_free(srslte_pdsch_t *q) { free(q->d); } for (i = 0; i < q->cell.nof_ports; i++) { - if (q->ce[i]) { - free(q->ce[i]); - } if (q->x[i]) { free(q->x[i]); } - if (q->symbols[i]) { - free(q->symbols[i]); + for (int j=0;jnof_rx_antennas;j++) { + if (q->ce[i][j]) { + free(q->ce[i][j]); + } } } - + for (int j=0;jnof_rx_antennas;j++) { + if (q->symbols[j]) { + free(q->symbols[j]); + } + } if (q->users) { for (uint16_t u=0;uusers[u]) { @@ -363,13 +378,28 @@ void srslte_pdsch_free_rnti(srslte_pdsch_t* q, uint16_t rnti) } } -/** Decodes the PDSCH from the received symbols - */ int srslte_pdsch_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate, uint16_t rnti, uint8_t *data) { + cf_t *_sf_symbols[SRSLTE_MAX_RXANT]; + cf_t *_ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT]; + + _sf_symbols[0] = sf_symbols; + for (int i=0;icell.nof_ports;i++) { + _ce[i][0] = ce[i]; + } + return srslte_pdsch_decode_multi(q, cfg, softbuffer, _sf_symbols, _ce, noise_estimate, rnti, data); +} + +/** Decodes the PDSCH from the received symbols + */ +int srslte_pdsch_decode_multi(srslte_pdsch_t *q, + srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, + cf_t *sf_symbols[SRSLTE_MAX_RXANT], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT], float noise_estimate, + uint16_t rnti, uint8_t *data) +{ /* Set pointers for layermapping & precoding */ uint32_t i, n; @@ -391,31 +421,31 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, } memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports)); - /* extract symbols */ - n = srslte_pdsch_get(q, sf_symbols, q->symbols[0], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); - if (n != cfg->nbits.nof_re) { - fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n); - return SRSLTE_ERROR; - } - - /* extract channel estimates */ - for (i = 0; i < q->cell.nof_ports; i++) { - n = srslte_pdsch_get(q, ce[i], q->ce[i], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); + for (int j=0;jnof_rx_antennas;j++) { + /* extract symbols */ + n = srslte_pdsch_get(q, sf_symbols[j], q->symbols[j], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); if (n != cfg->nbits.nof_re) { fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n); return SRSLTE_ERROR; } + + /* extract channel estimates */ + for (i = 0; i < q->cell.nof_ports; i++) { + n = srslte_pdsch_get(q, ce[i][j], q->ce[i][j], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); + if (n != cfg->nbits.nof_re) { + fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n); + return SRSLTE_ERROR; + } + } } /* TODO: only diversity is supported */ if (q->cell.nof_ports == 1) { /* no need for layer demapping */ - srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, cfg->nbits.nof_re, noise_estimate); + srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, cfg->nbits.nof_re, noise_estimate); } else { - srslte_predecoding_diversity(q->symbols[0], q->ce, x, q->cell.nof_ports, - cfg->nbits.nof_re); - srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, - cfg->nbits.nof_re / q->cell.nof_ports); + srslte_predecoding_diversity_multi(q->symbols, q->ce, x, q->cell.nof_ports, q->nof_rx_antennas, cfg->nbits.nof_re); + srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, cfg->nbits.nof_re / q->cell.nof_ports); } if (SRSLTE_VERBOSE_ISDEBUG()) { diff --git a/srslte/lib/phch/test/pdsch_test_mex.c b/srslte/lib/phch/test/pdsch_test_mex.c index 45bd1ae09..869a4829c 100644 --- a/srslte/lib/phch/test/pdsch_test_mex.c +++ b/srslte/lib/phch/test/pdsch_test_mex.c @@ -55,7 +55,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) srslte_ofdm_t ofdm_rx; srslte_pdsch_t pdsch; srslte_chest_dl_t chest; - cf_t *input_fft; + cf_t *input_fft[SRSLTE_MAX_RXANT]; srslte_pdsch_cfg_t cfg; srslte_softbuffer_rx_t softbuffer; uint32_t rnti32; @@ -92,8 +92,16 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) fprintf(stderr, "Error initializing FFT\n"); return; } - - if (srslte_pdsch_init(&pdsch, cell)) { + + + const size_t ndims = mxGetNumberOfDimensions(INPUT); + uint32_t nof_antennas = 1; + if (ndims >= 3) { + const mwSize *dims = mxGetDimensions(INPUT); + nof_antennas = dims[2]; + } + + if (srslte_pdsch_init_multi(&pdsch, cell, nof_antennas)) { mexErrMsgTxt("Error initiating PDSCH\n"); return; } @@ -188,18 +196,19 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) nof_retx = mexutils_getLength(INPUT); } - cf_t *ce[SRSLTE_MAX_PORTS]; - for (i=0;i= 6) { - mexutils_write_cf(ce[0], &plhs[5], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), 1); + uint32_t len = nof_antennas*cell.nof_ports*SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp); + cf_t *cearray_ptr = srslte_vec_malloc(len*sizeof(cf_t)); + int n=0; + for (int k=0;k