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); }
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); }
void base_init() { int i; /* Select transmission mode */ if (srslte_str2mimotype(mimo_type_str, &pdsch_cfg.mimo_type)) { ERROR("Wrong transmission mode! Allowed modes: single, diversity, cdd and multiplex"); exit(-1); } /* Configure cell and PDSCH in function of the transmission mode */ switch(pdsch_cfg.mimo_type) { case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA: cell.nof_ports = 1; break; case SRSLTE_MIMO_TYPE_TX_DIVERSITY: cell.nof_ports = 2; break; case SRSLTE_MIMO_TYPE_CDD: cell.nof_ports = 2; break; case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX: cell.nof_ports = 2; break; default: ERROR("Transmission mode not implemented."); exit(-1); } /* Allocate memory */ for(i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { data[i] = srslte_vec_malloc(sizeof(uint8_t) * SOFTBUFFER_SIZE); if (!data[i]) { perror("malloc"); exit(-1); } bzero(data[i], sizeof(uint8_t) * SOFTBUFFER_SIZE); } data_mbms = srslte_vec_malloc(sizeof(uint8_t) * SOFTBUFFER_SIZE); /* init memory */ for (i = 0; i < SRSLTE_MAX_PORTS; i++) { sf_buffer[i] = srslte_vec_malloc(sizeof(cf_t) * sf_n_re); if (!sf_buffer[i]) { perror("malloc"); exit(-1); } } for (i = 0; i < SRSLTE_MAX_PORTS; i++) { output_buffer[i] = srslte_vec_malloc(sizeof(cf_t) * sf_n_samples); if (!output_buffer[i]) { perror("malloc"); exit(-1); } bzero(output_buffer[i], sizeof(cf_t) * sf_n_samples); } /* open file or USRP */ if (output_file_name) { if (strcmp(output_file_name, "NULL")) { if (srslte_filesink_init(&fsink, output_file_name, SRSLTE_COMPLEX_FLOAT_BIN)) { fprintf(stderr, "Error opening file %s\n", output_file_name); exit(-1); } null_file_sink = false; } else { null_file_sink = true; } } else { #ifndef DISABLE_RF printf("Opening RF device...\n"); if (srslte_rf_open_multi(&rf, rf_args, cell.nof_ports)) { fprintf(stderr, "Error opening rf\n"); exit(-1); } #else printf("Error RF not available. Select an output file\n"); exit(-1); #endif } if (net_port > 0) { if (srslte_netsource_init(&net_source, "127.0.0.1", net_port, SRSLTE_NETSOURCE_UDP)) { fprintf(stderr, "Error creating input UDP socket at port %d\n", net_port); exit(-1); } if (null_file_sink) { if (srslte_netsink_init(&net_sink, "127.0.0.1", net_port+1, SRSLTE_NETSINK_TCP)) { fprintf(stderr, "Error sink\n"); exit(-1); } } if (sem_init(&net_sem, 0, 1)) { perror("sem_init"); exit(-1); } } /* create ifft object */ for (i = 0; i < cell.nof_ports; i++) { if (srslte_ofdm_tx_init(&ifft[i], SRSLTE_CP_NORM, sf_buffer[i], output_buffer[i], cell.nof_prb)) { fprintf(stderr, "Error creating iFFT object\n"); exit(-1); } srslte_ofdm_set_normalize(&ifft[i], true); } if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn, SRSLTE_CP_EXT, sf_buffer[0], output_buffer[0], cell.nof_prb)) { fprintf(stderr, "Error creating iFFT object\n"); exit(-1); } srslte_ofdm_set_non_mbsfn_region(&ifft_mbsfn, 2); srslte_ofdm_set_normalize(&ifft_mbsfn, true); if (srslte_pbch_init(&pbch)) { fprintf(stderr, "Error creating PBCH object\n"); exit(-1); } if (srslte_pbch_set_cell(&pbch, cell)) { fprintf(stderr, "Error creating PBCH object\n"); exit(-1); } if (srslte_regs_init(®s, cell)) { fprintf(stderr, "Error initiating regs\n"); exit(-1); } if (srslte_pcfich_init(&pcfich, 1)) { fprintf(stderr, "Error creating PBCH object\n"); exit(-1); } if (srslte_pcfich_set_cell(&pcfich, ®s, cell)) { fprintf(stderr, "Error creating PBCH object\n"); exit(-1); } if (srslte_pdcch_init_enb(&pdcch, cell.nof_prb)) { fprintf(stderr, "Error creating PDCCH object\n"); exit(-1); } if (srslte_pdcch_set_cell(&pdcch, ®s, cell)) { fprintf(stderr, "Error creating PDCCH object\n"); exit(-1); } if (srslte_pdsch_init_enb(&pdsch, cell.nof_prb)) { fprintf(stderr, "Error creating PDSCH object\n"); exit(-1); } if (srslte_pdsch_set_cell(&pdsch, cell)) { fprintf(stderr, "Error creating PDSCH object\n"); exit(-1); } srslte_pdsch_set_rnti(&pdsch, UE_CRNTI); if(mbsfn_area_id > -1){ if (srslte_pmch_init(&pmch, cell.nof_prb)) { fprintf(stderr, "Error creating PMCH object\n"); } srslte_pmch_set_area_id(&pmch, mbsfn_area_id); } for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { softbuffers[i] = calloc(sizeof(srslte_softbuffer_tx_t), 1); if (!softbuffers[i]) { fprintf(stderr, "Error allocating soft buffer\n"); exit(-1); } if (srslte_softbuffer_tx_init(softbuffers[i], cell.nof_prb)) { fprintf(stderr, "Error initiating soft buffer\n"); exit(-1); } } }