int srslte_ue_mib_sync_decode(srslte_ue_mib_sync_t * q, uint32_t max_frames_timeout, uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN], uint32_t *nof_tx_ports, int *sfn_offset) { int ret = SRSLTE_ERROR_INVALID_INPUTS; cf_t *sf_buffer = NULL; uint32_t nof_frames = 0; int mib_ret = SRSLTE_UE_MIB_NOTFOUND; if (q != NULL) { ret = SRSLTE_SUCCESS; do { mib_ret = SRSLTE_UE_MIB_NOTFOUND; ret = srslte_ue_sync_get_buffer(&q->ue_sync, &sf_buffer); if (ret < 0) { fprintf(stderr, "Error calling srslte_ue_sync_work()\n"); break; } else if (srslte_ue_sync_get_sfidx(&q->ue_sync) == 0) { if (ret == 1) { mib_ret = srslte_ue_mib_decode(&q->ue_mib, sf_buffer, bch_payload, nof_tx_ports, sfn_offset); } else { DEBUG("Resetting PBCH decoder after %d frames\n", q->ue_mib.frame_cnt); srslte_ue_mib_reset(&q->ue_mib); } nof_frames++; } } while (mib_ret == SRSLTE_UE_MIB_NOTFOUND && ret >= 0 && nof_frames < max_frames_timeout); if (mib_ret < 0) { ret = mib_ret; } } return mib_ret; }
int main(int argc, char **argv) { int ret; cf_t *sf_buffer; prog_args_t prog_args; srslte_cell_t cell; int64_t sf_cnt; srslte_ue_sync_t ue_sync; srslte_ue_mib_t ue_mib; void *uhd; srslte_ue_dl_t ue_dl; srslte_ofdm_t fft; srslte_chest_dl_t chest; uint32_t nframes=0; uint32_t nof_trials = 0; uint32_t sfn = 0; // system frame number int n; uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; uint32_t sfn_offset; float rssi_utra=0,rssi=0, rsrp=0, rsrq=0, snr=0; cf_t *ce[SRSLTE_MAX_PORTS]; if (parse_args(&prog_args, argc, argv)) { exit(-1); } if (prog_args.uhd_gain > 0) { printf("Opening UHD device...\n"); if (cuhd_open(prog_args.uhd_args, &uhd)) { fprintf(stderr, "Error opening uhd\n"); exit(-1); } cuhd_set_rx_gain(uhd, prog_args.uhd_gain); } else { printf("Opening UHD device with threaded RX Gain control ...\n"); if (cuhd_open_th(prog_args.uhd_args, &uhd, false)) { fprintf(stderr, "Error opening uhd\n"); exit(-1); } cuhd_set_rx_gain(uhd, 50); } sigset_t sigset; sigemptyset(&sigset); sigaddset(&sigset, SIGINT); sigprocmask(SIG_UNBLOCK, &sigset, NULL); signal(SIGINT, sig_int_handler); cuhd_set_master_clock_rate(uhd, 30.72e6); /* set receiver frequency */ cuhd_set_rx_freq(uhd, (double) prog_args.uhd_freq); cuhd_rx_wait_lo_locked(uhd); printf("Tunning receiver to %.3f MHz\n", (double ) prog_args.uhd_freq/1000000); uint32_t ntrial=0; do { ret = cuhd_search_and_decode_mib(uhd, &cell_detect_config, prog_args.force_N_id_2, &cell); if (ret < 0) { fprintf(stderr, "Error searching for cell\n"); exit(-1); } else if (ret == 0 && !go_exit) { printf("Cell not found after %d trials. Trying again (Press Ctrl+C to exit)\n", ntrial++); } } while (ret == 0 && !go_exit); if (go_exit) { exit(0); } /* set sampling frequency */ int srate = srslte_sampling_freq_hz(cell.nof_prb); if (srate != -1) { if (srate < 10e6) { cuhd_set_master_clock_rate(uhd, 4*srate); } else { cuhd_set_master_clock_rate(uhd, srate); } printf("Setting sampling rate %.2f MHz\n", (float) srate/1000000); float srate_uhd = cuhd_set_rx_srate(uhd, (double) srate); if (srate_uhd != srate) { fprintf(stderr, "Could not set sampling rate\n"); exit(-1); } } else { fprintf(stderr, "Invalid number of PRB %d\n", cell.nof_prb); exit(-1); } INFO("Stopping UHD and flushing buffer...\n",0); cuhd_stop_rx_stream(uhd); cuhd_flush_buffer(uhd); if (srslte_ue_sync_init(&ue_sync, cell, cuhd_recv_wrapper, uhd)) { fprintf(stderr, "Error initiating ue_sync\n"); return -1; } if (srslte_ue_dl_init(&ue_dl, cell)) { fprintf(stderr, "Error initiating UE downlink processing module\n"); return -1; } if (srslte_ue_mib_init(&ue_mib, cell)) { fprintf(stderr, "Error initaiting UE MIB decoder\n"); return -1; } /* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */ srslte_ue_dl_set_rnti(&ue_dl, SRSLTE_SIRNTI); /* Initialize subframe counter */ sf_cnt = 0; if (srslte_ofdm_rx_init(&fft, cell.cp, cell.nof_prb)) { fprintf(stderr, "Error initiating FFT\n"); return -1; } if (srslte_chest_dl_init(&chest, cell)) { fprintf(stderr, "Error initiating channel estimator\n"); return -1; } int sf_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp); cf_t *sf_symbols = srslte_vec_malloc(sf_re * sizeof(cf_t)); for (int i=0;i<SRSLTE_MAX_PORTS;i++) { ce[i] = srslte_vec_malloc(sizeof(cf_t) * sf_re); } cuhd_start_rx_stream(uhd); float rx_gain_offset = 0; /* Main loop */ while ((sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1) && !go_exit) { ret = srslte_ue_sync_get_buffer(&ue_sync, &sf_buffer); if (ret < 0) { fprintf(stderr, "Error calling srslte_ue_sync_work()\n"); } /* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */ if (ret == 1) { switch (state) { case DECODE_MIB: if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) { srslte_pbch_decode_reset(&ue_mib.pbch); n = srslte_ue_mib_decode(&ue_mib, sf_buffer, bch_payload, NULL, &sfn_offset); if (n < 0) { fprintf(stderr, "Error decoding UE MIB\n"); return -1; } else if (n == SRSLTE_UE_MIB_FOUND) { srslte_pbch_mib_unpack(bch_payload, &cell, &sfn); printf("Decoded MIB. SFN: %d, offset: %d\n", sfn, sfn_offset); sfn = (sfn + sfn_offset)%1024; state = DECODE_SIB; } } break; case DECODE_SIB: /* We are looking for SI Blocks, search only in appropiate places */ if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) { n = srslte_ue_dl_decode_rnti_rv(&ue_dl, sf_buffer, data, srslte_ue_sync_get_sfidx(&ue_sync), SRSLTE_SIRNTI, ((int) ceilf((float)3*(((sfn)/2)%4)/2))%4); if (n < 0) { fprintf(stderr, "Error decoding UE DL\n");fflush(stdout); return -1; } else if (n == 0) { printf("CFO: %+6.4f KHz, SFO: %+6.4f Khz, NOI: %.2f, PDCCH-Det: %.3f\r", srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000, srslte_sch_average_noi(&ue_dl.pdsch.dl_sch), (float) ue_dl.nof_detected/nof_trials); nof_trials++; } else { printf("Decoded SIB1. Payload: "); srslte_vec_fprint_byte(stdout, data, n/8);; state = MEASURE; } } break; case MEASURE: if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) { /* Run FFT for all subframe data */ srslte_ofdm_rx_sf(&fft, sf_buffer, sf_symbols); srslte_chest_dl_estimate(&chest, sf_symbols, ce, srslte_ue_sync_get_sfidx(&ue_sync)); rssi = SRSLTE_VEC_EMA(srslte_vec_avg_power_cf(sf_buffer,SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb))),rssi,0.05); rssi_utra = SRSLTE_VEC_EMA(srslte_chest_dl_get_rssi(&chest),rssi_utra,0.05); rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&chest),rsrq,0.05); rsrp = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp(&chest),rsrp,0.05); snr = SRSLTE_VEC_EMA(srslte_chest_dl_get_snr(&chest),snr,0.05); nframes++; } if ((nframes%100) == 0 || rx_gain_offset == 0) { if (cuhd_has_rssi(uhd)) { rx_gain_offset = 10*log10(rssi)-cuhd_get_rssi(uhd); } else { rx_gain_offset = cuhd_get_rx_gain(uhd); } } // Plot and Printf if ((nframes%10) == 0) { printf("CFO: %+8.4f KHz, SFO: %+8.4f Khz, RSSI: %5.1f dBm, RSSI/ref-symbol: %+5.1f dBm, " "RSRP: %+5.1f dBm, RSRQ: %5.1f dB, SNR: %5.1f dB\r", srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000, 10*log10(rssi*1000) - rx_gain_offset, 10*log10(rssi_utra*1000)- rx_gain_offset, 10*log10(rsrp*1000) - rx_gain_offset, 10*log10(rsrq), 10*log10(snr)); if (srslte_verbose != SRSLTE_VERBOSE_NONE) { printf("\n"); } } break; } if (srslte_ue_sync_get_sfidx(&ue_sync) == 9) { sfn++; if (sfn == 1024) { sfn = 0; } } } else if (ret == 0) { printf("Finding PSS... Peak: %8.1f, FrameCnt: %d, State: %d\r", srslte_sync_get_peak_value(&ue_sync.sfind), ue_sync.frame_total_cnt, ue_sync.state); } sf_cnt++; } // Main loop srslte_ue_sync_free(&ue_sync); cuhd_close(uhd); printf("\nBye\n"); exit(0); }
int main(int argc, char **argv) { int ret; srslte_cell_t cell; srslte_ue_mib_t ue_mib; #ifndef DISABLE_RF srslte_rf_t rf; #endif int n; uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; int sfn_offset; uint32_t sfn_target = 0; uint32_t sf_target = 0; uint32_t ncce_target = 0; uint32_t L_target = 0; uint32_t cfi_target = 0; FILE *fid; uint16_t rnti_tmp; parse_args(&prog_args, argc, argv); /* If reading from file, go straight to PDSCH decoding. Otherwise, decode MIB first */ if (prog_args.input_file_name) { /* preset cell configuration */ cell.id = prog_args.file_cell_id; cell.cp = SRSLTE_CP_NORM; cell.phich_length = SRSLTE_PHICH_NORM; cell.phich_resources = SRSLTE_PHICH_R_1; cell.nof_ports = prog_args.file_nof_ports; cell.nof_prb = prog_args.file_nof_prb; if (srslte_ue_sync_init_file(&ue_sync, prog_args.file_nof_prb, prog_args.input_file_name, prog_args.file_offset_time, prog_args.file_offset_freq)) { fprintf(stderr, "Error initiating ue_sync\n"); exit(-1); } } if (srslte_ue_mib_init(&ue_mib, cell)) { fprintf(stderr, "Error initaiting UE MIB decoder\n"); exit(-1); } if (srslte_ue_dl_init(&ue_dl, cell)) { // This is the User RNTI fprintf(stderr, "Error initiating UE downlink processing module\n"); exit(-1); } /* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */ srslte_ue_dl_set_rnti(&ue_dl, prog_args.rnti); /* Initialize subframe counter */ if (prog_args.rnti_to_fix != NULL) { fid = fopen(prog_args.rnti_to_fix,"r"); for (int i=0;i<65536;i++) { if (fscanf(fid,"%d",&rnti_tmp) != EOF) { // if (rnti_tmp) printf("rnti %d val %d\n", i, rnti_tmp); srslte_ue_dl_reset_rnti_user_to(&ue_dl, i, rnti_tmp); // check this //printf("is rnti in the list? %d\n",rnti_in_list(&ue_dl, rnti_tmp)); } } fclose(fid); } ue_sync.correct_cfo = !prog_args.disable_cfo; srslte_pbch_decode_reset(&ue_mib.pbch); INFO("\nEntering main loop...\n\n", 0); /* Main loop */ ret = srslte_ue_sync_get_buffer(&ue_sync, &sf_buffer); if (ret < 0) { fprintf(stderr, "Error calling srslte_ue_sync_work()\n"); } if (ret == 7) { go_exit = true; } if (ret == 1) { if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) { n = srslte_ue_mib_decode(&ue_mib, sf_buffer, bch_payload, NULL, &sfn_offset); if (n < 0) { fprintf(stderr, "Error decoding UE MIB\n"); exit(-1); } else if (n == SRSLTE_UE_MIB_FOUND) { srslte_pbch_mib_unpack(bch_payload, &cell, &sfn); //srslte_cell_fprint(stdout, &cell, sfn); //printf("Decoded MIB. SFN: %d, offset: %d\n", sfn, sfn_offset); sfn = (sfn + sfn_offset)%1024; } } } // Main loop #define M_OFF 500 float tprob[M_OFF]; float bprob = 0; int b_offset = 0, b_offset2 = 0; int i, j, k; int t_offset, l_offset, m_offset = 30*ue_sync.sf_len/11520; uint16_t rnti_cand[M_OFF]; uint16_t rnti_cnt[M_OFF][2]; int rnti_off[M_OFF]; uint16_t bcnt = 0; float rnti_bprob[M_OFF]; int found = 0; fid = fopen(prog_args.to_fix,"r"); bzero(tprob, sizeof(tprob)); while (fscanf(fid,"%d %d %d %d %d",&sfn_target, &sf_target, &ncce_target, &L_target, &cfi_target) != EOF) { // printf("checking sfn %d sf %d, ncce %d, L %d \n",sfn_target,sf_target, ncce_target, L_target); bprob = 0; b_offset = 0; b_offset2 = 0; bcnt = 0; found = 0; if (sfn == sfn_target && sf_target == 0) { l_offset = 0; } else { srslte_filesource_seek(&ue_sync.file_source, ((sfn_target-sfn)*10+sf_target)*ue_sync.sf_len-m_offset); srslte_ue_sync_get_buffer(&ue_sync, &sf_buffer); l_offset = -m_offset; } for (i=0; i<m_offset+1; i++) { for (k=0; k<2 && !found; k++) { if ((i==0 && k==1) || (l_offset==0 && k==1)) { } else { if (k==0) t_offset = i; if (k==1) t_offset = -i; //printf("checking offset %d for sfn %d sf %d (%d.%d)\n",t_offset,sfn_target,sf_target,i,k); tprob[t_offset-l_offset] = srslte_ue_dl_fix_control_ra(&ue_dl, &sf_buffer[t_offset-l_offset], data, sf_target, 0, sfn_target, ncce_target, L_target, cfi_target, 0); rnti_cand[t_offset-l_offset] = ue_dl.current_rnti; rnti_cnt[t_offset-l_offset][0] = rnti_cand[t_offset-l_offset]; rnti_cnt[t_offset-l_offset][1] = 1; rnti_off[t_offset-l_offset] = t_offset; rnti_bprob[t_offset-l_offset] = tprob[t_offset-l_offset]; if ((tprob[t_offset-l_offset] >= 97 && tprob[t_offset-l_offset] <=101) || tprob[t_offset-l_offset] >= 197) { //printf("Early winner...\n"); srslte_ue_dl_fix_control_ra(&ue_dl, &sf_buffer[t_offset-l_offset], data, sf_target, 0, sfn_target, ncce_target, L_target, cfi_target, 1); found = 1; break; } for (j = 0; j < t_offset-l_offset; j++) { if (rnti_cnt[j][0] == rnti_cnt[t_offset-l_offset][0] && rnti_bprob[t_offset-l_offset] > 90) { rnti_cnt[j][1]++; //printf("at offset %d counting rnti %x cnt %d prob %.3f\n", t_offset, rnti_cnt[j][0], rnti_cnt[j][1], rnti_bprob[j]); if (rnti_bprob[j] < rnti_bprob[t_offset-l_offset]) { rnti_bprob[j] = rnti_bprob[t_offset-l_offset]; rnti_off[j] = t_offset; //printf("at offset %d updating rnti %x cnt %d prob %.3f\n", t_offset, rnti_cnt[j][0], rnti_cnt[j][1], rnti_bprob[j]); } } } } } } // for (t_offset = l_offset; t_offset < (m_offset+1); t_offset++) { // //printf("checking offset %d for sfn %d sf %d\n",t_offset,sfn_target,sf_target); // tprob[t_offset-l_offset] = srslte_ue_dl_fix_control_ra(&ue_dl, &sf_buffer[t_offset-l_offset], data, sf_target, 0, sfn_target, ncce_target, L_target, cfi_target, 0); // rnti_cand[t_offset-l_offset] = ue_dl.current_rnti; // rnti_cnt[t_offset-l_offset][0] = rnti_cand[t_offset-l_offset]; // rnti_cnt[t_offset-l_offset][1] = 1; // rnti_off[t_offset-l_offset] = t_offset; // rnti_bprob[t_offset-l_offset] = tprob[t_offset-l_offset]; // // if ((tprob[t_offset-l_offset] >= 97 && tprob[t_offset-l_offset] <=101) || tprob[t_offset-l_offset] >= 197) { // //printf("Early winner...\n"); // srslte_ue_dl_fix_control_ra(&ue_dl, &sf_buffer[t_offset-l_offset], data, sf_target, 0, sfn_target, ncce_target, L_target, cfi_target, 1); // found = 1; // break; // } // // for (j = 0; j < t_offset-l_offset; j++) { // if (rnti_cnt[j][0] == rnti_cnt[t_offset-l_offset][0] && rnti_bprob[t_offset-l_offset] > 90) { // rnti_cnt[j][1]++; // //printf("at offset %d counting rnti %x cnt %d prob %.3f\n", t_offset, rnti_cnt[j][0], rnti_cnt[j][1], rnti_bprob[j]); // if (rnti_bprob[j] < rnti_bprob[t_offset-l_offset]) { // rnti_bprob[j] = rnti_bprob[t_offset-l_offset]; // rnti_off[j] = t_offset; // //printf("at offset %d updating rnti %x cnt %d prob %.3f\n", t_offset, rnti_cnt[j][0], rnti_cnt[j][1], rnti_bprob[j]); // } // } // } // } if (found == 0) { for (j = 0; j < (m_offset*2+1); j++) { //if (rnti_cnt[j][1] > 1 && rnti_bprob[j] > 90) printf("entry %d, rnti %x cnt %d prob %.3f offset %d\n", j, rnti_cnt[j][0], rnti_cnt[j][1], rnti_bprob[j], rnti_off[j]); if (rnti_cnt[j][1] > bcnt) { bcnt = rnti_cnt[j][1]; b_offset = rnti_off[j]; } if (rnti_cnt[j][1] > 1 && rnti_bprob[j] > bprob) { bprob = rnti_bprob[j]; b_offset2 = rnti_off[j]; } } if (rnti_cand[b_offset-l_offset] == rnti_cand[b_offset2-l_offset]) { if (rnti_bprob[b_offset-l_offset] >= rnti_bprob[b_offset2-l_offset] && rnti_bprob[b_offset-l_offset] >= 97) { //printf("Most popular at offset %d...\n",b_offset); //srslte_filesource_seek(&ue_sync.file_source, ((sfn_target-sfn)*10+sf_target)*ue_sync.sf_len+b_offset); //srslte_ue_sync_get_buffer(&ue_sync, &sf_buffer); srslte_ue_dl_fix_control_ra(&ue_dl, &sf_buffer[b_offset-l_offset], data, sf_target, 0, sfn_target, ncce_target, L_target, cfi_target, 1); } else if (rnti_bprob[b_offset2-l_offset] >= 97) { //printf("Most likely not unique at offset %d...\n",b_offset2); //srslte_filesource_seek(&ue_sync.file_source, ((sfn_target-sfn)*10+sf_target)*ue_sync.sf_len+b_offset2); //srslte_ue_sync_get_buffer(&ue_sync, &sf_buffer); srslte_ue_dl_fix_control_ra(&ue_dl, &sf_buffer[b_offset2-l_offset], data, sf_target, 0, sfn_target, ncce_target, L_target, cfi_target, 1); } } else { //printf("Most popular at offset %d...\n",b_offset); //srslte_filesource_seek(&ue_sync.file_source, ((sfn_target-sfn)*10+sf_target)*ue_sync.sf_len+b_offset); //srslte_ue_sync_get_buffer(&ue_sync, &sf_buffer); if (rnti_bprob[b_offset-l_offset] >= 95) srslte_ue_dl_fix_control_ra(&ue_dl, &sf_buffer[b_offset-l_offset], data, sf_target, 0, sfn_target, ncce_target, L_target, cfi_target, 1); //printf("Most likely not unique at offset %d...\n",b_offset2); //srslte_filesource_seek(&ue_sync.file_source, ((sfn_target-sfn)*10+sf_target)*ue_sync.sf_len+b_offset2); //srslte_ue_sync_get_buffer(&ue_sync, &sf_buffer); if (rnti_bprob[b_offset2-l_offset] >= 95) srslte_ue_dl_fix_control_ra(&ue_dl, &sf_buffer[b_offset2-l_offset], data, sf_target, 0, sfn_target, ncce_target, L_target, cfi_target, 1); //if (rnti_bprob[b_offset2-l_offset] < 98 && rnti_bprob[b_offset-l_offset] < 98) printf("nothing found in %d.%d L=%d,%d,%d\n",sfn_target,sf_target,ncce_target, L_target, cfi_target); } } //if (sfn_target > 0) exit(0); } srslte_ue_dl_free(&ue_dl); srslte_ue_sync_free(&ue_sync); #ifndef DISABLE_RF if (!prog_args.input_file_name) { srslte_ue_mib_free(&ue_mib); srslte_rf_close(&rf); } #endif //printf("\nBye\n"); exit(0); }