|
|
|
@ -176,16 +176,16 @@ cf_t* phch_worker::get_buffer_rx()
|
|
|
|
|
void phch_worker::set_time(uint32_t tti_, uint32_t tx_mutex_cnt_, srslte_timestamp_t tx_time_)
|
|
|
|
|
{
|
|
|
|
|
tti_rx = tti_;
|
|
|
|
|
tti_tx = HARQ_TX(tti_rx);
|
|
|
|
|
tti_sched_ul = HARQ_RX(tti_rx);
|
|
|
|
|
|
|
|
|
|
tti_tx_dl = TTI_TX(tti_rx);
|
|
|
|
|
tti_tx_ul = TTI_RX_ACK(tti_rx);
|
|
|
|
|
|
|
|
|
|
sf_rx = tti_rx%10;
|
|
|
|
|
sf_tx = tti_tx%10;
|
|
|
|
|
|
|
|
|
|
t_tx = TTIMOD(tti_tx);
|
|
|
|
|
sf_tx = tti_tx_dl%10;
|
|
|
|
|
|
|
|
|
|
t_tx_dl = TTIMOD(tti_tx_dl);
|
|
|
|
|
t_rx = TTIMOD(tti_rx);
|
|
|
|
|
t_sched_ul = TTIMOD(tti_sched_ul);
|
|
|
|
|
|
|
|
|
|
t_tx_ul = TTIMOD(tti_tx_ul);
|
|
|
|
|
|
|
|
|
|
tx_mutex_cnt = tx_mutex_cnt_;
|
|
|
|
|
memcpy(&tx_time, &tx_time_, sizeof(srslte_timestamp_t));
|
|
|
|
|
}
|
|
|
|
@ -194,16 +194,16 @@ int phch_worker::add_rnti(uint16_t rnti)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (srslte_enb_dl_add_rnti(&enb_dl, rnti)) {
|
|
|
|
|
return -1;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (srslte_enb_ul_add_rnti(&enb_ul, rnti)) {
|
|
|
|
|
return -1;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create user
|
|
|
|
|
ue_db[rnti].rnti = rnti;
|
|
|
|
|
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
// Create user
|
|
|
|
|
ue_db[rnti].rnti = rnti;
|
|
|
|
|
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -211,61 +211,61 @@ uint32_t phch_worker::get_nof_rnti() {
|
|
|
|
|
return ue_db.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void phch_worker::set_config_dedicated(uint16_t rnti,
|
|
|
|
|
srslte_uci_cfg_t *uci_cfg,
|
|
|
|
|
void phch_worker::set_config_dedicated(uint16_t rnti,
|
|
|
|
|
srslte_uci_cfg_t *uci_cfg,
|
|
|
|
|
srslte_pucch_sched_t *pucch_sched,
|
|
|
|
|
srslte_refsignal_srs_cfg_t *srs_cfg,
|
|
|
|
|
srslte_refsignal_srs_cfg_t *srs_cfg,
|
|
|
|
|
uint32_t I_sr, bool pucch_cqi, uint32_t pmi_idx, bool pucch_cqi_ack)
|
|
|
|
|
{
|
|
|
|
|
pthread_mutex_lock(&mutex);
|
|
|
|
|
pthread_mutex_lock(&mutex);
|
|
|
|
|
if (ue_db.count(rnti)) {
|
|
|
|
|
pucch_sched->N_pucch_1 = phy->pucch_cfg.n1_pucch_an;
|
|
|
|
|
srslte_enb_ul_cfg_ue(&enb_ul, rnti, uci_cfg, pucch_sched, srs_cfg);
|
|
|
|
|
|
|
|
|
|
ue_db[rnti].I_sr = I_sr;
|
|
|
|
|
|
|
|
|
|
ue_db[rnti].I_sr = I_sr;
|
|
|
|
|
ue_db[rnti].I_sr_en = true;
|
|
|
|
|
|
|
|
|
|
if (pucch_cqi) {
|
|
|
|
|
ue_db[rnti].pmi_idx = pmi_idx;
|
|
|
|
|
ue_db[rnti].cqi_en = true;
|
|
|
|
|
ue_db[rnti].pucch_cqi_ack = pucch_cqi_ack;
|
|
|
|
|
ue_db[rnti].pmi_idx = pmi_idx;
|
|
|
|
|
ue_db[rnti].cqi_en = true;
|
|
|
|
|
ue_db[rnti].pucch_cqi_ack = pucch_cqi_ack;
|
|
|
|
|
} else {
|
|
|
|
|
ue_db[rnti].pmi_idx = 0;
|
|
|
|
|
ue_db[rnti].cqi_en = false;
|
|
|
|
|
ue_db[rnti].pmi_idx = 0;
|
|
|
|
|
ue_db[rnti].cqi_en = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
Error("Setting config dedicated: rnti=0x%x does not exist\n");
|
|
|
|
|
}
|
|
|
|
|
pthread_mutex_unlock(&mutex);
|
|
|
|
|
pthread_mutex_unlock(&mutex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void phch_worker::rem_rnti(uint16_t rnti)
|
|
|
|
|
{
|
|
|
|
|
pthread_mutex_lock(&mutex);
|
|
|
|
|
pthread_mutex_lock(&mutex);
|
|
|
|
|
if (ue_db.count(rnti)) {
|
|
|
|
|
ue_db.erase(rnti);
|
|
|
|
|
|
|
|
|
|
srslte_enb_dl_rem_rnti(&enb_dl, rnti);
|
|
|
|
|
|
|
|
|
|
srslte_enb_dl_rem_rnti(&enb_dl, rnti);
|
|
|
|
|
srslte_enb_ul_rem_rnti(&enb_ul, rnti);
|
|
|
|
|
|
|
|
|
|
// remove any pending grant for each subframe
|
|
|
|
|
|
|
|
|
|
// remove any pending grant for each subframe
|
|
|
|
|
for (uint32_t i=0;i<TTIMOD_SZ;i++) {
|
|
|
|
|
for (uint32_t j=0;j<phy->ul_grants[i].nof_grants;j++) {
|
|
|
|
|
if (phy->ul_grants[i].sched_grants[j].rnti == rnti) {
|
|
|
|
|
phy->ul_grants[i].sched_grants[j].rnti = 0;
|
|
|
|
|
phy->ul_grants[i].sched_grants[j].rnti = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (uint32_t j=0;j<phy->dl_grants[i].nof_grants;j++) {
|
|
|
|
|
if (phy->dl_grants[i].sched_grants[j].rnti == rnti) {
|
|
|
|
|
phy->dl_grants[i].sched_grants[j].rnti = 0;
|
|
|
|
|
phy->dl_grants[i].sched_grants[j].rnti = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
Error("Removing user: rnti=0x%x does not exist\n", rnti);
|
|
|
|
|
}
|
|
|
|
|
pthread_mutex_unlock(&mutex);
|
|
|
|
|
pthread_mutex_unlock(&mutex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void phch_worker::work_imp()
|
|
|
|
@ -275,18 +275,18 @@ void phch_worker::work_imp()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pthread_mutex_lock(&mutex);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mac_interface_phy::ul_sched_t *ul_grants = phy->ul_grants;
|
|
|
|
|
mac_interface_phy::dl_sched_t *dl_grants = phy->dl_grants;
|
|
|
|
|
mac_interface_phy *mac = phy->mac;
|
|
|
|
|
|
|
|
|
|
mac_interface_phy::dl_sched_t *dl_grants = phy->dl_grants;
|
|
|
|
|
mac_interface_phy *mac = phy->mac;
|
|
|
|
|
|
|
|
|
|
log_h->step(tti_rx);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Debug("Worker %d running\n", get_id());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(std::map<uint16_t, ue>::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) {
|
|
|
|
|
uint16_t rnti = (uint16_t) iter->first;
|
|
|
|
|
ue_db[rnti].has_grant_tti = -1;
|
|
|
|
|
ue_db[rnti].has_grant_tti = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Process UL signal
|
|
|
|
@ -294,51 +294,51 @@ void phch_worker::work_imp()
|
|
|
|
|
|
|
|
|
|
// Decode pending UL grants for the tti they were scheduled
|
|
|
|
|
decode_pusch(ul_grants[t_rx].sched_grants, ul_grants[t_rx].nof_grants);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Decode remaining PUCCH ACKs not associated with PUSCH transmission and SR signals
|
|
|
|
|
decode_pucch();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Get DL scheduling for the TX TTI from MAC
|
|
|
|
|
if (mac->get_dl_sched(tti_tx, &dl_grants[t_tx]) < 0) {
|
|
|
|
|
if (mac->get_dl_sched(tti_tx_dl, &dl_grants[t_tx_dl]) < 0) {
|
|
|
|
|
Error("Getting DL scheduling from MAC\n");
|
|
|
|
|
goto unlock;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dl_grants[t_tx].cfi < 1 || dl_grants[t_tx].cfi > 3) {
|
|
|
|
|
Error("Invalid CFI=%d\n", dl_grants[t_tx].cfi);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dl_grants[t_tx_dl].cfi < 1 || dl_grants[t_tx_dl].cfi > 3) {
|
|
|
|
|
Error("Invalid CFI=%d\n", dl_grants[t_tx_dl].cfi);
|
|
|
|
|
goto unlock;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Get UL scheduling for the TX TTI from MAC
|
|
|
|
|
if (mac->get_ul_sched(tti_sched_ul, &ul_grants[t_sched_ul]) < 0) {
|
|
|
|
|
if (mac->get_ul_sched(tti_tx_ul, &ul_grants[t_tx_ul]) < 0) {
|
|
|
|
|
Error("Getting UL scheduling from MAC\n");
|
|
|
|
|
goto unlock;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Put base signals (references, PBCH, PCFICH and PSS/SSS) into the resource grid
|
|
|
|
|
srslte_enb_dl_clear_sf(&enb_dl);
|
|
|
|
|
srslte_enb_dl_set_cfi(&enb_dl, dl_grants[t_tx].cfi);
|
|
|
|
|
srslte_enb_dl_put_base(&enb_dl, tti_tx);
|
|
|
|
|
srslte_enb_dl_set_cfi(&enb_dl, dl_grants[t_tx_dl].cfi);
|
|
|
|
|
srslte_enb_dl_put_base(&enb_dl, tti_tx_dl);
|
|
|
|
|
|
|
|
|
|
// Put UL/DL grants to resource grid. PDSCH data will be encoded as well.
|
|
|
|
|
encode_pdcch_dl(dl_grants[t_tx_dl].sched_grants, dl_grants[t_tx_dl].nof_grants);
|
|
|
|
|
encode_pdcch_ul(ul_grants[t_tx_ul].sched_grants, ul_grants[t_tx_ul].nof_grants);
|
|
|
|
|
encode_pdsch(dl_grants[t_tx_dl].sched_grants, dl_grants[t_tx_dl].nof_grants);
|
|
|
|
|
|
|
|
|
|
// Put UL/DL grants to resource grid. PDSCH data will be encoded as well.
|
|
|
|
|
encode_pdcch_dl(dl_grants[t_tx].sched_grants, dl_grants[t_tx].nof_grants);
|
|
|
|
|
encode_pdcch_ul(ul_grants[t_sched_ul].sched_grants, ul_grants[t_sched_ul].nof_grants);
|
|
|
|
|
encode_pdsch(dl_grants[t_tx].sched_grants, dl_grants[t_tx].nof_grants);
|
|
|
|
|
|
|
|
|
|
// Put pending PHICH HARQ ACK/NACK indications into subframe
|
|
|
|
|
encode_phich(ul_grants[t_sched_ul].phich, ul_grants[t_sched_ul].nof_phich);
|
|
|
|
|
|
|
|
|
|
// Prepare for receive ACK for DL grants in t_tx+4
|
|
|
|
|
phy->ack_clear(TTIMOD(HARQ_TX(sf_tx)));
|
|
|
|
|
for (uint32_t i=0;i<dl_grants[t_tx].nof_grants;i++) {
|
|
|
|
|
encode_phich(ul_grants[t_tx_ul].phich, ul_grants[t_tx_ul].nof_phich);
|
|
|
|
|
|
|
|
|
|
// Prepare for receive ACK for DL grants in t_tx_dl+4
|
|
|
|
|
phy->ack_clear(TTIMOD(TTI_TX(t_tx_dl)));
|
|
|
|
|
for (uint32_t i=0;i<dl_grants[t_tx_dl].nof_grants;i++) {
|
|
|
|
|
// SI-RNTI and RAR-RNTI do not have ACK
|
|
|
|
|
if (dl_grants[t_tx].sched_grants[i].rnti >= SRSLTE_CRNTI_START && dl_grants[t_tx].sched_grants[i].rnti <= SRSLTE_CRNTI_END) {
|
|
|
|
|
phy->ack_set_pending(TTIMOD(HARQ_TX(sf_tx)), dl_grants[t_tx].sched_grants[i].rnti, dl_grants[t_tx].sched_grants[i].location.ncce);
|
|
|
|
|
if (dl_grants[t_tx_dl].sched_grants[i].rnti >= SRSLTE_CRNTI_START && dl_grants[t_tx_dl].sched_grants[i].rnti <= SRSLTE_CRNTI_END) {
|
|
|
|
|
phy->ack_set_pending(TTIMOD(TTI_TX(t_tx_dl)), dl_grants[t_tx_dl].sched_grants[i].rnti, dl_grants[t_tx_dl].sched_grants[i].location.ncce);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Generate signal and transmit
|
|
|
|
|
srslte_enb_dl_gen_signal(&enb_dl, signal_buffer_tx);
|
|
|
|
|
srslte_enb_dl_gen_signal(&enb_dl, signal_buffer_tx);
|
|
|
|
|
Debug("Sending to radio\n");
|
|
|
|
|
phy->worker_end(tx_mutex_cnt, signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time);
|
|
|
|
|
|
|
|
|
@ -347,35 +347,35 @@ void phch_worker::work_imp()
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_WRITE_FILE
|
|
|
|
|
if (tti_tx == 10) {
|
|
|
|
|
if (tti_tx_dl == 10) {
|
|
|
|
|
fclose(f);
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Tell the plotting thread to draw the plots */
|
|
|
|
|
#ifdef ENABLE_GUI
|
|
|
|
|
if ((int) get_id() == plot_worker_id) {
|
|
|
|
|
sem_post(&plot_sem);
|
|
|
|
|
sem_post(&plot_sem);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
unlock:
|
|
|
|
|
pthread_mutex_unlock(&mutex);
|
|
|
|
|
pthread_mutex_unlock(&mutex);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
|
|
|
|
|
{
|
|
|
|
|
srslte_uci_data_t uci_data;
|
|
|
|
|
srslte_uci_data_t uci_data;
|
|
|
|
|
bzero(&uci_data, sizeof(srslte_uci_data_t));
|
|
|
|
|
|
|
|
|
|
uint32_t wideband_cqi_value = 0;
|
|
|
|
|
|
|
|
|
|
uint32_t n_rb_ho = 0;
|
|
|
|
|
|
|
|
|
|
uint32_t wideband_cqi_value = 0;
|
|
|
|
|
|
|
|
|
|
uint32_t n_rb_ho = 0;
|
|
|
|
|
for (uint32_t i=0;i<nof_pusch;i++) {
|
|
|
|
|
uint16_t rnti = grants[i].rnti;
|
|
|
|
|
uint16_t rnti = grants[i].rnti;
|
|
|
|
|
if (rnti) {
|
|
|
|
|
|
|
|
|
|
#ifdef LOG_EXECTIME
|
|
|
|
@ -386,27 +386,27 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
|
|
|
|
|
|
|
|
|
|
// Get pending ACKs with an associated PUSCH transmission
|
|
|
|
|
if (phy->ack_is_pending(t_rx, rnti)) {
|
|
|
|
|
uci_data.uci_ack_len = 1;
|
|
|
|
|
uci_data.uci_ack_len = 1;
|
|
|
|
|
}
|
|
|
|
|
// Configure PUSCH CQI channel
|
|
|
|
|
// Configure PUSCH CQI channel
|
|
|
|
|
srslte_cqi_value_t cqi_value;
|
|
|
|
|
bool cqi_enabled = false;
|
|
|
|
|
bool cqi_enabled = false;
|
|
|
|
|
if (ue_db[rnti].cqi_en && srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) {
|
|
|
|
|
cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND;
|
|
|
|
|
cqi_enabled = true;
|
|
|
|
|
cqi_enabled = true;
|
|
|
|
|
} else if (grants[i].grant.cqi_request) {
|
|
|
|
|
cqi_value.type = SRSLTE_CQI_TYPE_SUBBAND_HL;
|
|
|
|
|
cqi_value.subband_hl.N = (phy->cell.nof_prb > 7) ? srslte_cqi_hl_get_no_subbands(phy->cell.nof_prb) : 0;
|
|
|
|
|
cqi_enabled = true;
|
|
|
|
|
cqi_enabled = true;
|
|
|
|
|
}
|
|
|
|
|
if (cqi_enabled) {
|
|
|
|
|
uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// mark this tti as having an ul grant to avoid pucch
|
|
|
|
|
ue_db[rnti].has_grant_tti = tti_rx;
|
|
|
|
|
|
|
|
|
|
srslte_ra_ul_grant_t phy_grant;
|
|
|
|
|
|
|
|
|
|
// mark this tti as having an ul grant to avoid pucch
|
|
|
|
|
ue_db[rnti].has_grant_tti = tti_rx;
|
|
|
|
|
|
|
|
|
|
srslte_ra_ul_grant_t phy_grant;
|
|
|
|
|
int res = -1;
|
|
|
|
|
if (!srslte_ra_ul_dci_to_grant(&grants[i].grant, enb_ul.cell.nof_prb, n_rb_ho, &phy_grant, tti_rx%8)) {
|
|
|
|
|
if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) {
|
|
|
|
@ -414,27 +414,27 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
|
|
|
|
|
}
|
|
|
|
|
phy_grant.Qm = SRSLTE_MIN(phy_grant.Qm, 4);
|
|
|
|
|
res = srslte_enb_ul_get_pusch(&enb_ul, &phy_grant, grants[i].softbuffer,
|
|
|
|
|
rnti, grants[i].rv_idx,
|
|
|
|
|
grants[i].current_tx_nb,
|
|
|
|
|
grants[i].data,
|
|
|
|
|
&uci_data,
|
|
|
|
|
rnti, grants[i].rv_idx,
|
|
|
|
|
grants[i].current_tx_nb,
|
|
|
|
|
grants[i].data,
|
|
|
|
|
&uci_data,
|
|
|
|
|
sf_rx);
|
|
|
|
|
} else {
|
|
|
|
|
Error("Computing PUSCH grant\n");
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef LOG_EXECTIME
|
|
|
|
|
gettimeofday(&t[2], NULL);
|
|
|
|
|
get_time_interval(t);
|
|
|
|
|
snprintf(timestr, 64, ", dec_time=%4d us", (int) t[0].tv_usec);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
bool crc_res = (res == 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool crc_res = (res == 0);
|
|
|
|
|
|
|
|
|
|
// Save PHICH scheduling for this user. Each user can have just 1 PUSCH grant per TTI
|
|
|
|
|
ue_db[rnti].phich_info.n_prb_lowest = enb_ul.pusch_cfg.grant.n_prb_tilde[0];
|
|
|
|
|
ue_db[rnti].phich_info.n_dmrs = phy_grant.ncs_dmrs;
|
|
|
|
|
ue_db[rnti].phich_info.n_prb_lowest = enb_ul.pusch_cfg.grant.n_prb_tilde[0];
|
|
|
|
|
ue_db[rnti].phich_info.n_dmrs = phy_grant.ncs_dmrs;
|
|
|
|
|
|
|
|
|
|
char cqi_str[64];
|
|
|
|
|
if (cqi_enabled) {
|
|
|
|
@ -446,8 +446,8 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
|
|
|
|
|
}
|
|
|
|
|
snprintf(cqi_str, 64, ", cqi=%d", wideband_cqi_value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float snr_db = 10*log10(srslte_chest_ul_get_snr(&enb_ul.chest));
|
|
|
|
|
|
|
|
|
|
float snr_db = 10*log10(srslte_chest_ul_get_snr(&enb_ul.chest));
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
if (!crc_res && enb_ul.pusch_cfg.grant.L_prb == 1 && enb_ul.pusch_cfg.grant.n_prb[0] == 0 && snr_db > 5) {
|
|
|
|
@ -456,8 +456,8 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
|
|
|
|
|
srslte_vec_save_file("d", enb_ul.pusch.d, sizeof(cf_t)*enb_ul.pusch_cfg.nbits.nof_re);
|
|
|
|
|
srslte_vec_save_file("ce2", enb_ul.pusch.ce, sizeof(cf_t)*enb_ul.pusch_cfg.nbits.nof_re);
|
|
|
|
|
srslte_vec_save_file("z", enb_ul.pusch.z, sizeof(cf_t)*enb_ul.pusch_cfg.nbits.nof_re);
|
|
|
|
|
printf("saved sf_idx=%d, mcs=%d, tbs=%d, rnti=%d, rv=%d, snr=%.1f\n", tti%10,
|
|
|
|
|
grants[i].grant.mcs_idx, enb_ul.pusch_cfg.cb_segm.tbs, rnti, grants[i].rv_idx, snr_db);
|
|
|
|
|
printf("saved sf_idx=%d, mcs=%d, tbs=%d, rnti=%d, rv=%d, snr=%.1f\n", tti%10,
|
|
|
|
|
grants[i].grant.mcs_idx, enb_ul.pusch_cfg.cb_segm.tbs, rnti, grants[i].rv_idx, snr_db);
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
@ -465,120 +465,121 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch)
|
|
|
|
|
"PUSCH: rnti=0x%x, prb=(%d,%d), tbs=%d, mcs=%d, rv=%d, snr=%.1f dB, n_iter=%d, crc=%s%s%s%s\n",
|
|
|
|
|
rnti, phy_grant.n_prb[0], phy_grant.n_prb[0]+phy_grant.L_prb,
|
|
|
|
|
phy_grant.mcs.tbs/8, phy_grant.mcs.idx, grants[i].grant.rv_idx,
|
|
|
|
|
snr_db,
|
|
|
|
|
snr_db,
|
|
|
|
|
srslte_pusch_last_noi(&enb_ul.pusch),
|
|
|
|
|
crc_res?"OK":"KO",
|
|
|
|
|
uci_data.uci_ack_len>0?(uci_data.uci_ack?", ack=1":", ack=0"):"",
|
|
|
|
|
uci_data.uci_cqi_len>0?cqi_str:"",
|
|
|
|
|
timestr);
|
|
|
|
|
|
|
|
|
|
// Notify MAC of RL status
|
|
|
|
|
uci_data.uci_cqi_len>0?cqi_str:"",
|
|
|
|
|
timestr);
|
|
|
|
|
|
|
|
|
|
// Notify MAC of RL status
|
|
|
|
|
if (grants[i].grant.rv_idx == 0) {
|
|
|
|
|
if (res && snr_db < PUSCH_RL_SNR_DB_TH) {
|
|
|
|
|
Debug("PUSCH: Radio-Link failure snr=%.1f dB\n", snr_db);
|
|
|
|
|
phy->mac->rl_failure(rnti);
|
|
|
|
|
} else {
|
|
|
|
|
phy->mac->rl_ok(rnti);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Notify MAC new received data and HARQ Indication value
|
|
|
|
|
phy->mac->crc_info(tti_rx, rnti, phy_grant.mcs.tbs/8, crc_res);
|
|
|
|
|
phy->mac->crc_info(tti_rx, rnti, phy_grant.mcs.tbs/8, crc_res);
|
|
|
|
|
if (uci_data.uci_ack_len) {
|
|
|
|
|
phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (crc_res || snr_db > PUSCH_RL_SNR_DB_TH));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Notify MAC of UL SNR and DL CQI
|
|
|
|
|
|
|
|
|
|
// Notify MAC of UL SNR and DL CQI
|
|
|
|
|
if (snr_db >= PUSCH_RL_SNR_DB_TH) {
|
|
|
|
|
phy->mac->snr_info(tti_rx, rnti, snr_db);
|
|
|
|
|
}
|
|
|
|
|
if (uci_data.uci_cqi_len>0 && crc_res) {
|
|
|
|
|
phy->mac->cqi_info(tti_rx, rnti, wideband_cqi_value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Save metrics stats
|
|
|
|
|
|
|
|
|
|
// Save metrics stats
|
|
|
|
|
ue_db[rnti].metrics_ul(phy_grant.mcs.idx, 0, snr_db, srslte_pusch_last_noi(&enb_ul.pusch));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int phch_worker::decode_pucch()
|
|
|
|
|
{
|
|
|
|
|
srslte_uci_data_t uci_data;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(std::map<uint16_t, ue>::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) {
|
|
|
|
|
uint16_t rnti = (uint16_t) iter->first;
|
|
|
|
|
|
|
|
|
|
if (rnti >= SRSLTE_CRNTI_START && rnti <= SRSLTE_CRNTI_END && ue_db[rnti].has_grant_tti != (int) tti_rx) {
|
|
|
|
|
// Check if user needs to receive PUCCH
|
|
|
|
|
bool needs_pucch = false, needs_ack=false, needs_sr=false, needs_cqi=false;
|
|
|
|
|
// Check if user needs to receive PUCCH
|
|
|
|
|
bool needs_pucch = false, needs_ack=false, needs_sr=false, needs_cqi=false;
|
|
|
|
|
uint32_t last_n_pdcch = 0;
|
|
|
|
|
bzero(&uci_data, sizeof(srslte_uci_data_t));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ue_db[rnti].I_sr_en) {
|
|
|
|
|
if (srslte_ue_ul_sr_send_tti(ue_db[rnti].I_sr, tti_rx)) {
|
|
|
|
|
needs_pucch = true;
|
|
|
|
|
needs_sr = true;
|
|
|
|
|
uci_data.scheduling_request = true;
|
|
|
|
|
needs_pucch = true;
|
|
|
|
|
needs_sr = true;
|
|
|
|
|
uci_data.scheduling_request = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (phy->ack_is_pending(t_rx, rnti, &last_n_pdcch)) {
|
|
|
|
|
needs_pucch = true;
|
|
|
|
|
needs_ack = true;
|
|
|
|
|
uci_data.uci_ack_len = 1;
|
|
|
|
|
needs_pucch = true;
|
|
|
|
|
needs_ack = true;
|
|
|
|
|
uci_data.uci_ack_len = 1;
|
|
|
|
|
}
|
|
|
|
|
srslte_cqi_value_t cqi_value;
|
|
|
|
|
if (ue_db[rnti].cqi_en && (ue_db[rnti].pucch_cqi_ack || !needs_ack)) {
|
|
|
|
|
if (srslte_cqi_send(ue_db[rnti].pmi_idx, tti_rx)) {
|
|
|
|
|
needs_pucch = true;
|
|
|
|
|
needs_cqi = true;
|
|
|
|
|
cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND;
|
|
|
|
|
needs_pucch = true;
|
|
|
|
|
needs_cqi = true;
|
|
|
|
|
cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND;
|
|
|
|
|
uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (needs_pucch) {
|
|
|
|
|
if (srslte_enb_ul_get_pucch(&enb_ul, rnti, last_n_pdcch, t_rx, &uci_data)) {
|
|
|
|
|
if (srslte_enb_ul_get_pucch(&enb_ul, rnti, last_n_pdcch, sf_rx, &uci_data)) {
|
|
|
|
|
fprintf(stderr, "Error getting PUCCH\n");
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
if (uci_data.uci_ack_len > 0) {
|
|
|
|
|
phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (srslte_pucch_get_last_corr(&enb_ul.pucch) >= PUCCH_RL_CORR_TH));
|
|
|
|
|
phy->mac->ack_info(tti_rx, rnti, uci_data.uci_ack && (srslte_pucch_get_last_corr(&enb_ul.pucch) >= PUCCH_RL_CORR_TH));
|
|
|
|
|
}
|
|
|
|
|
if (uci_data.scheduling_request) {
|
|
|
|
|
phy->mac->sr_detected(tti_rx, rnti);
|
|
|
|
|
phy->mac->sr_detected(tti_rx, rnti);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char cqi_str[64];
|
|
|
|
|
if (uci_data.uci_cqi_len) {
|
|
|
|
|
srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value);
|
|
|
|
|
phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi);
|
|
|
|
|
sprintf(cqi_str, ", cqi=%d", cqi_value.wideband.wideband_cqi);
|
|
|
|
|
}
|
|
|
|
|
log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s\n",
|
|
|
|
|
rnti,
|
|
|
|
|
log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s\n",
|
|
|
|
|
rnti,
|
|
|
|
|
srslte_pucch_get_last_corr(&enb_ul.pucch),
|
|
|
|
|
enb_ul.pucch.last_n_pucch, enb_ul.pucch.last_n_prb,
|
|
|
|
|
needs_ack?(uci_data.uci_ack?", ack=1":", ack=0"):"",
|
|
|
|
|
needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"",
|
|
|
|
|
needs_cqi?cqi_str:"");
|
|
|
|
|
needs_ack?(uci_data.uci_ack?", ack=1":", ack=0"):"",
|
|
|
|
|
needs_sr?(uci_data.scheduling_request?", sr=yes":", sr=no"):"",
|
|
|
|
|
needs_cqi?cqi_str:"");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Notify MAC of RL status
|
|
|
|
|
// Notify MAC of RL status
|
|
|
|
|
if (!needs_sr) {
|
|
|
|
|
if (srslte_pucch_get_last_corr(&enb_ul.pucch) < PUCCH_RL_CORR_TH) {
|
|
|
|
|
Debug("PUCCH: Radio-Link failure corr=%.1f\n", srslte_pucch_get_last_corr(&enb_ul.pucch));
|
|
|
|
|
phy->mac->rl_failure(rnti);
|
|
|
|
|
} else {
|
|
|
|
|
phy->mac->rl_ok(rnti);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -587,15 +588,15 @@ int phch_worker::encode_phich(srslte_enb_dl_phich_t *acks, uint32_t nof_acks)
|
|
|
|
|
for (uint32_t i=0;i<nof_acks;i++) {
|
|
|
|
|
uint16_t rnti = acks[i].rnti;
|
|
|
|
|
if (rnti) {
|
|
|
|
|
srslte_enb_dl_put_phich(&enb_dl, acks[i].ack,
|
|
|
|
|
ue_db[rnti].phich_info.n_prb_lowest,
|
|
|
|
|
ue_db[rnti].phich_info.n_dmrs,
|
|
|
|
|
srslte_enb_dl_put_phich(&enb_dl, acks[i].ack,
|
|
|
|
|
ue_db[rnti].phich_info.n_prb_lowest,
|
|
|
|
|
ue_db[rnti].phich_info.n_dmrs,
|
|
|
|
|
sf_tx);
|
|
|
|
|
|
|
|
|
|
Info("PHICH: rnti=0x%x, hi=%d, I_lowest=%d, n_dmrs=%d, tti_tx=%d\n",
|
|
|
|
|
rnti, acks[i].ack,
|
|
|
|
|
ue_db[rnti].phich_info.n_prb_lowest,
|
|
|
|
|
ue_db[rnti].phich_info.n_dmrs, tti_tx);
|
|
|
|
|
|
|
|
|
|
Info("PHICH: rnti=0x%x, hi=%d, I_lowest=%d, n_dmrs=%d, tti_tx_dl=%d\n",
|
|
|
|
|
rnti, acks[i].ack,
|
|
|
|
|
ue_db[rnti].phich_info.n_prb_lowest,
|
|
|
|
|
ue_db[rnti].phich_info.n_dmrs, tti_tx_dl);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
@ -609,14 +610,14 @@ int phch_worker::encode_pdcch_ul(srslte_enb_ul_pusch_t *grants, uint32_t nof_gra
|
|
|
|
|
if (grants[i].needs_pdcch && rnti) {
|
|
|
|
|
if (srslte_enb_dl_put_pdcch_ul(&enb_dl, &grants[i].grant, grants[i].location, rnti, sf_tx)) {
|
|
|
|
|
fprintf(stderr, "Error putting PUSCH %d\n",i);
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Info("PDCCH: UL DCI Format0 rnti=0x%x, cce_index=%d, L=%d, tpc=%d, tti_tx=%d\n",
|
|
|
|
|
rnti, grants[i].location.ncce, (1<<grants[i].location.L), grants[i].grant.tpc_pusch, tti_tx);
|
|
|
|
|
Info("PDCCH: UL DCI Format0 rnti=0x%x, cce_index=%d, L=%d, tpc=%d, tti_tx_dl=%d\n",
|
|
|
|
|
rnti, grants[i].location.ncce, (1<<grants[i].location.L), grants[i].grant.tpc_pusch, tti_tx_dl);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants)
|
|
|
|
@ -624,28 +625,28 @@ int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_gra
|
|
|
|
|
for (uint32_t i=0;i<nof_grants;i++) {
|
|
|
|
|
uint16_t rnti = grants[i].rnti;
|
|
|
|
|
if (rnti) {
|
|
|
|
|
srslte_dci_format_t format = SRSLTE_DCI_FORMAT1;
|
|
|
|
|
srslte_dci_format_t format = SRSLTE_DCI_FORMAT1;
|
|
|
|
|
switch(grants[i].grant.alloc_type) {
|
|
|
|
|
case SRSLTE_RA_ALLOC_TYPE0:
|
|
|
|
|
case SRSLTE_RA_ALLOC_TYPE1:
|
|
|
|
|
format = SRSLTE_DCI_FORMAT1;
|
|
|
|
|
format = SRSLTE_DCI_FORMAT1;
|
|
|
|
|
break;
|
|
|
|
|
case SRSLTE_RA_ALLOC_TYPE2:
|
|
|
|
|
format = SRSLTE_DCI_FORMAT1A;
|
|
|
|
|
format = SRSLTE_DCI_FORMAT1A;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, format, grants[i].location, rnti, sf_tx)) {
|
|
|
|
|
fprintf(stderr, "Error putting PDCCH %d\n",i);
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LOG_THIS(rnti)) {
|
|
|
|
|
Info("PDCCH: DL DCI %s rnti=0x%x, cce_index=%d, L=%d, tti_tx=%d\n", srslte_dci_format_string(format),
|
|
|
|
|
rnti, grants[i].location.ncce, (1<<grants[i].location.L), tti_tx);
|
|
|
|
|
Info("PDCCH: DL DCI %s rnti=0x%x, cce_index=%d, L=%d, tti_tx_dl=%d\n", srslte_dci_format_string(format),
|
|
|
|
|
rnti, grants[i].location.ncce, (1<<grants[i].location.L), tti_tx_dl);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants)
|
|
|
|
@ -654,14 +655,14 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
|
|
|
|
|
uint16_t rnti = grants[i].rnti;
|
|
|
|
|
if (rnti) {
|
|
|
|
|
|
|
|
|
|
bool rnti_is_user = true;
|
|
|
|
|
bool rnti_is_user = true;
|
|
|
|
|
if (rnti == SRSLTE_SIRNTI || rnti == SRSLTE_PRNTI || rnti == SRSLTE_MRNTI) {
|
|
|
|
|
rnti_is_user = false;
|
|
|
|
|
rnti_is_user = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
srslte_ra_dl_grant_t phy_grant;
|
|
|
|
|
|
|
|
|
|
srslte_ra_dl_grant_t phy_grant;
|
|
|
|
|
srslte_ra_dl_dci_to_grant(&grants[i].grant, enb_dl.cell.nof_prb, rnti, &phy_grant);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char grant_str[64];
|
|
|
|
|
switch(grants[i].grant.alloc_type) {
|
|
|
|
|
case SRSLTE_RA_ALLOC_TYPE0:
|
|
|
|
@ -674,19 +675,19 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
|
|
|
|
|
sprintf(grant_str, "rb_start=%d",grants[i].grant.type2_alloc.RB_start);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LOG_THIS(rnti)) {
|
|
|
|
|
|
|
|
|
|
if (LOG_THIS(rnti)) {
|
|
|
|
|
uint8_t x = 0;
|
|
|
|
|
uint8_t *ptr = grants[i].data;
|
|
|
|
|
uint32_t len = phy_grant.mcs[0].tbs / (uint32_t) 8;
|
|
|
|
|
if (!ptr) {
|
|
|
|
|
if (!ptr) {
|
|
|
|
|
ptr = &x;
|
|
|
|
|
len = 1;
|
|
|
|
|
}
|
|
|
|
|
len = 1;
|
|
|
|
|
}
|
|
|
|
|
log_h->info_hex(ptr, len,
|
|
|
|
|
"PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx=%d\n",
|
|
|
|
|
rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process,
|
|
|
|
|
phy_grant.mcs[0].tbs/8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx);
|
|
|
|
|
"PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx_dl=%d\n",
|
|
|
|
|
rnti, phy_grant.nof_prb, grant_str, grants[i].grant.harq_process,
|
|
|
|
|
phy_grant.mcs[0].tbs/8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx_dl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
srslte_softbuffer_tx_t *sb[SRSLTE_MAX_CODEWORDS] = {grants[i].softbuffer, NULL};
|
|
|
|
|