void srslte_enb_dl_prepare_power_allocation(srslte_enb_dl_t *q) { uint32_t nof_symbols_slot = SRSLTE_CP_NSYMB(q->cell.cp); uint32_t nof_re_symbol = SRSLTE_NRE * q->cell.nof_prb; if (q->rho_b != 0.0f && q->rho_b != 1.0f) { float scaling = 1.0f / q->rho_b; for (uint32_t i = 0; i < q->cell.nof_ports; i++) { for (uint32_t j = 0; j < 2; j++) { cf_t *ptr; ptr = q->sf_symbols[i] + nof_re_symbol * (j * nof_symbols_slot + 0); srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol); if (q->cell.cp == SRSLTE_CP_NORM) { ptr = q->sf_symbols[i] + nof_re_symbol * (j * nof_symbols_slot + 4); srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol); } else { ptr = q->sf_symbols[i] + nof_re_symbol * (j * nof_symbols_slot + 3); srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol); } if (q->cell.nof_ports == 4) { ptr = q->sf_symbols[i] + nof_re_symbol * (j * nof_symbols_slot + 1); srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol); } } } } }
void srslte_ue_dl_set_power_alloc(srslte_ue_dl_t *q, float rho_a, float rho_b) { if (q) { srslte_pdsch_set_power_allocation(&q->pdsch, rho_a); q->rho_b = rho_b; uint32_t nof_symbols_slot = SRSLTE_CP_NSYMB(q->cell.cp); uint32_t nof_re_symbol = SRSLTE_NRE * q->cell.nof_prb; /* Apply rho_b if required according to 3GPP 36.213 Table 5.2-2 */ if (rho_b != 0.0f && rho_b != 1.0f) { float scaling = 1.0f / rho_b; for (uint32_t i = 0; i < q->nof_rx_antennas; i++) { for (uint32_t j = 0; j < 2; j++) { cf_t *ptr; ptr = q->sf_symbols_m[i] + nof_re_symbol * (j * nof_symbols_slot + 0); srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol); if (q->cell.cp == SRSLTE_CP_NORM) { ptr = q->sf_symbols_m[i] + nof_re_symbol * (j * nof_symbols_slot + 4); srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol); } else { ptr = q->sf_symbols_m[i] + nof_re_symbol * (j * nof_symbols_slot + 3); srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol); } if (q->cell.nof_ports == 4) { ptr = q->sf_symbols_m[i] + nof_re_symbol * (j * nof_symbols_slot + 1); srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol); } } } } } }
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 = srslte_filesource_read(&fsrc, input_buffer, flen); srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer); if (fmatlab) { fprintf(fmatlab, "infft="); srslte_vec_fprint_c(fmatlab, input_buffer, flen); fprintf(fmatlab, ";\n"); fprintf(fmatlab, "outfft="); srslte_vec_sc_prod_cfc(fft_buffer, 1000.0, fft_buffer, SRSLTE_CP_NSYMB(cell.cp) * cell.nof_prb * SRSLTE_NRE); srslte_vec_fprint_c(fmatlab, fft_buffer, SRSLTE_CP_NSYMB(cell.cp) * cell.nof_prb * SRSLTE_NRE); fprintf(fmatlab, ";\n"); srslte_vec_sc_prod_cfc(fft_buffer, 0.001, fft_buffer, SRSLTE_CP_NSYMB(cell.cp) * cell.nof_prb * SRSLTE_NRE); } /* Get channel estimates for each port */ srslte_chest_dl_estimate(&chest, fft_buffer, ce, 0); INFO("Decoding PCFICH\n", 0); n = srslte_pcfich_decode(&pcfich, fft_buffer, ce, srslte_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 srslte_pss_synch_init_N_id_2(cf_t *pss_signal_freq, cf_t *pss_signal_time, uint32_t N_id_2, uint32_t fft_size, int cfo_i) { srslte_dft_plan_t plan; cf_t pss_signal_pad[2048]; int ret = SRSLTE_ERROR_INVALID_INPUTS; if (srslte_N_id_2_isvalid(N_id_2) && fft_size <= 2048) { srslte_pss_generate(pss_signal_freq, N_id_2); bzero(pss_signal_pad, fft_size * sizeof(cf_t)); bzero(pss_signal_time, fft_size * sizeof(cf_t)); memcpy(&pss_signal_pad[(fft_size-SRSLTE_PSS_LEN)/2+cfo_i], pss_signal_freq, SRSLTE_PSS_LEN * sizeof(cf_t)); /* Convert signal into the time domain */ if (srslte_dft_plan(&plan, fft_size, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) { return SRSLTE_ERROR; } srslte_dft_plan_set_mirror(&plan, true); srslte_dft_plan_set_dc(&plan, true); srslte_dft_plan_set_norm(&plan, true); srslte_dft_run_c(&plan, pss_signal_pad, pss_signal_time); srslte_vec_conj_cc(pss_signal_time, pss_signal_time, fft_size); srslte_vec_sc_prod_cfc(pss_signal_time, 1.0/SRSLTE_PSS_LEN, pss_signal_time, fft_size); srslte_dft_plan_free(&plan); ret = SRSLTE_SUCCESS; } return ret; }
void srslte_interp_linear_offset(srslte_interp_lin_t *q, cf_t *input, cf_t *output, uint32_t off_st, uint32_t off_end) { uint32_t i, j; cf_t diff; i=0; for (j=0;j<off_st;j++) { output[j] = input[i] + (j+1) * (input[i+1]-input[i]) / q->M; } srslte_vec_sub_ccc(&input[1], input, q->diff_vec, (q->vector_len-1)); srslte_vec_sc_prod_cfc(q->diff_vec, (float) 1/q->M, q->diff_vec, q->vector_len-1); for (i=0;i<q->vector_len-1;i++) { for (j=0;j<q->M;j++) { output[i*q->M+j+off_st] = input[i]; q->diff_vec2[i*q->M+j] = q->diff_vec[i]; } srslte_vec_prod_cfc(&q->diff_vec2[i*q->M],q->ramp,&q->diff_vec2[i*q->M],q->M); } srslte_vec_sum_ccc(&output[off_st], q->diff_vec2, &output[off_st], q->M*(q->vector_len-1)); if (q->vector_len > 1) { diff = input[q->vector_len-1]-input[q->vector_len-2]; for (j=0;j<off_end;j++) { output[i*q->M+j+off_st] = input[i] + j * diff / q->M; } } }
void srslte_enb_dl_gen_signal(srslte_enb_dl_t* q) { // TODO: PAPR control float norm_factor = 0.05f / sqrt(q->cell.nof_prb); if (q->dl_sf.sf_type == SRSLTE_SF_MBSFN) { srslte_ofdm_tx_sf(&q->ifft_mbsfn); srslte_vec_sc_prod_cfc( q->ifft_mbsfn.out_buffer, norm_factor, q->ifft_mbsfn.out_buffer, (uint32_t)SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); } else { for (int i = 0; i < q->cell.nof_ports; i++) { srslte_ofdm_tx_sf(&q->ifft[i]); srslte_vec_sc_prod_cfc( q->ifft[i].out_buffer, norm_factor, q->ifft[i].out_buffer, (uint32_t)SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); } } }
// TODO: Improve this implementation void srslte_vec_norm_cfc(cf_t *x, float amplitude, cf_t *y, uint32_t len) { // We should use fabs() here but is statistically should be similar float *xp = (float*) x; uint32_t idx = srslte_vec_max_fi(xp, 2*len); float max = xp[idx]; // Normalize before TX srslte_vec_sc_prod_cfc(x, amplitude/max, y, len); }
void srslte_interp_linear_vector(srslte_interp_linsrslte_vec_t *q, cf_t *in0, cf_t *in1, cf_t *between, uint32_t M) { uint32_t i; srslte_vec_sub_ccc(in1, in0, q->diff_vec, q->vector_len); srslte_vec_sc_prod_cfc(q->diff_vec, (float) 1/M, q->diff_vec, q->vector_len); srslte_vec_sum_ccc(in0, q->diff_vec, between, q->vector_len); for (i=0;i<M-1;i++) { srslte_vec_sum_ccc(between, q->diff_vec, &between[q->vector_len], q->vector_len); between += q->vector_len; } }
// TODO: Improve this implementation void srslte_vec_norm_cfc(cf_t *x, float amplitude, cf_t *y, uint32_t len) { // Compute peak float max = 0; float *t = (float*) x; for (int i=0;i<2*len;i++) { if (fabsf(t[i]) > max) { max = fabsf(t[i]); } } // Normalize before TX srslte_vec_sc_prod_cfc(x, amplitude/max, y, len); }
/* input points to beginning of last OFDM symbol of slot 0 of subframe 0 or 5 * It must be called after calling srslte_pss_cfo_compute() with filter enabled */ void srslte_pss_sic(srslte_pss_t *q, cf_t *input) { if (q->chest_on_filter) { bzero(q->tmp_fft, sizeof(cf_t)*q->fft_size); // Pass transmitted PSS sequence through the channel srslte_vec_prod_ccc(q->pss_signal_freq[q->N_id_2], q->tmp_ce, &q->tmp_fft[(q->fft_size-SRSLTE_PSS_LEN)/2], SRSLTE_PSS_LEN); // Get time-domain version of the received PSS srslte_dft_run_c(&q->idftp_input, q->tmp_fft, q->tmp_fft2); // Substract received PSS from this N_id_2 from the input signal srslte_vec_sc_prod_cfc(q->tmp_fft2, 1.0/q->fft_size, q->tmp_fft2, q->fft_size); srslte_vec_sub_ccc(input, q->tmp_fft2, input, q->fft_size); } else { ERROR("Error calling srslte_pss_sic(): need to enable channel estimation on filtering\n"); } }
void srslte_dft_run_c(srslte_dft_plan_t *plan, cf_t *in, cf_t *out) { float norm; int i; fftwf_complex *f_out = plan->out; copy_pre((uint8_t*)plan->in, (uint8_t*)in, sizeof(cf_t), plan->size, plan->forward, plan->mirror, plan->dc); fftwf_execute(plan->p); if (plan->norm) { norm = 1.0/sqrtf(plan->size); srslte_vec_sc_prod_cfc(f_out, norm, f_out, plan->size); } if (plan->db) { for (i=0;i<plan->size;i++) { f_out[i] = 10*log10(f_out[i]); } } copy_post((uint8_t*)out, (uint8_t*)plan->out, sizeof(cf_t), plan->size, plan->forward, plan->mirror, plan->dc); }
int main(int argc, char **argv) { int sf_idx=0, N_id_2=0; cf_t pss_signal[SRSLTE_PSS_LEN]; float sss_signal0[SRSLTE_SSS_LEN]; // for subframe 0 float sss_signal5[SRSLTE_SSS_LEN]; // for subframe 5 int i; #ifdef DISABLE_UHD if (argc < 3) { usage(argv[0]); exit(-1); } #endif parse_args(argc, argv); N_id_2 = cell.id % 3; sf_n_re = 2 * SRSLTE_CP_NORM_NSYMB * cell.nof_prb * SRSLTE_NRE; sf_n_samples = 2 * SRSLTE_SLOT_LEN(srslte_symbol_sz(cell.nof_prb)); cell.phich_length = SRSLTE_PHICH_NORM; cell.phich_resources = SRSLTE_PHICH_R_1; /* this *must* be called after setting slot_len_* */ base_init(); /* Generate PSS/SSS signals */ srslte_pss_generate(pss_signal, N_id_2); srslte_sss_generate(sss_signal0, sss_signal5, cell.id); printf("Set TX rate: %.2f MHz\n", cuhd_set_tx_srate(uhd, srslte_sampling_freq_hz(cell.nof_prb)) / 1000000); printf("Set TX gain: %.1f dB\n", cuhd_set_tx_gain(uhd, uhd_gain)); printf("Set TX freq: %.2f MHz\n", cuhd_set_tx_freq(uhd, uhd_freq) / 1000000); uint32_t nbits; srslte_modem_table_t modulator; srslte_modem_table_init(&modulator); srslte_modem_table_lte(&modulator, modulation); srslte_tcod_t turbocoder; srslte_tcod_init(&turbocoder, SRSLTE_TCOD_MAX_LEN_CB); srslte_dft_precoding_t dft_precod; srslte_dft_precoding_init(&dft_precod, 12); nbits = srslte_cbsegm_cbindex(sf_n_samples/8/srslte_mod_bits_x_symbol(modulation)/3 - 12); uint32_t ncoded_bits = sf_n_samples/8/srslte_mod_bits_x_symbol(modulation); uint8_t *data = malloc(sizeof(uint8_t)*nbits); uint8_t *data_enc = malloc(sizeof(uint8_t)*ncoded_bits); cf_t *symbols = malloc(sizeof(cf_t)*sf_n_samples); bzero(data_enc, sizeof(uint8_t)*ncoded_bits); while (1) { for (sf_idx = 0; sf_idx < SRSLTE_NSUBFRAMES_X_FRAME; sf_idx++) { bzero(sf_buffer, sizeof(cf_t) * sf_n_re); #ifdef kk if (sf_idx == 0 || sf_idx == 5) { srslte_pss_put_slot(pss_signal, sf_buffer, cell.nof_prb, SRSLTE_CP_NORM); srslte_sss_put_slot(sf_idx ? sss_signal5 : sss_signal0, sf_buffer, cell.nof_prb, SRSLTE_CP_NORM); /* Transform to OFDM symbols */ srslte_ofdm_tx_sf(&ifft, sf_buffer, output_buffer); float norm_factor = (float) sqrtf(cell.nof_prb)/15; srslte_vec_sc_prod_cfc(output_buffer, uhd_amp*norm_factor, output_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb)); } else { #endif /* Generate random data */ for (i=0;i<nbits;i++) { data[i] = rand()%2; } srslte_tcod_encode(&turbocoder, data, data_enc, nbits); srslte_mod_modulate(&modulator, data_enc, symbols, ncoded_bits); srslte_interp_linear_offset_cabs(symbols, output_buffer, 8, sf_n_samples/8, 0, 0); // } /* send to usrp */ srslte_vec_sc_prod_cfc(output_buffer, uhd_amp, output_buffer, sf_n_samples); cuhd_send(uhd, output_buffer, sf_n_samples, true); } } base_free(); printf("Done\n"); exit(0); }
void srslte_vec_ema_filter(cf_t *new_data, cf_t *average, cf_t *output, float coeff, uint32_t len) { srslte_vec_sc_prod_cfc(new_data, coeff, new_data, len); srslte_vec_sc_prod_cfc(average, 1-coeff, output, len); srslte_vec_sum_ccc(output, new_data, output, len); }
void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) { float gain_db = 10*log10(q->gain); float gain_uhd_db = 1.0; //float gain_uhd = 1.0; float y = 0; // Apply current gain to input signal if (!q->uhd_handler) { srslte_vec_sc_prod_cfc(signal, q->gain, signal, len); } else { if (q->gain < 1) { q->gain = 1.0; } if (isinf(gain_db) || isnan(gain_db)) { q->gain = 10.0; } else { gain_uhd_db = q->set_gain_callback(q->uhd_handler, gain_db); q->gain = pow(10, gain_uhd_db/10); } } float *t; switch(q->mode) { case SRSLTE_AGC_MODE_ENERGY: y = sqrtf(crealf(srslte_vec_dot_prod_conj_ccc(signal, signal, len))/len); break; case SRSLTE_AGC_MODE_PEAK_AMPLITUDE: t = (float*) signal; y = t[srslte_vec_max_fi(t, 2*len)];// take only positive max to avoid abs() (should be similar) break; default: fprintf(stderr, "Unsupported AGC mode\n"); return; } if (q->nof_frames > 0) { q->y_tmp[q->frame_cnt++] = y; if (q->frame_cnt == q->nof_frames) { q->frame_cnt = 0; switch(q->mode) { case SRSLTE_AGC_MODE_ENERGY: y = srslte_vec_acc_ff(q->y_tmp, q->nof_frames)/q->nof_frames; break; case SRSLTE_AGC_MODE_PEAK_AMPLITUDE: y = q->y_tmp[srslte_vec_max_fi(q->y_tmp, q->nof_frames)]; break; default: fprintf(stderr, "Unsupported AGC mode\n"); return; } } } double gg = 1.0; if (q->isfirst) { q->y_out = y; q->isfirst = false; } else { if (q->frame_cnt == 0) { q->y_out = (1-q->bandwidth) * q->y_out + q->bandwidth * y; if (!q->lock) { gg = expf(-0.5*q->bandwidth*logf(q->y_out/q->target)); q->gain *= gg; } INFO("AGC gain: %.2f (%.2f) y_out=%.3f, y=%.3f target=%.1f gg=%.2f\n", gain_db, gain_uhd_db, q->y_out, y, q->target, gg); } } }
/* the gateway function */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { if (nrhs != NOF_INPUTS) { help(); return; } uint32_t n_ul_rb = 0; if (mexutils_read_uint32_struct(UECFG, "NULRB", &n_ul_rb)) { mexErrMsgTxt("Field NULRB not found in UE config\n"); return; } int r = srslte_symbol_sz(n_ul_rb); if (r < 0) { mexErrMsgTxt("Invalid NULRB\n"); return; } uint32_t N_ifft_ul = (uint32_t) r; uint32_t sf_idx = 0; mexutils_read_uint32_struct(UECFG, "NSubframe", &sf_idx); uint32_t nframe = 0; mexutils_read_uint32_struct(UECFG, "NFrame", &nframe); uint32_t preamble_format = 0; mexutils_read_uint32_struct(PRACHCFG, "Format", &preamble_format); uint32_t root_seq_idx = 0; mexutils_read_uint32_struct(PRACHCFG, "SeqIdx", &root_seq_idx); uint32_t seq_idx = 0; mexutils_read_uint32_struct(PRACHCFG, "PreambleIdx", &seq_idx); uint32_t zero_corr_zone = 0; mexutils_read_uint32_struct(PRACHCFG, "CyclicShiftIdx", &zero_corr_zone); uint32_t high_speed_flag = 0; mexutils_read_uint32_struct(PRACHCFG, "HighSpeed", &high_speed_flag); uint32_t timing_offset = 0; mexutils_read_uint32_struct(PRACHCFG, "TimingOffset", &timing_offset); uint32_t frequency_offset = 0; mexutils_read_uint32_struct(PRACHCFG, "FreqOffset", &frequency_offset); srslte_prach_t prach; if (srslte_prach_init(&prach, N_ifft_ul, preamble_format, root_seq_idx, high_speed_flag, zero_corr_zone)) { mexErrMsgTxt("Error initiating PRACH\n"); return; } uint32_t nof_samples = srslte_sampling_freq_hz(n_ul_rb) * 0.001; cf_t *signal = srslte_vec_malloc(sizeof(cf_t) * nof_samples); if (!signal) { mexErrMsgTxt("malloc"); return; } bzero(signal, sizeof(cf_t) * nof_samples); if (srslte_prach_gen(&prach, seq_idx, frequency_offset, signal)) { mexErrMsgTxt("Error generating PRACH\n"); return; } srslte_vec_sc_prod_cfc(signal, 1.0/sqrtf(N_ifft_ul), signal, nof_samples); if (nlhs >= 0) { mexutils_write_cf(signal, &plhs[0], nof_samples, 1); } free(signal); srslte_prach_free(&prach); return; }