diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 294606bb5..2713e2a6e 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -546,7 +546,10 @@ public: } phy_cfg_t; virtual void get_current_cell(srslte_cell_t *cell, uint32_t *current_earfcn = NULL) = 0; - virtual void get_config(phy_cfg_t *phy_cfg) = 0; + virtual uint32_t get_current_earfcn() = 0; + virtual uint32_t get_current_pci() = 0; + + virtual void get_config(phy_cfg_t *phy_cfg) = 0; virtual void set_config(phy_cfg_t *phy_cfg) = 0; virtual void set_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *dedicated) = 0; virtual void set_config_common(phy_cfg_common_t *common) = 0; diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index 0f8ae8074..d76397cf0 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -435,7 +435,9 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui } /* Compute RSRP for the channel estimates in this port */ - q->rsrp[rxant_id][port_id] = srslte_vec_avg_power_cf(q->pilot_recv_signal, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id)); + uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); + float energy = cabsf(srslte_vec_acc_cc(q->pilot_estimates, npilots)/npilots); + q->rsrp[rxant_id][port_id] = energy*energy; if (port_id == 0) { /* compute rssi only for port 0 */ q->rssi[rxant_id][port_id] = srslte_chest_dl_rssi(q, input, port_id); diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index 05edf31f9..adc2abdca 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -137,7 +137,10 @@ public: float get_pathloss_db(); uint32_t get_current_tti(); + void get_current_cell(srslte_cell_t *cell, uint32_t *current_earfcn = NULL); + uint32_t get_current_earfcn(); + uint32_t get_current_pci(); void start_plot(); diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 7b903f0d9..20b32477f 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -346,6 +346,27 @@ private: rrc_meas measurements; + // Cell selection/reselection functions/variables + typedef struct { + float Qrxlevmin; + float Qrxlevminoffset; + float Qqualmin; + float Qqualminoffset; + float s_intrasearchP; + float s_intrasearchQ; + float q_hyst; + float threshservinglow; + + } cell_resel_cfg_t; + + cell_resel_cfg_t cell_resel_cfg; + + float get_srxlev(float Qrxlevmeas); + float get_squal(float Qqualmeas); + void cell_reselection_eval(float rsrp, float rsrq); + + + // RLC interface void max_retx_attempted(); diff --git a/srsue/src/mac/mux.cc b/srsue/src/mac/mux.cc index d624d2d62..e6e136d2e 100644 --- a/srsue/src/mac/mux.cc +++ b/srsue/src/mac/mux.cc @@ -213,10 +213,8 @@ uint8_t* mux::pdu_get(uint8_t *payload, uint32_t pdu_sz, uint32_t tx_tti, uint32 for (uint32_t i=0;iget_buffer_state(lch[i].id); lch[i].sched_len = 0; - Info("lch[%d].buffer_len=%d\n",i,lch[i].buffer_len); } - // data from any Logical Channel, except data from UL-CCCH; // first only those with positive Bj for (uint32_t i=0;iinfo("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm, SNR=%.1f dB\n", - cnt, nof_subframes, sf_idx, - rsrp, snr); + cnt, nof_subframes, sf_idx, rsrp, snr); if (cnt >= nof_subframes) { return MEASURE_OK; @@ -1107,7 +1113,7 @@ void phch_recv::scell_recv::init(srslte::log *log_h) } srslte_sync_cp_en(&sync_find, false); srslte_sync_set_cfo_ema_alpha(&sync_find, 0.8); - srslte_sync_set_threshold(&sync_find, 2.0); + srslte_sync_set_threshold(&sync_find, 1.2); reset(); } @@ -1126,6 +1132,7 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, fprintf(stderr, "Error resizing sync\n"); return SRSLTE_ERROR; } + int nof_cells = 0; uint32_t peak_idx = 0; uint32_t sf_idx = 0; @@ -1143,7 +1150,9 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, if (current_cell.id%3 != n_id_2) { srslte_sync_set_N_id_2(&sync_find, n_id_2); - switch(srslte_sync_find(&sync_find, input_buffer, 0, &peak_idx)) { + srslte_sync_find_ret_t sync_res = srslte_sync_find(&sync_find, input_buffer, 0, &peak_idx); + + switch(sync_res) { case SRSLTE_SYNC_ERROR: return SRSLTE_ERROR; fprintf(stderr, "Error finding correlation peak\n"); @@ -1155,6 +1164,7 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, peak_idx, n_id_2, cell_id, sf_idx); found_cell.id = cell_id; + found_cell.nof_ports = 1; // Use port 0 only for measurement measure_p.set_cell(found_cell); offset = peak_idx-sf_len/2; @@ -1208,7 +1218,9 @@ void phch_recv::meas_reset() { int phch_recv::meas_start(uint32_t earfcn, int pci) { if (earfcn == current_earfcn) { worker_com->pcell_meas_enabled = true; - intra_freq_meas.add_cell(pci); + if (pci != (int) cell.id) { + intra_freq_meas.add_cell(pci); + } return 0; } else { Warning("INTRA: Inter-frequency measurements not supported (current EARFCN=%d, requested measurement for %d)\n", @@ -1331,7 +1343,7 @@ void phch_recv::intra_measure::run_thread() } if (running) { - Info("INTRA: Running intra-frequency measurement for %d cells\n", active_pci.size()); + Info("INTRA: Running intra-frequency measurements\n"); // Read 5 ms data from buffer srslte_ringbuffer_read(&ring_buffer, search_buffer, CAPTURE_LEN_SF*current_sflen*sizeof(cf_t)); diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 96949e94c..917c0b480 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -301,6 +301,18 @@ void phy::get_current_cell(srslte_cell_t *cell, uint32_t *current_earfcn) sf_recv.get_current_cell(cell, current_earfcn); } +uint32_t phy::get_current_pci() { + srslte_cell_t cell; + sf_recv.get_current_cell(&cell); + return cell.id; +} + +uint32_t phy::get_current_earfcn() { + uint32_t earfcn; + sf_recv.get_current_cell(NULL, &earfcn); + return earfcn; +} + void phy::prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm) { diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 45e030294..afa4bca96 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -255,6 +255,7 @@ void rrc::run_thread() { rrc_log->info("Leaving RRC_CONNECTED state\n"); drb_up = false; reestablishment_in_progress = false; + measurements.reset(); pdcp->reset(); rlc->reset(); phy->reset(); @@ -264,6 +265,11 @@ void rrc::run_thread() { mac->pcch_start_rx(); mac_timers->timer_get(t310)->stop(); mac_timers->timer_get(t311)->stop(); + + // Instruct PHY to measure serving cell for cell reselection + phy->meas_start(phy->get_current_earfcn(), phy->get_current_pci()); + + // Move to RRC_IDLE state = RRC_STATE_IDLE; break; default: @@ -460,7 +466,11 @@ void rrc::select_next_cell_in_plmn() { } void rrc::new_phy_meas(float rsrp, float rsrq, uint32_t tti, uint32_t earfcn, uint32_t pci) { - measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti); + if (state == RRC_STATE_CONNECTED) { + measurements.new_phy_meas(earfcn, pci, rsrp, rsrq, tti); + } else { + cell_reselection_eval(rsrp, rsrq); + } } void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { @@ -493,6 +503,7 @@ void rrc::cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) { cell.earfcn = earfcn; cell.has_valid_sib1 = false; cell.has_valid_sib2 = false; + cell.has_valid_sib3 = false; known_cells.push_back(cell); // save current cell @@ -532,8 +543,31 @@ void rrc::add_neighbour_cell(uint32_t earfcn, uint32_t pci, float rsrp) { known_cells.push_back(c); } +// Cell reselection in IDLE Section 5.2.4 of 36.304 +void rrc::cell_reselection_eval(float rsrp, float rsrq) +{ + // Intra-frequency cell-reselection criteria + + if (get_srxlev(rsrp) > cell_resel_cfg.s_intrasearchP && get_squal(rsrq) > cell_resel_cfg.s_intrasearchQ) { + // UE may not perform intra-frequency measurements + phy->meas_reset(); + } else { + // UE must start intra-frequency measurements + phy->meas_start(phy->get_current_earfcn(), -1); + } + + // TODO: Inter-frequency cell reselection +} +float rrc::get_srxlev(float Qrxlevmeas) { + // TODO: Do max power limitation + float Pcompensation = 0; + return Qrxlevmeas - (cell_resel_cfg.Qrxlevmin + cell_resel_cfg.Qrxlevminoffset) - Pcompensation; +} +float rrc::get_squal(float Qqualmeas) { + return Qqualmeas - (cell_resel_cfg.Qqualmin + cell_resel_cfg.Qqualminoffset); +} @@ -865,14 +899,11 @@ void rrc::ho_prepare() { mac->set_ho_rnti(mob_reconf.mob_ctrl_info.new_ue_id, mob_reconf.mob_ctrl_info.target_pci); apply_rr_config_common_dl(&mob_reconf.mob_ctrl_info.rr_cnfg_common); - uint32_t current_earfcn = 0; - phy->get_current_cell(NULL, ¤t_earfcn); - bool found = false; for (uint32_t i = 0; i < known_cells.size(); i++) { rrc_log->info("cell[%d]=%d:%d, cur_earfcn=%d\n", i, known_cells[i].earfcn, known_cells[i].phy_cell.id, current_cell->earfcn); - if (known_cells[i].earfcn == current_earfcn && + if (known_cells[i].earfcn == phy->get_current_earfcn() && known_cells[i].phy_cell.id == mob_reconf.mob_ctrl_info.target_pci) { rrc_log->info("Selecting new cell pci=%d\n", known_cells[i].phy_cell.id); if (!phy->cell_handover(known_cells[i].phy_cell)) { @@ -895,7 +926,7 @@ void rrc::ho_prepare() { } printf("ncc=%d\n", mob_reconf.sec_cnfg_ho.intra_lte.next_hop_chaining_count); - usim->generate_as_keys_ho(mob_reconf.mob_ctrl_info.target_pci, current_earfcn, + usim->generate_as_keys_ho(mob_reconf.mob_ctrl_info.target_pci, phy->get_current_earfcn(), k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo); pdcp->config_security(1, k_rrc_enc, k_rrc_int, cipher_algo, integ_algo); send_rrc_con_reconfig_complete(NULL); @@ -1094,6 +1125,8 @@ void rrc::handle_sib2() void rrc::handle_sib3() { rrc_log->info("SIB3 received\n"); + + } void rrc::handle_sib13() @@ -1591,8 +1624,8 @@ void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT sizeof(LIBLTE_RRC_UL_POWER_CONTROL_DEDICATED_STRUCT)); } else if (apply_defaults) { current_cfg->ul_pwr_ctrl_ded.p0_ue_pusch = 0; - current_cfg->ul_pwr_ctrl_ded.delta_mcs_en = LIBLTE_RRC_DELTA_MCS_ENABLED_EN0; - current_cfg->ul_pwr_ctrl_ded.accumulation_en = true; + current_cfg->ul_pwr_ctrl_ded.delta_mcs_en = LIBLTE_RRC_DELTA_MCS_ENABLED_EN0; + current_cfg->ul_pwr_ctrl_ded.accumulation_en = true; current_cfg->ul_pwr_ctrl_ded.p0_ue_pucch = 0; current_cfg->ul_pwr_ctrl_ded.p_srs_offset = 7; } @@ -1741,7 +1774,7 @@ void rrc::apply_mac_config_dedicated(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_cnfg default_cfg.time_alignment_timer = mac_cnfg->time_alignment_timer; } - // Setup MAC configuration + // Setup MAC configuration mac->set_config_main(&default_cfg); // Update UL HARQ config @@ -2099,7 +2132,7 @@ void rrc::rrc_meas::generate_report(uint32_t meas_id) report->pcell_rsrp_result = value_to_range(RSRP, pcell_measurement.ms[RSRP]); report->pcell_rsrq_result = value_to_range(RSRQ, pcell_measurement.ms[RSRQ]); - log_h->info("MEAS: Generate report MeasId=%d, rsrp=%f rsrq=%f\n", + log_h->console("MEAS: Generate report MeasId=%d, rsrp=%f rsrq=%f\n", report->meas_id, pcell_measurement.ms[RSRP], pcell_measurement.ms[RSRQ]); // TODO: report up to 8 best cells @@ -2189,16 +2222,14 @@ void rrc::rrc_meas::calculate_triggers(uint32_t tti) // Get serving cell if (active.size()) { - uint32_t current_earfcn = 0; - srslte_cell_t current_cell; - phy->get_current_cell(¤t_cell, ¤t_earfcn); - if (find_earfcn_cell(current_earfcn, current_cell.id, &serving_object, &serving_cell_idx)) { + if (find_earfcn_cell(phy->get_current_earfcn(), phy->get_current_pci(), &serving_object, &serving_cell_idx)) { Ofp = serving_object->q_offset; if (serving_cell_idx >= 0) { Ocp = serving_object->cells[serving_cell_idx].q_offset; } } else { - log_h->warning("Can't find current eafcn=%d, pci=%d in objects list. Using Ofp=0, Ocp=0\n", current_earfcn, current_cell.id); + log_h->warning("Can't find current eafcn=%d, pci=%d in objects list. Using Ofp=0, Ocp=0\n", + phy->get_current_earfcn(), phy->get_current_pci()); } }