diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index 53848905b..14687da73 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -53,6 +53,7 @@ public: cf_t* get_buffer(uint32_t antenna_idx); void set_tti(uint32_t tti, uint32_t tx_tti); void set_tx_time(srslte_timestamp_t tx_time, uint32_t next_offset); + void set_prach(cf_t *prach_ptr, float prach_power); void set_cfo(float cfo); void set_ul_params(bool pregen_disabled = false); @@ -169,6 +170,8 @@ private: bool sr_configured; float cfo; bool rar_cqi_request; + cf_t *prach_ptr; + float prach_power; uint32_t rssi_read_cnt; diff --git a/srsue/hdr/phy/prach.h b/srsue/hdr/phy/prach.h index 651203eb7..06d8f61cf 100644 --- a/srsue/hdr/phy/prach.h +++ b/srsue/hdr/phy/prach.h @@ -58,13 +58,11 @@ namespace srsue { bool is_ready_to_send(uint32_t current_tti); bool is_pending(); int tx_tti(); - - void send(srslte::radio* radio_handler, float cfo, float pathloss, srslte_timestamp_t rx_time); - float get_p0_preamble(); - - static const uint32_t tx_advance_sf = 4; // Number of subframes to advance transmission - - private: + cf_t* generate(float cfo, uint32_t *nof_sf, float *target_power = NULL); + + private: + + const static int MAX_LEN_SF = 3; LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config; phy_args_t *args; @@ -81,7 +79,7 @@ namespace srsue { srslte_cell_t cell; cf_t *signal_buffer; srslte_cfo_t cfo_h; - float target_power_dbm; + float target_power_dbm; }; diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 7cd7a7abe..12c113e24 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -367,6 +367,11 @@ void phch_recv::run_thread() dummy_buffer[i] = (cf_t*) malloc(sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100)); } + uint32_t prach_nof_sf = 0; + uint32_t prach_sf_cnt = 0; + cf_t *prach_ptr = NULL; + float prach_power = 0; + while (running) { Debug("SYNC: state=%s\n", phy_state.to_string()); @@ -423,40 +428,46 @@ void phch_recv::run_thread() metrics.sfo = srslte_ue_sync_get_sfo(&ue_sync); metrics.cfo = srslte_ue_sync_get_cfo(&ue_sync); - worker->set_cfo(get_tx_cfo()); worker_com->set_sync_metrics(metrics); - /* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */ - srslte_timestamp_t rx_time, tx_time, tx_time_prach; - srslte_ue_sync_get_last_timestamp(&ue_sync, &rx_time); - srslte_timestamp_copy(&tx_time, &rx_time); - srslte_timestamp_add(&tx_time, 0, HARQ_DELAY_MS*1e-3 - time_adv_sec); - worker->set_tx_time(tx_time, next_offset); - next_offset = 0; - - Debug("SYNC: Setting TTI=%d, tx_mutex=%d to worker %d\n", tti, tx_mutex_cnt, worker->get_id()); - worker->set_tti(tti, tx_mutex_cnt); - tx_mutex_cnt = (tx_mutex_cnt+1) % nof_tx_mutex; - - // Reset Uplink TX buffer to avoid mixing packets in TX queue - /* - if (prach_buffer->is_pending()) { - Info("SYNC: PRACH pending: Reset UL\n"); - radio_h->tx_end(); - }*/ - // Check if we need to TX a PRACH if (prach_buffer->is_ready_to_send(tti)) { - srslte_timestamp_copy(&tx_time_prach, &rx_time); - srslte_timestamp_add(&tx_time_prach, 0, prach::tx_advance_sf * 1e-3); - prach_buffer->send(radio_h, get_tx_cfo(), worker_com->pathloss, tx_time_prach); - radio_h->tx_end(); - worker_com->p0_preamble = prach_buffer->get_p0_preamble(); - worker_com->cur_radio_power = SRSLTE_MIN(SRSLTE_PC_MAX, worker_com->pathloss+worker_com->p0_preamble); + prach_ptr = prach_buffer->generate(get_tx_cfo(), &prach_nof_sf, &prach_power); + if (!prach_ptr) { + Error("Generating PRACH\n"); + } } + /* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */ + srslte_timestamp_t rx_time, tx_time; + srslte_ue_sync_get_last_timestamp(&ue_sync, &rx_time); + srslte_timestamp_copy(&tx_time, &rx_time); + if (prach_ptr) { + srslte_timestamp_add(&tx_time, 0, HARQ_DELAY_MS*1e-3); + } else { + srslte_timestamp_add(&tx_time, 0, HARQ_DELAY_MS*1e-3 - time_adv_sec); + } + + worker->set_prach(prach_ptr?&prach_ptr[prach_sf_cnt*SRSLTE_SF_LEN_PRB(cell.nof_prb)]:NULL, prach_power); + worker->set_cfo(get_tx_cfo()); + worker->set_tti(tti, tx_mutex_cnt); + worker->set_tx_time(tx_time, next_offset); + next_offset = 0; + tx_mutex_cnt = (tx_mutex_cnt+1) % nof_tx_mutex; + + // Advance/reset prach subframe pointer + if (prach_ptr) { + prach_sf_cnt++; + if (prach_sf_cnt == prach_nof_sf) { + prach_sf_cnt = 0; + prach_ptr = NULL; + } + } + + // Start worker workers_pool->start_worker(worker); + // Save signal for Intra-frequency measurement if ((tti%5) == 0 && worker_com->args->sic_pss_enabled) { srslte_pss_sic(&ue_sync.strack.pss, &buffer[0][SRSLTE_SF_LEN_PRB(cell.nof_prb)/2-ue_sync.strack.fft_size]); } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 300e264fc..8bdbe12e2 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -186,6 +186,11 @@ void phch_worker::set_tti(uint32_t tti_, uint32_t tx_tti_) log_phy_lib_h->step(tti); } +void phch_worker::set_prach(cf_t *prach_ptr, float prach_power) { + this->prach_ptr = prach_ptr; + this->prach_power = prach_power; +} + void phch_worker::set_cfo(float cfo_) { cfo = cfo_; @@ -319,60 +324,70 @@ void phch_worker::work_imp() /***** Uplink Processing + Transmission *******/ - - /* Generate SR if required*/ - set_uci_sr(); - /* Check if we have UL grant. ul_phy_grant will be overwritten by new grant */ - ul_grant_available = decode_pdcch_ul(&ul_mac_grant); + bool signal_ready = false; + cf_t *signal_ptr = NULL; - /* Generate CQI reports if required, note that in case both aperiodic - and periodic ones present, only aperiodic is sent (36.213 section 7.2) */ - if (ul_grant_available && ul_mac_grant.has_cqi_request) { - set_uci_aperiodic_cqi(); + /* Transmit PRACH if pending, or PUSCH/PUCCH otherwise */ + if (prach_ptr) { + signal_ready = true; + signal_ptr = prach_ptr; } else { - set_uci_periodic_cqi(); - } + /* Generate SR if required*/ + set_uci_sr(); - /* TTI offset for UL */ - ul_action.tti_offset = HARQ_DELAY_MS; + /* Check if we have UL grant. ul_phy_grant will be overwritten by new grant */ + ul_grant_available = decode_pdcch_ul(&ul_mac_grant); - /* Send UL grant or HARQ information (from PHICH) to MAC */ - if (ul_grant_available && ul_ack_available) { - phy->mac->new_grant_ul_ack(ul_mac_grant, ul_ack, &ul_action); - } else if (ul_grant_available && !ul_ack_available) { - phy->mac->new_grant_ul(ul_mac_grant, &ul_action); - } else if (!ul_grant_available && ul_ack_available) { - phy->mac->harq_recv(tti, ul_ack, &ul_action); - } - - /* Set UL CFO before transmission */ - srslte_ue_ul_set_cfo(&ue_ul, cfo); - - /* Transmit PUSCH, PUCCH or SRS */ - bool signal_ready = false; - if (ul_action.tx_enabled) { - encode_pusch(&ul_action.phy_grant.ul, ul_action.payload_ptr[0], ul_action.current_tx_nb, - &ul_action.softbuffers[0], ul_action.rv[0], ul_action.rnti, ul_mac_grant.is_from_rar); - signal_ready = true; - if (ul_action.expect_ack) { - phy->set_pending_ack(TTI_RX_ACK(tti), ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs); + /* Generate CQI reports if required, note that in case both aperiodic + and periodic ones present, only aperiodic is sent (36.213 section 7.2) */ + if (ul_grant_available && ul_mac_grant.has_cqi_request) { + set_uci_aperiodic_cqi(); + } else { + set_uci_periodic_cqi(); } - } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0 || uci_data.uci_ri_len > 0) { - encode_pucch(); - signal_ready = true; - } else if (srs_is_ready_to_send()) { - encode_srs(); - signal_ready = true; - } + /* TTI offset for UL */ + ul_action.tti_offset = HARQ_DELAY_MS; + + /* Send UL grant or HARQ information (from PHICH) to MAC */ + if (ul_grant_available && ul_ack_available) { + phy->mac->new_grant_ul_ack(ul_mac_grant, ul_ack, &ul_action); + } else if (ul_grant_available && !ul_ack_available) { + phy->mac->new_grant_ul(ul_mac_grant, &ul_action); + } else if (!ul_grant_available && ul_ack_available) { + phy->mac->harq_recv(tti, ul_ack, &ul_action); + } + + /* Set UL CFO before transmission */ + srslte_ue_ul_set_cfo(&ue_ul, cfo); + + /* Transmit PUSCH, PUCCH or SRS */ + if (ul_action.tx_enabled) { + encode_pusch(&ul_action.phy_grant.ul, ul_action.payload_ptr[0], ul_action.current_tx_nb, + &ul_action.softbuffers[0], ul_action.rv[0], ul_action.rnti, ul_mac_grant.is_from_rar); + signal_ready = true; + if (ul_action.expect_ack) { + phy->set_pending_ack(TTI_RX_ACK(tti), ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs); + } + + } else if (dl_action.generate_ack || uci_data.scheduling_request || uci_data.uci_cqi_len > 0 || uci_data.uci_ri_len > 0) { + encode_pucch(); + signal_ready = true; + } else if (srs_is_ready_to_send()) { + encode_srs(); + signal_ready = true; + } + signal_ptr = signal_buffer[0]; + } + tr_log_end(); if (next_offset > 0) { - phy->worker_end(tx_tti, signal_ready, signal_buffer[0], SRSLTE_SF_LEN_PRB(cell.nof_prb)+next_offset, tx_time); + phy->worker_end(tx_tti, signal_ready, signal_ptr, SRSLTE_SF_LEN_PRB(cell.nof_prb)+next_offset, tx_time); } else { - phy->worker_end(tx_tti, signal_ready, &signal_buffer[0][-next_offset], SRSLTE_SF_LEN_PRB(cell.nof_prb)+next_offset, tx_time); + phy->worker_end(tx_tti, signal_ready, &signal_ptr[-next_offset], SRSLTE_SF_LEN_PRB(cell.nof_prb)+next_offset, tx_time); } if (!dl_action.generate_ack_callback) { diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 875fc483c..eb1b87aa7 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -341,6 +341,7 @@ void phy::reset() { Info("Resetting PHY\n"); n_ta = 0; + sf_recv.set_time_adv_sec(0); pdcch_dl_search_reset(); for(uint32_t i=0;i= 0 && nof_sf) { -void prach::send(srslte::radio *radio_handler, float cfo, float pathloss, srslte_timestamp_t tx_time) -{ - - // Get current TX gain - float old_gain = radio_handler->get_tx_gain(); - - // Correct CFO before transmission FIXME: UL SISO Only - srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, cfo / srslte_symbol_sz(cell.nof_prb)); + // Correct CFO before transmission FIXME: UL SISO Only + srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, cfo / srslte_symbol_sz(cell.nof_prb)); - // If power control is enabled, choose amplitude and power - if (args->ul_pwr_ctrl_en) { - // Get PRACH transmission power - float tx_power = SRSLTE_MIN(SRSLTE_PC_MAX, pathloss + target_power_dbm); - - // Get output power for amplitude 1 - radio_handler->set_tx_power(tx_power); - - // Scale signal - float digital_power = srslte_vec_avg_power_cf(signal_buffer, len); - float scale = sqrtf(pow(10,tx_power/10)/digital_power); - - srslte_vec_sc_prod_cfc(signal_buffer, scale, signal_buffer, len); - log_h->console("PRACH: Pathloss=%.2f dB, Target power %.2f dBm, TX_power %.2f dBm, TX_gain %.1f dB, scale %.2f\n", - pathloss, target_power_dbm, tx_power, radio_handler->get_tx_gain(), scale); - - } else { - float prach_gain = args->prach_gain; - if (prach_gain > 0) { - radio_handler->set_tx_gain(prach_gain); + // pad guard symbols with zeros + uint32_t nsf = (len-1)/SRSLTE_SF_LEN_PRB(cell.nof_prb)+1; + bzero(&signal_buffer[len], (nsf*SRSLTE_SF_LEN_PRB(cell.nof_prb)-len)*sizeof(cf_t)); + + *nof_sf = nsf; + + if (target_power) { + *target_power = target_power_dbm; } - Debug("TX PRACH: Power control for PRACH is disabled, setting gain to %.0f dB\n", prach_gain); + + Info("PRACH: Transmitted preamble=%d, CFO=%.2f KHz, nof_sf=%d, target_power=%.1f dBm\n", + preamble_idx, cfo*15, nsf, target_power_dbm); + preamble_idx = -1; + + return signal_buffer; + } else { + return NULL; } - - void *tmp_buffer[SRSLTE_MAX_PORTS] = {signal_buffer, NULL, NULL, NULL}; - radio_handler->tx(tmp_buffer, len, tx_time); - radio_handler->tx_end(); - - Info("PRACH: Transmitted preamble=%d, CFO=%.2f KHz, tx_time=%f\n", - preamble_idx, cfo*15, tx_time.frac_secs); - preamble_idx = -1; - - radio_handler->set_tx_gain(old_gain); - Debug("Restoring TX gain to %.0f dB\n", old_gain); } } // namespace srsue