/** * * \section COPYRIGHT * * Copyright 2013-2015 The srsLTE Developers. See the * COPYRIGHT file at the top-level directory of this distribution. * * \section LICENSE * * This file is part of the srsLTE library. * * srsLTE is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * srsLTE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * A copy of the GNU Affero General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. * */ #include #include "srslte/srslte.h" #include "srsapps/ue/phy/phch_common.h" namespace srslte { namespace ue { phch_common::phch_common() { params_db = NULL; log_h = NULL; radio_h = NULL; mac = NULL; sr_enabled = false; is_first_of_burst = true; is_first_tx = true; rar_grant_pending = false; } void phch_common::init(phy_params *_params, log *_log, radio *_radio, mac_interface_phy *_mac) { params_db = _params; log_h = _log; radio_h = _radio; mac = _mac; is_first_tx = true; } bool phch_common::ul_rnti_active(uint32_t tti) { if ((tti >= ul_rnti_start && ul_rnti_start >= 0 || ul_rnti_start < 0) && (tti < ul_rnti_end && ul_rnti_end >= 0 || ul_rnti_end < 0)) { return true; } else { return false; } } bool phch_common::dl_rnti_active(uint32_t tti) { if (((tti >= dl_rnti_start && dl_rnti_start >= 0) || dl_rnti_start < 0) && ((tti < dl_rnti_end && dl_rnti_end >= 0) || dl_rnti_end < 0)) { return true; } else { return false; } } // Unpack RAR grant as defined in Section 6.2 of 36.213 void phch_common::set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]) { srslte_dci_rar_grant_unpack(&rar_grant, grant_payload); rar_grant_pending = true; Info("Setting RAR grant: \n"); srslte_dci_rar_grant_fprint(stdout, &rar_grant); // PUSCH is at n+6 or n+7 and phch_worker assumes default delay of 4 ttis if (rar_grant.ul_delay) { rar_grant_tti = (tti + 3) % 10240; } else { rar_grant_tti = (tti + 2) % 10240; } } bool phch_common::get_pending_rar(uint32_t tti, srslte_dci_rar_grant_t *rar_grant_) { if (rar_grant_pending && (tti >= rar_grant_tti || (tti < 10 && rar_grant_pending > 10235))) { if (rar_grant_) { rar_grant_pending = false; memcpy(rar_grant_, &rar_grant, sizeof(srslte_dci_rar_grant_t)); } return true; } return false; } /* Common variables used by all phy workers */ uint16_t phch_common::get_ul_rnti(uint32_t tti) { if (ul_rnti_active(tti)) { return ul_rnti; } else { return 0; } } srslte_rnti_type_t phch_common::get_ul_rnti_type() { return ul_rnti_type; } void phch_common::set_ul_rnti(srslte_rnti_type_t type, uint16_t rnti_value, int tti_start, int tti_end) { ul_rnti = rnti_value; ul_rnti_type = type; ul_rnti_start = tti_start; ul_rnti_end = tti_end; } uint16_t phch_common::get_dl_rnti(uint32_t tti) { if (dl_rnti_active(tti)) { return dl_rnti; } else { return 0; } } srslte_rnti_type_t phch_common::get_dl_rnti_type() { return dl_rnti_type; } void phch_common::set_dl_rnti(srslte_rnti_type_t type, uint16_t rnti_value, int tti_start, int tti_end) { dl_rnti = rnti_value; dl_rnti_type = type; dl_rnti_start = tti_start; dl_rnti_end = tti_end; Debug("Set DL rnti: start=%d, end=%d, value=0x%x\n", tti_start, tti_end, rnti_value); } void phch_common::reset_pending_ack(uint32_t tti) { pending_ack[tti%10].enabled = false; } void phch_common::set_pending_ack(uint32_t tti, uint32_t I_lowest, uint32_t n_dmrs) { pending_ack[tti%10].enabled = true; pending_ack[tti%10].I_lowest = I_lowest; pending_ack[tti%10].n_dmrs = n_dmrs; Debug("Set pending ACK for tti=%d I_lowest=%d, n_dmrs=%d\n", tti, I_lowest, n_dmrs); } bool phch_common::get_pending_ack(uint32_t tti) { return get_pending_ack(tti, NULL, NULL); } bool phch_common::get_pending_ack(uint32_t tti, uint32_t *I_lowest, uint32_t *n_dmrs) { if (I_lowest) { *I_lowest = pending_ack[tti%10].I_lowest; } if (n_dmrs) { *n_dmrs = pending_ack[tti%10].n_dmrs; } return pending_ack[tti%10].enabled; } /* The transmisison of UL subframes must be in sequence. Each worker uses this function to indicate * that all processing is done and data is ready for transmission or there is no transmission at all (tx_enable). * In that case, the end of burst message will be send to the radio */ void phch_common::worker_end(uint32_t tti, bool tx_enable, cf_t *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) { pthread_mutex_lock(&tx_mutex); // Wait previous TTIs to be transmitted if (is_first_tx) { tx_tti_cnt = tti; is_first_tx = false; } else { while(tti != tx_tti_cnt) { pthread_cond_wait(&tx_cvar, &tx_mutex); } } if (tx_enable) { radio_h->tx(buffer, nof_samples, tx_time); is_first_of_burst = false; } else if (!is_first_of_burst) { radio_h->tx_end(); is_first_of_burst = true; } /* else do nothing, just update tti counter */ tx_tti_cnt = (tx_tti_cnt + 1) % 10240; pthread_cond_signal(&tx_cvar); pthread_mutex_unlock(&tx_mutex); } } }