/** Decodes the PDSCH from the received symbols */ int srslte_pdsch_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffers[SRSLTE_MAX_CODEWORDS], cf_t *sf_symbols[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], float noise_estimate, uint16_t rnti, uint8_t *data[SRSLTE_MAX_CODEWORDS], bool acks[SRSLTE_MAX_CODEWORDS]) { /* Set pointers for layermapping & precoding */ uint32_t i; cf_t *x[SRSLTE_MAX_LAYERS]; if (q != NULL && sf_symbols != NULL && data != NULL && cfg != NULL) { uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant); INFO("Decoding PDSCH SF: %d, RNTI: 0x%x, NofSymbols: %d, C_prb=%d, mimo_type=%s, nof_layers=%d, nof_tb=%d\n", cfg->sf_idx, rnti, cfg->nbits[0].nof_re, cfg->grant.nof_prb, srslte_mod_string(cfg->grant.mcs->mod), cfg->nof_layers, nof_tb); // Extract Symbols and Channel Estimates for (int j=0;j<q->nof_rx_antennas;j++) { int n = srslte_pdsch_get(q, sf_symbols[j], q->symbols[j], &cfg->grant, cfg->nbits[0].lstart, cfg->sf_idx); if (n != cfg->nbits[0].nof_re) { fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits[0].nof_re, n); return SRSLTE_ERROR; } 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[0].lstart, cfg->sf_idx); if (n != cfg->nbits[0].nof_re) { fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits[0].nof_re, n); return SRSLTE_ERROR; } } } // Prepare layers int nof_symbols [SRSLTE_MAX_CODEWORDS]; nof_symbols[0] = cfg->nbits[0].nof_re * nof_tb / cfg->nof_layers; nof_symbols[1] = cfg->nbits[1].nof_re * nof_tb / cfg->nof_layers; if (cfg->nof_layers == nof_tb) { /* Skip layer demap */ for (i = 0; i < cfg->nof_layers; i++) { x[i] = q->d[i]; } } else { /* number of layers equals number of ports */ for (i = 0; i < cfg->nof_layers; i++) { x[i] = q->x[i]; } memset(&x[cfg->nof_layers], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - cfg->nof_layers)); } float pdsch_scaling = 1.0f; if (q->rho_a != 0.0f) { pdsch_scaling = q->rho_a; } // Pre-decoder if (srslte_predecoding_type(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers, cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, pdsch_scaling, noise_estimate)<0) { DEBUG("Error predecoding\n"); return SRSLTE_ERROR; } // Layer demapping only if necessary if (cfg->nof_layers != nof_tb) { srslte_layerdemap_type(x, q->d, cfg->nof_layers, nof_tb, nof_symbols[0], nof_symbols, cfg->mimo_type); } /* Codeword decoding: Implementation of 3GPP 36.212 Table 5.3.3.1.5-1 and Table 5.3.3.1.5-2 */ uint32_t cw_idx = (nof_tb == SRSLTE_MAX_TB && cfg->tb_cw_swap) ? 1 : 0; for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) { /* Decode only if transport block is enabled and the default ACK is not true */ if (cfg->grant.tb_en[tb_idx]) { if (!acks[tb_idx]) { int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb_idx], rnti, data[tb_idx], cw_idx, tb_idx, &acks[tb_idx]); /* Check if there has been any execution error */ if (ret) { return ret; } } cw_idx = (cw_idx + 1) % SRSLTE_MAX_CODEWORDS; } } pdsch_decode_debug(q, cfg, sf_symbols, ce); return SRSLTE_SUCCESS; } else { return SRSLTE_ERROR_INVALID_INPUTS; } }
int main(int argc, char **argv) { int i, j; float mse; cf_t *x[SRSLTE_MAX_LAYERS], *r[SRSLTE_MAX_PORTS], *y[SRSLTE_MAX_PORTS], *h[SRSLTE_MAX_PORTS], *xr[SRSLTE_MAX_LAYERS]; srslte_mimo_type_t type; srslte_precoding_t precoding; parse_args(argc, argv); if (nof_ports > SRSLTE_MAX_PORTS || nof_layers > SRSLTE_MAX_LAYERS) { fprintf(stderr, "Invalid number of layers or ports\n"); exit(-1); } if (srslte_str2mimotype(mimo_type_name, &type)) { fprintf(stderr, "Invalid MIMO type %s\n", mimo_type_name); exit(-1); } for (i = 0; i < nof_layers; i++) { x[i] = srslte_vec_malloc(sizeof(cf_t) * nof_symbols); if (!x[i]) { perror("srslte_vec_malloc"); exit(-1); } xr[i] = srslte_vec_malloc(sizeof(cf_t) * nof_symbols); if (!xr[i]) { perror("srslte_vec_malloc"); exit(-1); } } for (i = 0; i < nof_ports; i++) { y[i] = srslte_vec_malloc(sizeof(cf_t) * nof_symbols * nof_layers); // TODO: The number of symbols per port is different in spatial multiplexing. if (!y[i]) { perror("srslte_vec_malloc"); exit(-1); } h[i] = srslte_vec_malloc(sizeof(cf_t) * nof_symbols * nof_layers); if (!h[i]) { perror("srslte_vec_malloc"); exit(-1); } } /* only 1 receiver antenna supported now */ r[0] = srslte_vec_malloc(sizeof(cf_t) * nof_symbols * nof_layers); if (!r[0]) { perror("srslte_vec_malloc"); exit(-1); } /* generate random data */ for (i = 0; i < nof_layers; i++) { for (j = 0; j < nof_symbols; j++) { x[i][j] = (2*(rand()%2)-1+(2*(rand()%2)-1)*_Complex_I)/sqrt(2); } } if (srslte_precoding_init(&precoding, nof_symbols * nof_layers)) { fprintf(stderr, "Error initializing precoding\n"); exit(-1); } /* precoding */ if (srslte_precoding_type(&precoding, x, y, nof_layers, nof_ports, nof_symbols, type) < 0) { fprintf(stderr, "Error layer mapper encoder\n"); exit(-1); } /* generate channel */ for (i = 0; i < nof_ports; i++) { for (j = 0; j < nof_symbols; j++) { h[i][nof_layers*j] = (float) rand()/RAND_MAX+((float) rand()/RAND_MAX)*_Complex_I; // assume the channel is time-invariant in nlayer consecutive symbols for (int k=0;k<nof_layers;k++) { h[i][nof_layers*j+k] = h[i][nof_layers*j]; } } } /* pass signal through channel (we are in the frequency domain so it's a multiplication) */ /* there's only one receiver antenna, signals from different transmitter * ports are simply combined at the receiver */ for (j = 0; j < nof_symbols * nof_layers; j++) { r[0][j] = 0; for (i = 0; i < nof_ports; i++) { r[0][j] += y[i][j] * h[i][j]; } } /* predecoding / equalization */ struct timeval t[3]; gettimeofday(&t[1], NULL); if (srslte_predecoding_type(&precoding, r[0], h, xr, nof_ports, nof_layers, nof_symbols * nof_layers, type, 0) < 0) { fprintf(stderr, "Error layer mapper encoder\n"); exit(-1); } gettimeofday(&t[2], NULL); get_time_interval(t); printf("Execution Time: %d us\n", t[0].tv_usec); /* check errors */ mse = 0; for (i = 0; i < nof_layers; i++) { for (j = 0; j < nof_symbols; j++) { mse += cabsf(xr[i][j] - x[i][j]); } } printf("MSE: %f\n", mse/ nof_layers / nof_symbols ); if (mse / nof_layers / nof_symbols > MSE_THRESHOLD) { exit(-1); } for (i = 0; i < nof_layers; i++) { free(x[i]); free(xr[i]); } for (i = 0; i < nof_ports; i++) { free(y[i]); free(h[i]); } free(r[0]); srslte_precoding_free(&precoding); printf("Ok\n"); exit(0); }
int main(int argc, char **argv) { int i, j, k, nof_errors = 0, ret = SRSLTE_SUCCESS; float mse; cf_t *x[SRSLTE_MAX_LAYERS], *r[SRSLTE_MAX_PORTS], *y[SRSLTE_MAX_PORTS], *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], *xr[SRSLTE_MAX_LAYERS]; srslte_mimo_type_t type; parse_args(argc, argv); /* Check input ranges */ if (nof_tx_ports > SRSLTE_MAX_PORTS || nof_rx_ports > SRSLTE_MAX_PORTS || nof_layers > SRSLTE_MAX_LAYERS) { fprintf(stderr, "Invalid number of layers or ports\n"); exit(-1); } /* Parse MIMO Type */ if (srslte_str2mimotype(mimo_type_name, &type)) { fprintf(stderr, "Invalid MIMO type %s\n", mimo_type_name); exit(-1); } /* Check scenario conditions are OK */ switch (type) { case SRSLTE_MIMO_TYPE_TX_DIVERSITY: nof_re = nof_layers*nof_symbols; break; case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX: nof_re = nof_symbols; break; case SRSLTE_MIMO_TYPE_CDD: nof_re = nof_symbols*nof_tx_ports/nof_layers; if (nof_rx_ports != 2 || nof_tx_ports != 2) { fprintf(stderr, "CDD nof_tx_ports=%d nof_rx_ports=%d is not currently supported\n", nof_tx_ports, nof_rx_ports); exit(-1); } break; default: nof_re = nof_symbols*nof_layers; } /* Allocate x and xr (received symbols) in memory for each layer */ for (i = 0; i < nof_layers; i++) { /* Source data */ x[i] = srslte_vec_malloc(sizeof(cf_t) * nof_symbols); if (!x[i]) { perror("srslte_vec_malloc"); exit(-1); } /* Sink data */ xr[i] = srslte_vec_malloc(sizeof(cf_t) * nof_symbols); if (!xr[i]) { perror("srslte_vec_malloc"); exit(-1); } } /* Allocate y in memory for tx each port */ for (i = 0; i < nof_tx_ports; i++) { y[i] = srslte_vec_malloc(sizeof(cf_t) * nof_re); if (!y[i]) { perror("srslte_vec_malloc"); exit(-1); } } /* Allocate h in memory for each cross channel and layer */ for (i = 0; i < nof_tx_ports; i++) { for (j = 0; j < nof_rx_ports; j++) { h[i][j] = srslte_vec_malloc(sizeof(cf_t) * nof_re); if (!h[i][j]) { perror("srslte_vec_malloc"); exit(-1); } } } /* Allocate r */ for (i = 0; i < nof_rx_ports; i++) { r[i] = srslte_vec_malloc(sizeof(cf_t) * nof_re); if (!r[i]) { perror("srslte_vec_malloc"); exit(-1); } } /* Generate source random data */ for (i = 0; i < nof_layers; i++) { for (j = 0; j < nof_symbols; j++) { x[i][j] = (2 * (rand() % 2) - 1 + (2 * (rand() % 2) - 1) * _Complex_I) / sqrt(2); } } /* Execute Precoding (Tx) */ if (srslte_precoding_type(x, y, nof_layers, nof_tx_ports, codebook_idx, nof_symbols, scaling, type) < 0) { fprintf(stderr, "Error layer mapper encoder\n"); exit(-1); } /* generate channel */ populate_channel(type, h); /* pass signal through channel (we are in the frequency domain so it's a multiplication) */ for (i = 0; i < nof_rx_ports; i++) { for (k = 0; k < nof_re; k++) { r[i][k] = (cf_t) (0.0 + 0.0 * _Complex_I); for (j = 0; j < nof_tx_ports; j++) { r[i][k] += y[j][k] * h[j][i][k]; } } } awgn(r, (uint32_t) nof_re, snr_db); /* If CDD or Spatial muliplex choose decoder */ if (strncmp(decoder_type_name, "zf", 16) == 0) { srslte_predecoding_set_mimo_decoder(SRSLTE_MIMO_DECODER_ZF); } else if (strncmp(decoder_type_name, "mmse", 16) == 0) { srslte_predecoding_set_mimo_decoder(SRSLTE_MIMO_DECODER_MMSE); } else { ret = SRSLTE_ERROR; goto quit; } /* predecoding / equalization */ struct timeval t[3]; gettimeofday(&t[1], NULL); srslte_predecoding_type(r, h, xr, NULL, nof_rx_ports, nof_tx_ports, nof_layers, codebook_idx, nof_re, type, scaling, powf(10, -snr_db / 10)); gettimeofday(&t[2], NULL); get_time_interval(t); /* check errors */ mse = 0; for (i = 0; i < nof_layers; i++) { for (j = 0; j < nof_symbols; j++) { mse += cabsf(xr[i][j] - x[i][j]); if ((crealf(xr[i][j]) > 0) != (crealf(x[i][j]) > 0)) { nof_errors ++; } if ((cimagf(xr[i][j]) > 0) != (cimagf(x[i][j]) > 0)) { nof_errors ++; } } } printf("SNR: %5.1fdB;\tExecution time: %5ldus;\tMSE: %.6f;\tBER: %.6f\n", snr_db, t[0].tv_usec, mse / nof_layers / nof_symbols, (float) nof_errors / (4.0f * nof_re)); if (mse / nof_layers / nof_symbols > MSE_THRESHOLD) { ret = SRSLTE_ERROR; } quit: /* Free all data */ for (i = 0; i < nof_layers; i++) { free(x[i]); free(xr[i]); } for (i = 0; i < nof_rx_ports; i++) { free(r[i]); } for (i = 0; i < nof_rx_ports; i++) { for (j = 0; j < nof_tx_ports; j++) { free(h[j][i]); } } exit(ret); }