Send PRACH from worker thread with zero time advance

This commit is contained in:
Ismael Gomez 2018-04-24 10:43:17 +02:00
parent e446c14214
commit ab7a0842ba
6 changed files with 129 additions and 125 deletions

View File

@ -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;

View File

@ -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;
};

View File

@ -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]);
}

View File

@ -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) {

View File

@ -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<nof_workers;i++) {
workers[i].reset();

View File

@ -75,7 +75,7 @@ void prach::init(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config_, uint32_t max_prb,
return;
}
srslte_cfo_set_tol(&cfo_h, 0);
signal_buffer = (cf_t *) srslte_vec_malloc(SRSLTE_PRACH_MAX_LEN * sizeof(cf_t));
signal_buffer = (cf_t *) srslte_vec_malloc(MAX_LEN_SF * 30720 * sizeof(cf_t));
if (!signal_buffer) {
perror("malloc");
return;
@ -159,10 +159,10 @@ bool prach::is_pending() {
bool prach::is_ready_to_send(uint32_t current_tti_) {
if (is_pending()) {
// consider the number of subframes the transmission must be anticipated
uint32_t current_tti = (current_tti_ + tx_advance_sf)%10240;
if (srslte_prach_tti_opportunity(&prach_obj, current_tti, allowed_subframe)) {
Debug("PRACH Buffer: Ready to send at tti: %d (now is %d)\n", current_tti, current_tti_);
transmitted_tti = current_tti;
uint32_t tti_tx = TTI_TX(current_tti_);
if (srslte_prach_tti_opportunity(&prach_obj, tti_tx, allowed_subframe)) {
Debug("PRACH Buffer: Ready to send at tti: %d (now is %d)\n", tti_tx, current_tti_);
transmitted_tti = tti_tx;
return true;
}
}
@ -173,55 +173,31 @@ int prach::tx_tti() {
return transmitted_tti;
}
float prach::get_p0_preamble()
{
return target_power_dbm;
}
cf_t *prach::generate(float cfo, uint32_t *nof_sf, float *target_power) {
if (cell_initiated && preamble_idx >= 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