added support for multiple rx antennas to pdsch. Working in matlab for 1/2 ports tx diversity

This commit is contained in:
Ismael Gomez 2017-02-07 19:04:15 +00:00
parent 462d222fd2
commit 0bd749aa29
6 changed files with 153 additions and 72 deletions

View File

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

View File

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

View File

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

View File

@ -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;rxant<nof_rx_antennas;rxant++) {
for (uint32_t port_id=0;port_id<q->cell.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;
}
}

View File

@ -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;j<q->nof_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;j<q->nof_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;j<q->nof_rx_antennas;j++) {
if (q->ce[i][j]) {
free(q->ce[i][j]);
}
}
}
for (int j=0;j<q->nof_rx_antennas;j++) {
if (q->symbols[j]) {
free(q->symbols[j]);
}
}
if (q->users) {
for (uint16_t u=0;u<SRSLTE_SIRNTI;u++) {
if (q->users[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;i<q->cell.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;j<q->nof_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()) {

View File

@ -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<cell.nof_ports;i++) {
ce[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_RXANT];
for (int j=0;j<SRSLTE_MAX_RXANT;j++) {
for (i=0;i<cell.nof_ports;i++) {
ce[i][j] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
}
}
uint8_t *data_bytes = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs.tbs/8);
if (!data_bytes) {
return;
}
srslte_sch_set_max_noi(&pdsch.dl_sch, max_iterations);
input_fft = NULL;
bool input_fft_allocated = false;
int r=-1;
for (int rvIdx=0;rvIdx<nof_retx && r != 0;rvIdx++) {
@ -218,11 +227,17 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexErrMsgTxt("Error reading input signal\n");
return;
}
if (insignal_len == SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)) {
input_fft = input_signal;
} else {
input_fft = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
srslte_ofdm_rx_sf(&ofdm_rx, input_signal, input_fft);
if (!(insignal_len % SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp))) {
for (int i=0;i<nof_antennas;i++) {
input_fft[i] = &input_signal[i*insignal_len/nof_antennas];
}
} else if (!(insignal_len % SRSLTE_SF_LEN_PRB(cell.nof_prb))) {
for (int i=0;i<nof_antennas;i++) {
input_fft[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
srslte_ofdm_rx_sf(&ofdm_rx, &input_signal[i*insignal_len/nof_antennas], input_fft[i]);
input_fft_allocated = true;
}
free(input_signal);
}
@ -230,16 +245,18 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
cf_t *cearray = NULL;
mexutils_read_cf(prhs[NOF_INPUTS], &cearray);
cf_t *cearray_ptr = cearray;
for (i=0;i<cell.nof_ports;i++) {
for (int j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
ce[i][j] = *cearray_ptr;
cearray_ptr++;
}
}
for (int k=0;k<SRSLTE_MAX_RXANT;k++) {
for (i=0;i<cell.nof_ports;i++) {
for (int j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
ce[i][k][j] = *cearray_ptr;
cearray_ptr++;
}
}
}
if (cearray)
free(cearray);
} else {
srslte_chest_dl_estimate(&chest, input_fft, ce, cfg.sf_idx);
srslte_chest_dl_estimate_multi(&chest, input_fft, ce, cfg.sf_idx, nof_antennas);
}
float noise_power;
@ -251,7 +268,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
noise_power = srslte_chest_dl_get_noise_estimate(&chest);
}
r = srslte_pdsch_decode(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, rnti, data_bytes);
r = srslte_pdsch_decode_multi(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, rnti, data_bytes);
}
uint8_t *data = malloc(grant.mcs.tbs);
@ -273,21 +290,41 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexutils_write_s(pdsch.e, &plhs[4], cfg.nbits.nof_bits, 1);
}
if (nlhs >= 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<nof_antennas;k++) {
for (i=0;i<cell.nof_ports;i++) {
for (int j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
cearray_ptr[n] = ce[i][k][j];
n++;
}
}
}
mexutils_write_cf(cearray_ptr, &plhs[5], len, 1);
if (cearray_ptr) {
free(cearray_ptr);
}
}
srslte_softbuffer_rx_free(&softbuffer);
srslte_chest_dl_free(&chest);
srslte_pdsch_free(&pdsch);
srslte_ofdm_rx_free(&ofdm_rx);
for (i=0;i<cell.nof_ports;i++) {
free(ce[i]);
for (int j=0;j<nof_antennas;j++) {
for (i=0;i<cell.nof_ports;i++) {
if (ce[i][j]) {
free(ce[i][j]);
}
}
if (input_fft_allocated) {
if (input_fft[j]) {
free(input_fft[j]);
}
}
}
free(data_bytes);
free(data);
if (input_fft) {
free(input_fft);
}
return;
}