int main(int argc, char **argv) { uint32_t cfi; float cfi_corr; int n; if (argc < 3) { usage(argv[0]); exit(-1); } parse_args(argc,argv); if (base_init()) { fprintf(stderr, "Error initializing receiver\n"); exit(-1); } n = filesource_read(&fsrc, input_buffer, flen); lte_fft_run_sf(&fft, input_buffer, fft_buffer); if (fmatlab) { fprintf(fmatlab, "infft="); vec_fprint_c(fmatlab, input_buffer, flen); fprintf(fmatlab, ";\n"); fprintf(fmatlab, "outfft="); vec_sc_prod_cfc(fft_buffer, 1000.0, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB); vec_fprint_c(fmatlab, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB); fprintf(fmatlab, ";\n"); vec_sc_prod_cfc(fft_buffer, 0.001, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB); } /* Get channel estimates for each port */ chest_dl_estimate(&chest, fft_buffer, ce, 0); INFO("Decoding PCFICH\n", 0); n = pcfich_decode(&pcfich, fft_buffer, ce, chest_dl_get_noise_estimate(&chest), 0, &cfi, &cfi_corr); printf("cfi: %d, distance: %f\n", cfi, cfi_corr); base_free(); if (n < 0) { fprintf(stderr, "Error decoding PCFICH\n"); exit(-1); } else if (n == 0) { printf("Could not decode PCFICH\n"); exit(-1); } else { if (cfi_corr > 2.8 && cfi == 1) { exit(0); } else { exit(-1); } } }
int main(int argc, char **argv) { pbch_mib_t mib; int n; if (argc < 3) { usage(argv[0]); exit(-1); } parse_args(argc,argv); if (base_init()) { fprintf(stderr, "Error initializing receiver\n"); exit(-1); } n = filesource_read(&fsrc, input_buffer, FLEN); lte_fft_run_sf(&fft, input_buffer, fft_buffer); if (fmatlab) { fprintf(fmatlab, "outfft="); vec_sc_prod_cfc(fft_buffer, 1000.0, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB); vec_fprint_c(fmatlab, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB); fprintf(fmatlab, ";\n"); vec_sc_prod_cfc(fft_buffer, 0.001, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB); } /* Get channel estimates for each port */ chest_ce_sf(&chest, fft_buffer, ce, 0); INFO("Decoding PBCH\n", 0); n = pbch_decode(&pbch, fft_buffer, ce, &mib); base_free(); if (n < 0) { fprintf(stderr, "Error decoding PBCH\n"); exit(-1); } else if (n == 0) { printf("Could not decode PBCH\n"); exit(-1); } else { if (mib.nof_ports == 2 && mib.nof_prb == 50 && mib.phich_length == PHICH_NORM && mib.phich_resources == R_1 && mib.sfn == 28) { pbch_mib_fprint(stdout, &mib, cell.id); printf("This is the signal.1.92M.dat file\n"); exit(0); } else { pbch_mib_fprint(stdout, &mib, cell.id); printf("This is an unknown file\n"); exit(-1); } } }
/** 36.211 10.3 section 6.11.1.2 */ void pss_put_slot(cf_t *pss_signal, cf_t *slot, uint32_t nof_prb, lte_cp_t cp) { int k; k = (CP_NSYMB(cp) - 1) * nof_prb * RE_X_RB + nof_prb * RE_X_RB / 2 - 31; memset(&slot[k - 5], 0, 5 * sizeof(cf_t)); memcpy(&slot[k], pss_signal, PSS_LEN * sizeof(cf_t)); memset(&slot[k + PSS_LEN], 0, 5 * sizeof(cf_t)); }
int chest_init_LTEDL(chest_t *q, lte_cell_t cell) { int ret; ret = chest_init(q, cell.nof_prb * RE_X_RB, CP_NSYMB(cell.cp), cell.nof_ports); if (ret != LIBLTE_SUCCESS) { return ret; } else { return chest_ref_LTEDL(q, cell); } }
/** 36.211 10.3 section 6.11.2.2 */ void sss_put_slot(float *sss, cf_t *slot, uint32_t nof_prb, lte_cp_t cp) { uint32_t i, k; k = (CP_NSYMB(cp) - 2) * nof_prb * RE_X_RB + nof_prb * RE_X_RB / 2 - 31; if (k > 5) { memset(&slot[k - 5], 0, 5 * sizeof(cf_t)); for (i = 0; i < SSS_LEN; i++) { __real__ slot[k + i] = sss[i]; __imag__ slot[k + i] = 0; } memset(&slot[k + SSS_LEN], 0, 5 * sizeof(cf_t)); } }
int chest_init(chest_t *q, chest_interp_t interp, lte_cp_t cp, int nof_prb, int nof_ports) { if (nof_ports > MAX_PORTS) { fprintf(stderr, "Error: Maximum ports %d\n", MAX_PORTS); return -1; } bzero(q, sizeof(chest_t)); q->nof_ports = nof_ports; q->nof_symbols = CP_NSYMB(cp); q->cp = cp; q->nof_prb = nof_prb; switch(interp) { case LINEAR: q->interp = interp_linear_offset; } INFO("Initializing channel estimator size %dx%d, nof_ports=%d\n", q->nof_symbols, nof_prb, nof_ports); return 0; }
/* the gateway function */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { int i; lte_cell_t cell; chest_dl_t chest; precoding_t cheq; cf_t *input_signal = NULL, *output_signal[MAX_LAYERS]; cf_t *output_signal2 = NULL; cf_t *ce[MAX_PORTS]; double *outr0=NULL, *outi0=NULL; double *outr1=NULL, *outi1=NULL; double *outr2=NULL, *outi2=NULL; if (nrhs < NOF_INPUTS) { help(); return; } if (!mxIsDouble(CELLID) && mxGetN(CELLID) != 1 && !mxIsDouble(PORTS) && mxGetN(PORTS) != 1 && mxGetM(CELLID) != 1) { help(); return; } cell.id = (uint32_t) *((double*) mxGetPr(CELLID)); cell.nof_prb = mxGetM(INPUT)/RE_X_RB; cell.nof_ports = (uint32_t) *((double*) mxGetPr(PORTS)); if ((mxGetN(INPUT)%14) == 0) { cell.cp = CPNORM; } else if ((mxGetN(INPUT)%12)!=0) { cell.cp = CPEXT; } else { mexErrMsgTxt("Invalid number of symbols\n"); help(); return; } if (chest_dl_init(&chest, cell)) { mexErrMsgTxt("Error initiating channel estimator\n"); return; } int nsubframes; if (cell.cp == CPNORM) { nsubframes = mxGetN(INPUT)/14; } else { nsubframes = mxGetN(INPUT)/12; } uint32_t sf_idx=0; if (nsubframes == 1) { if (nrhs != NOF_INPUTS+1) { mexErrMsgTxt("Received 1 subframe. Need to provide subframe index.\n"); help(); return; } sf_idx = (uint32_t) *((double*) mxGetPr(SFIDX)); } else { if (nrhs != NOF_INPUTS) { help(); return; } } uint32_t filter_len = 0; float *filter; double *f; filter_len = mxGetNumberOfElements(FREQ_FILTER); filter = malloc(sizeof(float) * filter_len); f = (double*) mxGetPr(FREQ_FILTER); for (i=0;i<filter_len;i++) { filter[i] = (float) f[i]; } chest_dl_set_filter_freq(&chest, filter, filter_len); filter_len = mxGetNumberOfElements(TIME_FILTER); filter = malloc(sizeof(float) * filter_len); f = (double*) mxGetPr(TIME_FILTER); for (i=0;i<filter_len;i++) { filter[i] = (float) f[i]; } chest_dl_set_filter_time(&chest, filter, filter_len); double *inr=(double *)mxGetPr(INPUT); double *ini=(double *)mxGetPi(INPUT); /** Allocate input buffers */ int nof_re = 2*CP_NSYMB(cell.cp)*cell.nof_prb*RE_X_RB; for (i=0;i<MAX_PORTS;i++) { ce[i] = vec_malloc(nof_re * sizeof(cf_t)); } input_signal = vec_malloc(nof_re * sizeof(cf_t)); for (i=0;i<MAX_PORTS;i++) { output_signal[i] = vec_malloc(nof_re * sizeof(cf_t)); } output_signal2 = vec_malloc(nof_re * sizeof(cf_t)); precoding_init(&cheq, nof_re); /* Create output values */ if (nlhs >= 1) { plhs[0] = mxCreateDoubleMatrix(nof_re * nsubframes, cell.nof_ports, mxCOMPLEX); outr0 = mxGetPr(plhs[0]); outi0 = mxGetPi(plhs[0]); } if (nlhs >= 2) { plhs[1] = mxCreateDoubleMatrix(REFSIGNAL_MAX_NUM_SF(cell.nof_prb)*nsubframes, cell.nof_ports, mxCOMPLEX); outr1 = mxGetPr(plhs[1]); outi1 = mxGetPi(plhs[1]); } if (nlhs >= 3) { plhs[2] = mxCreateDoubleMatrix(nof_re * nsubframes, 1, mxCOMPLEX); outr2 = mxGetPr(plhs[2]); outi2 = mxGetPi(plhs[2]); } for (int sf=0;sf<nsubframes;sf++) { /* Convert input to C complex type */ for (i=0;i<nof_re;i++) { __real__ input_signal[i] = (float) *inr; if (ini) { __imag__ input_signal[i] = (float) *ini; } inr++; ini++; } if (nsubframes != 1) { sf_idx = sf%10; } if (chest_dl_estimate(&chest, input_signal, ce, sf_idx)) { mexErrMsgTxt("Error running channel estimator\n"); return; } if (cell.nof_ports == 1) { predecoding_single(&cheq, input_signal, ce[0], output_signal2, nof_re, chest_dl_get_noise_estimate(&chest)); } else { predecoding_diversity(&cheq, input_signal, ce, output_signal, cell.nof_ports, nof_re, chest_dl_get_noise_estimate(&chest)); layerdemap_diversity(output_signal, output_signal2, cell.nof_ports, nof_re/cell.nof_ports); } if (nlhs >= 1) { for (int j=0;j<cell.nof_ports;j++) { for (i=0;i<nof_re;i++) { *outr0 = (double) crealf(ce[j][i]); if (outi0) { *outi0 = (double) cimagf(ce[j][i]); } outr0++; outi0++; } } } if (nlhs >= 2) { for (int j=0;j<cell.nof_ports;j++) { for (i=0;i<REFSIGNAL_NUM_SF(cell.nof_prb,j);i++) { *outr1 = (double) crealf(chest.pilot_estimates_average[j][i]); if (outi1) { *outi1 = (double) cimagf(chest.pilot_estimates_average[j][i]); } outr1++; outi1++; } } } if (nlhs >= 3) { for (i=0;i<nof_re;i++) { *outr2 = (double) crealf(output_signal2[i]); if (outi2) { *outi2 = (double) cimagf(output_signal2[i]); } outr2++; outi2++; } } } if (nlhs >= 4) { plhs[3] = mxCreateDoubleScalar(chest_dl_get_snr(&chest)); } if (nlhs >= 5) { plhs[4] = mxCreateDoubleScalar(chest_dl_get_noise_estimate(&chest)); } if (nlhs >= 6) { plhs[5] = mxCreateDoubleScalar(chest_dl_get_rsrp(&chest)); } chest_dl_free(&chest); precoding_free(&cheq); return; }
int base_init() { int i; if (filesource_init(&fsrc, input_file_name, COMPLEX_FLOAT_BIN)) { fprintf(stderr, "Error opening file %s\n", input_file_name); exit(-1); } if (matlab_file_name) { fmatlab = fopen(matlab_file_name, "w"); if (!fmatlab) { perror("fopen"); return -1; } } else { fmatlab = NULL; } input_buffer = malloc(FLEN * sizeof(cf_t)); if (!input_buffer) { perror("malloc"); exit(-1); } fft_buffer = malloc(2 * CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB * sizeof(cf_t)); if (!fft_buffer) { perror("malloc"); return -1; } for (i=0;i<cell.nof_ports;i++) { ce[i] = malloc(2 * CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB * sizeof(cf_t)); if (!ce[i]) { perror("malloc"); return -1; } } if (!lte_cell_isvalid(&cell)) { fprintf(stderr, "Invalid cell properties\n"); return -1; } if (chest_init_LTEDL(&chest, cell)) { fprintf(stderr, "Error initializing equalizer\n"); return -1; } if (lte_fft_init(&fft, cell.cp, cell.nof_prb)) { fprintf(stderr, "Error initializing FFT\n"); return -1; } if (pbch_init(&pbch, cell)) { fprintf(stderr, "Error initiating PBCH\n"); return -1; } DEBUG("Memory init OK\n",0); return 0; }
int main(int argc, char **argv) { ra_pdsch_t ra_dl; int i; int nof_frames; int ret; char *data; dci_location_t locations[10]; uint32_t nof_locations; dci_msg_t dci_msg; data = malloc(10000); if (argc < 3) { usage(argv[0]); exit(-1); } parse_args(argc,argv); if (base_init()) { fprintf(stderr, "Error initializing memory\n"); exit(-1); } if (rnti == SIRNTI) { INFO("Initializing common search space for SI-RNTI\n",0); nof_locations = pdcch_common_locations(&pdcch, locations, 10, cfi); } else { // For ue-specific, generate locations for subframe 5 INFO("Initializing user-specific search space for RNTI: 0x%x\n", rnti); nof_locations = pdcch_ue_locations(&pdcch, locations, 10, 5, cfi, rnti); } ret = -1; nof_frames = 0; do { filesource_read(&fsrc, input_buffer, flen); if (nof_frames == 5) { INFO("Reading %d samples sub-frame %d\n", flen, nof_frames); lte_fft_run_sf(&fft, input_buffer, fft_buffer); if (fmatlab) { fprintf(fmatlab, "infft%d=", nof_frames); vec_fprint_c(fmatlab, input_buffer, flen); fprintf(fmatlab, ";\n"); fprintf(fmatlab, "outfft%d=", nof_frames); vec_sc_prod_cfc(fft_buffer, 1000.0, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB); vec_fprint_c(fmatlab, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB); fprintf(fmatlab, ";\n"); vec_sc_prod_cfc(fft_buffer, 0.001, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB); } /* Get channel estimates for each port */ for (i=0;i<cell.nof_ports;i++) { chest_ce_slot_port(&chest, fft_buffer, ce[i], 2*nof_frames, i); chest_ce_slot_port(&chest, &fft_buffer[CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB], &ce[i][CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB], 2*nof_frames+1, i); if (fmatlab) { chest_fprint(&chest, fmatlab, 2*nof_frames+1, i); } } uint16_t crc_rem = 0; for (i=0;i<nof_locations && crc_rem != rnti;i++) { if (pdcch_extract_llr(&pdcch, fft_buffer, ce, locations[i], nof_frames, cfi)) { fprintf(stderr, "Error extracting LLRs\n"); return -1; } if (pdcch_decode_msg(&pdcch, &dci_msg, Format1A, &crc_rem)) { fprintf(stderr, "Error decoding DCI msg\n"); return -1; } } if (crc_rem == rnti) { if (dci_msg_to_ra_dl(&dci_msg, rnti, 1234, cell, cfi, &ra_dl)) { fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n"); goto goout; } if (pdsch_harq_setup(&harq_process, ra_dl.mcs, &ra_dl.prb_alloc)) { fprintf(stderr, "Error configuring HARQ process\n"); goto goout; } if (pdsch_decode(&pdsch, fft_buffer, ce, data, nof_frames%10, &harq_process, ra_dl.rv_idx)) { fprintf(stderr, "Error decoding PDSCH\n"); goto goout; } else { printf("PDSCH Decoded OK!\n"); } } } nof_frames++; } while (nof_frames <= max_frames); ret = 0; goout: base_free(); exit(ret); }
int base_init() { int i; if (filesource_init(&fsrc, input_file_name, COMPLEX_FLOAT_BIN)) { fprintf(stderr, "Error opening file %s\n", input_file_name); exit(-1); } if (matlab_file_name) { fmatlab = fopen(matlab_file_name, "w"); if (!fmatlab) { perror("fopen"); return -1; } } else { fmatlab = NULL; } flen = 2 * (SLOT_LEN(lte_symbol_sz(cell.nof_prb))); input_buffer = malloc(flen * sizeof(cf_t)); if (!input_buffer) { perror("malloc"); exit(-1); } fft_buffer = malloc(2 * CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB * sizeof(cf_t)); if (!fft_buffer) { perror("malloc"); return -1; } for (i=0;i<MAX_PORTS;i++) { ce[i] = malloc(2 * CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB * sizeof(cf_t)); if (!ce[i]) { perror("malloc"); return -1; } } if (chest_init_LTEDL(&chest, cell)) { fprintf(stderr, "Error initializing equalizer\n"); return -1; } if (lte_fft_init(&fft, cell.cp, cell.nof_prb)) { fprintf(stderr, "Error initializing FFT\n"); return -1; } if (regs_init(®s, R_1, PHICH_NORM, cell)) { fprintf(stderr, "Error initiating regs\n"); return -1; } if (regs_set_cfi(®s, cfi)) { fprintf(stderr, "Error setting CFI %d\n", cfi); return -1; } if (pdcch_init(&pdcch, ®s, cell)) { fprintf(stderr, "Error creating PDCCH object\n"); exit(-1); } if (pdsch_init(&pdsch, cell)) { fprintf(stderr, "Error creating PDSCH object\n"); exit(-1); } pdsch_set_rnti(&pdsch, rnti); if (pdsch_harq_init(&harq_process, &pdsch)) { fprintf(stderr, "Error initiating HARQ process\n"); exit(-1); } DEBUG("Memory init OK\n",0); return 0; }
int main(int argc, char **argv) { chest_t eq; cf_t *input = NULL, *ce = NULL, *h = NULL; refsignal_t refs; int i, j, n_port, n_slot, cid, num_re; int ret = -1; int max_cid; FILE *fmatlab = NULL; float mse_mag, mse_phase; parse_args(argc,argv); if (output_matlab) { fmatlab=fopen(output_matlab, "w"); if (!fmatlab) { perror("fopen"); goto do_exit; } } num_re = nof_prb * RE_X_RB * CP_NSYMB(cp); input = malloc(num_re * sizeof(cf_t)); if (!input) { perror("malloc"); goto do_exit; } h = malloc(num_re * sizeof(cf_t)); if (!h) { perror("malloc"); goto do_exit; } ce = malloc(num_re * sizeof(cf_t)); if (!ce) { perror("malloc"); goto do_exit; } if (cell_id == -1) { cid = 0; max_cid = 504; } else { cid = cell_id; max_cid = cell_id; } while(cid <= max_cid) { if (chest_init(&eq, LINEAR, cp, nof_prb, MAX_PORTS)) { fprintf(stderr, "Error initializing equalizer\n"); goto do_exit; } if (chest_ref_LTEDL(&eq, cid)) { fprintf(stderr, "Error initializing reference signal\n"); goto do_exit; } for (n_slot=0;n_slot<NSLOTS_X_FRAME;n_slot++) { for (n_port=0;n_port<MAX_PORTS;n_port++) { if (refsignal_init_LTEDL(&refs, n_port, n_slot, cid, cp, nof_prb)) { fprintf(stderr, "Error initiating CRS slot=%d\n", i); return -1; } bzero(input, sizeof(cf_t) * num_re); for (i=0;i<num_re;i++) { input[i] = 0.5-rand()/RAND_MAX+I*(0.5-rand()/RAND_MAX); } bzero(ce, sizeof(cf_t) * num_re); bzero(h, sizeof(cf_t) * num_re); refsignal_put(&refs, input); refsignal_free(&refs); for (i=0;i<CP_NSYMB(cp);i++) { for (j=0;j<nof_prb * RE_X_RB;j++) { float x = -1+(float) i/CP_NSYMB(cp) + cosf(2 * M_PI * (float) j/nof_prb/RE_X_RB); h[i*nof_prb * RE_X_RB+j] = (3+x) * cexpf(I * x); input[i*nof_prb * RE_X_RB+j] *= h[i*nof_prb * RE_X_RB+j]; } } chest_ce_slot_port(&eq, input, ce, n_slot, n_port); mse_mag = mse_phase = 0; for (i=0;i<num_re;i++) { mse_mag += (cabsf(h[i]) - cabsf(ce[i])) * (cabsf(h[i]) - cabsf(ce[i])) / num_re; mse_phase += (cargf(h[i]) - cargf(ce[i])) * (cargf(h[i]) - cargf(ce[i])) / num_re; } if (check_mse(mse_mag, mse_phase, n_port)) { goto do_exit; } if (fmatlab) { fprintf(fmatlab, "input="); vec_fprint_c(fmatlab, input, num_re); fprintf(fmatlab, ";\n"); fprintf(fmatlab, "h="); vec_fprint_c(fmatlab, h, num_re); fprintf(fmatlab, ";\n"); fprintf(fmatlab, "ce="); vec_fprint_c(fmatlab, ce, num_re); fprintf(fmatlab, ";\n"); chest_fprint(&eq, fmatlab, n_slot, n_port); } } } chest_free(&eq); cid+=10; INFO("cid=%d\n", cid); } ret = 0; do_exit: if (ce) { free(ce); } if (input) { free(input); } if (h) { free(h); } if (!ret) { printf("OK\n"); } else { printf("Error at cid=%d, slot=%d, port=%d\n",cid, n_slot, n_port); } exit(ret); }
int main(int argc, char **argv) { int distance; int i, n; int ngroup, nseq, max_nseq; char ack_rx; if (argc < 3) { usage(argv[0]); exit(-1); } parse_args(argc,argv); max_nseq = CP_ISNORM(cp)?PHICH_NORM_NSEQUENCES:PHICH_EXT_NSEQUENCES; if (base_init()) { fprintf(stderr, "Error initializing memory\n"); exit(-1); } n = filesource_read(&fsrc, input_buffer, flen); lte_fft_run(&fft, input_buffer, fft_buffer); if (fmatlab) { fprintf(fmatlab, "infft="); vec_fprint_c(fmatlab, input_buffer, flen); fprintf(fmatlab, ";\n"); fprintf(fmatlab, "outfft="); vec_fprint_c(fmatlab, fft_buffer, CP_NSYMB(cp) * nof_prb * RE_X_RB); fprintf(fmatlab, ";\n"); } /* Get channel estimates for each port */ for (i=0;i<nof_ports;i++) { chest_ce_slot_port(&chest, fft_buffer, ce[i], 0, i); if (fmatlab) { chest_fprint(&chest, fmatlab, 0, i); } } INFO("Decoding PHICH\n", 0); /* Receive all PHICH groups and sequence numbers */ for (ngroup=0;ngroup<phich_ngroups(&phich);ngroup++) { for (nseq=0;nseq<max_nseq;nseq++) { if (phich_decode(&phich, fft_buffer, ce, ngroup, nseq, numsubframe, &ack_rx, &distance)<0) { printf("Error decoding ACK\n"); exit(-1); } INFO("%d/%d, ack_rx: %d, ns: %d, distance: %d\n", ngroup, nseq, ack_rx, numsubframe, distance); } } base_free(); fftwf_cleanup(); if (n < 0) { fprintf(stderr, "Error decoding phich\n"); exit(-1); } else if (n == 0) { printf("Could not decode phich\n"); exit(-1); } else { exit(0); } }
int base_init() { int i; if (filesource_init(&fsrc, input_file_name, COMPLEX_FLOAT_BIN)) { fprintf(stderr, "Error opening file %s\n", input_file_name); exit(-1); } if (matlab_file_name) { fmatlab = fopen(matlab_file_name, "w"); if (!fmatlab) { perror("fopen"); return -1; } } else { fmatlab = NULL; } flen = SLOT_LEN(lte_symbol_sz(nof_prb), cp); input_buffer = malloc(flen * sizeof(cf_t)); if (!input_buffer) { perror("malloc"); exit(-1); } fft_buffer = malloc(CP_NSYMB(cp) * nof_prb * RE_X_RB * sizeof(cf_t)); if (!fft_buffer) { perror("malloc"); return -1; } for (i=0;i<MAX_PORTS_CTRL;i++) { ce[i] = malloc(CP_NSYMB(cp) * nof_prb * RE_X_RB * sizeof(cf_t)); if (!ce[i]) { perror("malloc"); return -1; } } if (chest_init(&chest, LINEAR, cp, nof_prb, nof_ports)) { fprintf(stderr, "Error initializing equalizer\n"); return -1; } if (chest_ref_LTEDL(&chest, cell_id)) { fprintf(stderr, "Error initializing reference signal\n"); return -1; } if (lte_fft_init(&fft, cp, nof_prb)) { fprintf(stderr, "Error initializing FFT\n"); return -1; } if (regs_init(®s, cell_id, nof_prb, nof_ports, phich_res, phich_length, cp)) { fprintf(stderr, "Error initiating regs\n"); return -1; } if (phich_init(&phich, ®s, cell_id, nof_prb, nof_ports, cp)) { fprintf(stderr, "Error creating PBCH object\n"); return -1; } DEBUG("Memory init OK\n",0); return 0; }
/** Converts the MIB message to symbols mapped to SLOT #1 ready for transmission */ int pbch_encode(pbch_t *q, pbch_mib_t *mib, cf_t *sf_symbols[MAX_PORTS]) { int i; int nof_bits; cf_t *slot1_symbols[MAX_PORTS]; cf_t *x[MAX_LAYERS]; if (q != NULL && mib != NULL) { for (i=0;i<q->cell.nof_ports;i++) { if (sf_symbols[i] == NULL) { return LIBLTE_ERROR_INVALID_INPUTS; } else { slot1_symbols[i] = &sf_symbols[i][q->cell.nof_prb * RE_X_RB * CP_NSYMB(q->cell.cp)]; } } /* Set pointers for layermapping & precoding */ nof_bits = 2 * q->nof_symbols; /* number of layers equals number of ports */ for (i = 0; i < q->cell.nof_ports; i++) { x[i] = q->pbch_x[i]; } memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports)); if (q->frame_idx == 0) { /* pack MIB */ pbch_mib_pack(mib, q->data); /* encode & modulate */ crc_attach(&q->crc, q->data, 24); crc_set_mask(q->data, q->cell.nof_ports); convcoder_encode(&q->encoder, q->data, q->data_enc, 40); rm_conv_tx(q->data_enc, 120, q->pbch_rm_b, 4 * nof_bits); } scrambling_b_offset(&q->seq_pbch, &q->pbch_rm_b[q->frame_idx * nof_bits], q->frame_idx * nof_bits, nof_bits); mod_modulate(&q->mod, &q->pbch_rm_b[q->frame_idx * nof_bits], q->pbch_d, nof_bits); /* layer mapping & precoding */ if (q->cell.nof_ports > 1) { layermap_diversity(q->pbch_d, x, q->cell.nof_ports, q->nof_symbols); precoding_diversity(x, q->pbch_symbols, q->cell.nof_ports, q->nof_symbols / q->cell.nof_ports); } else { memcpy(q->pbch_symbols[0], q->pbch_d, q->nof_symbols * sizeof(cf_t)); } /* mapping to resource elements */ for (i = 0; i < q->cell.nof_ports; i++) { pbch_put(q->pbch_symbols[i], slot1_symbols[i], q->cell); } q->frame_idx++; if (q->frame_idx == 4) { q->frame_idx = 0; } return LIBLTE_SUCCESS; } else { return LIBLTE_ERROR_INVALID_INPUTS; } }
/* Decodes the PBCH channel * * The PBCH spans in 40 ms. This function is called every 10 ms. It tries to decode the MIB * given the symbols of a subframe (1 ms). Successive calls will use more subframes * to help the decoding process. * * Returns 1 if successfully decoded MIB, 0 if not and -1 on error */ int pbch_decode(pbch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], pbch_mib_t *mib) { uint32_t src, dst, nb; uint32_t nant_[3] = { 1, 2, 4 }; uint32_t na, nant; cf_t *slot1_symbols; int i; int nof_bits; cf_t *x[MAX_LAYERS]; cf_t *ce_slot[MAX_PORTS]; int ret = LIBLTE_ERROR_INVALID_INPUTS; if (q != NULL && sf_symbols != NULL && mib != NULL) { for (i=0;i<q->cell.nof_ports;i++) { if (ce[i] == NULL) { return LIBLTE_ERROR_INVALID_INPUTS; } else { ce_slot[i] = &ce[i][q->cell.nof_prb * RE_X_RB * CP_NSYMB(q->cell.cp)]; } } slot1_symbols = &sf_symbols[q->cell.nof_prb * RE_X_RB * CP_NSYMB(q->cell.cp)]; /* Set pointers for layermapping & precoding */ nof_bits = 2 * q->nof_symbols; /* number of layers equals number of ports */ for (i = 0; i < MAX_PORTS; i++) { x[i] = q->pbch_x[i]; } memset(&x[MAX_PORTS], 0, sizeof(cf_t*) * (MAX_LAYERS - MAX_PORTS)); /* extract symbols */ if (q->nof_symbols != pbch_get(slot1_symbols, q->pbch_symbols[0], q->cell)) { fprintf(stderr, "There was an error getting the PBCH symbols\n"); return LIBLTE_ERROR; } /* extract channel estimates */ for (i = 0; i < q->cell.nof_ports; i++) { if (q->nof_symbols != pbch_get(ce_slot[i], q->ce[i], q->cell)) { fprintf(stderr, "There was an error getting the PBCH symbols\n"); return LIBLTE_ERROR; } } q->frame_idx++; ret = 0; /* Try decoding for 1 to cell.nof_ports antennas */ for (na = 0; na < q->cell.nof_ports && !ret; na++) { nant = nant_[na]; INFO("Trying %d TX antennas with %d frames\n", nant, q->frame_idx); /* in conctrol channels, only diversity is supported */ if (nant == 1) { /* no need for layer demapping */ predecoding_single_zf(q->pbch_symbols[0], q->ce[0], q->pbch_d, q->nof_symbols); } else { predecoding_diversity_zf(q->pbch_symbols[0], q->ce, x, nant, q->nof_symbols); layerdemap_diversity(x, q->pbch_d, nant, q->nof_symbols / nant); } /* demodulate symbols */ demod_soft_sigma_set(&q->demod, 1.0); demod_soft_demodulate(&q->demod, q->pbch_d, &q->pbch_llr[nof_bits * (q->frame_idx - 1)], q->nof_symbols); /* We don't know where the 40 ms begin, so we try all combinations. E.g. if we received * 4 frames, try 1,2,3,4 individually, 12, 23, 34 in pairs, 123, 234 and finally 1234. * We know they are ordered. * * FIXME: There are unnecessary checks because 2,3,4 have already been processed in the previous * calls. */ for (nb = 0; nb < q->frame_idx && !ret; nb++) { for (dst = 0; (dst < 4 - nb) && !ret; dst++) { for (src = 0; src < q->frame_idx - nb && !ret; src++) { DEBUG("Trying %d blocks at offset %d as subframe mod4 number %d\n", nb + 1, src, dst); ret = pbch_decode_frame(q, mib, src, dst, nb + 1, nof_bits, nant); } } } } /* If not found, make room for the next packet of radio frame symbols */ if (q->frame_idx == 4) { memmove(q->pbch_llr, &q->pbch_llr[nof_bits], nof_bits * 3 * sizeof(float)); q->frame_idx = 3; } } return ret; }