diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 6050babeb..6f9db923a 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -65,6 +65,7 @@ public: virtual int rach_detected(uint32_t tti, uint32_t preamble_idx, uint32_t time_adv) = 0; virtual int ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value) = 0; + virtual int pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value) = 0; virtual int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) = 0; virtual int snr_info(uint32_t tti, uint16_t rnti, float snr_db) = 0; virtual int ack_info(uint32_t tti, uint16_t rnti, bool ack) = 0; @@ -113,6 +114,7 @@ public: /* Manages UE bearers and associated configuration */ virtual int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t *cfg) = 0; virtual int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) = 0; + virtual int set_dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info) = 0; virtual void phy_config_enabled(uint16_t rnti, bool enabled) = 0; }; diff --git a/lib/include/srslte/interfaces/sched_interface.h b/lib/include/srslte/interfaces/sched_interface.h index 7a375e16e..5e4b68acf 100644 --- a/lib/include/srslte/interfaces/sched_interface.h +++ b/lib/include/srslte/interfaces/sched_interface.h @@ -131,9 +131,10 @@ public: typedef struct { uint32_t rnti; + srslte_dci_format_t dci_format; srslte_ra_dl_dci_t dci; srslte_dci_location_t dci_location; - uint32_t tbs; + uint32_t tbs[SRSLTE_MAX_TB]; bool mac_ce_ta; bool mac_ce_rnti; uint32_t nof_pdu_elems; @@ -228,6 +229,7 @@ public: virtual int dl_ack_info(uint32_t tti, uint16_t rnti, bool ack) = 0; virtual int dl_rach_info(uint32_t tti, uint32_t ra_id, uint16_t rnti, uint32_t estimated_size) = 0; virtual int dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value) = 0; + virtual int dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value) = 0; virtual int dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) = 0; /* UL information */ diff --git a/lib/include/srslte/phy/enb/enb_dl.h b/lib/include/srslte/phy/enb/enb_dl.h index b63cb6416..581b98e23 100644 --- a/lib/include/srslte/phy/enb/enb_dl.h +++ b/lib/include/srslte/phy/enb/enb_dl.h @@ -95,6 +95,7 @@ typedef struct SRSLTE_API { typedef struct { uint16_t rnti; + srslte_dci_format_t dci_format; srslte_ra_dl_dci_t grant; srslte_dci_location_t location; srslte_softbuffer_tx_t *softbuffers[SRSLTE_MAX_TB]; @@ -162,8 +163,7 @@ SRSLTE_API int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, int rv_idx[SRSLTE_MAX_CODEWORDS], uint32_t sf_idx, uint8_t *data[SRSLTE_MAX_CODEWORDS], - srslte_mimo_type_t mimo_type, - uint32_t pmi); + srslte_mimo_type_t mimo_type); SRSLTE_API int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q, srslte_ra_dl_dci_t *grant, diff --git a/lib/src/phy/enb/enb_dl.c b/lib/src/phy/enb/enb_dl.c index d0db1f553..b845b4c8a 100644 --- a/lib/src/phy/enb/enb_dl.c +++ b/lib/src/phy/enb/enb_dl.c @@ -326,8 +326,30 @@ int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q, srslte_ra_ul_dci_t *grant, int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, srslte_ra_dl_grant_t *grant, srslte_softbuffer_tx_t *softbuffer[SRSLTE_MAX_CODEWORDS], uint16_t rnti, int rv_idx[SRSLTE_MAX_CODEWORDS], uint32_t sf_idx, - uint8_t *data[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type, uint32_t pmi) + uint8_t *data[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type) { + uint32_t pmi = 0; + uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant); + + /* Translates Precoding Information (pinfo) to Precoding matrix Index (pmi) as 3GPP 36.212 Table 5.3.3.1.5-4 */ + if (mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) { + if (nof_tb == 1) { + if (grant->pinfo > 0 && grant->pinfo < 5) { + pmi = grant->pinfo - 1; + } else { + ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo); + return SRSLTE_ERROR; + } + } else { + if (grant->pinfo < 2) { + pmi = grant->pinfo; + } else { + ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo); + return SRSLTE_ERROR; + } + } + } + /* Configure pdsch_cfg parameters */ if (srslte_pdsch_cfg_mimo(&q->pdsch_cfg, q->cell, grant, q->cfi, sf_idx, rv_idx, mimo_type, pmi)) { fprintf(stderr, "Error configuring PDSCH\n"); diff --git a/lib/src/phy/enb/enb_ul.c b/lib/src/phy/enb/enb_ul.c index b669b31e1..c9c557a02 100644 --- a/lib/src/phy/enb/enb_ul.c +++ b/lib/src/phy/enb/enb_ul.c @@ -323,9 +323,17 @@ int srslte_enb_ul_get_pucch(srslte_enb_ul_t *q, uint16_t rnti, memcpy(uci_data->uci_cqi, pucch_bits, uci_data->uci_cqi_len*sizeof(uint8_t)); } + if (uci_data->uci_dif_cqi_len) { + memcpy(uci_data->uci_dif_cqi, pucch_bits + uci_data->uci_cqi_len, uci_data->uci_dif_cqi_len*sizeof(uint8_t)); + } + + if (uci_data->uci_pmi_len) { + memcpy(uci_data->uci_pmi, pucch_bits + uci_data->uci_cqi_len + uci_data->uci_dif_cqi_len, + uci_data->uci_pmi_len*sizeof(uint8_t)); + } + if (uci_data->uci_ri_len) { - uint8_t *ptr = pucch_bits; - uci_data->uci_ri = (uint8_t) srslte_bit_pack(&ptr, uci_data->uci_ri_len); + uci_data->uci_ri = pucch_bits[0]; /* Assume only one bit of RI */ } if (uci_data->uci_cqi_len || uci_data->uci_ri_len) { diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index c4e2d3f6c..1bef04981 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -677,6 +677,7 @@ int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint8_t *ri, uint8_t *pmi, flo } /* Set RI */ + q->ri = best_ri; if (ri != NULL) { *ri = best_ri; } @@ -712,9 +713,10 @@ int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, uint8_t *ri, float *cn) { *cn = _cn; } + q->ri = (uint8_t)((_cn < 17.0f)? 1:0); /* Set rank indicator */ if (!ret && ri) { - *ri = (uint8_t)((_cn < 17.0f)? 1:0); + *ri = (uint8_t) q->ri; } return ret; diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index 479299bd7..03b53c40a 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -281,8 +281,9 @@ void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format } if (format >= SRSLTE_PUCCH_FORMAT_2) { /* Append RI */ - uint8_t *ptr = uci_buffer; - srslte_bit_unpack(uci_data->uci_ri, &ptr, uci_data->uci_ri_len); + if (uci_data->uci_ri_len) { + uci_data->uci_ri = uci_buffer[0]; // It assumes only 1 bit of RI + } uci_buffer_len += uci_data->uci_ri_len; /* Append CQI */ diff --git a/srsenb/hdr/mac/mac.h b/srsenb/hdr/mac/mac.h index c3df1c9be..14269b0eb 100644 --- a/srsenb/hdr/mac/mac.h +++ b/srsenb/hdr/mac/mac.h @@ -72,7 +72,10 @@ public: int sr_detected(uint32_t tti, uint16_t rnti); int rach_detected(uint32_t tti, uint32_t preamble_idx, uint32_t time_adv); + int set_dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info); + int ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value); + int pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value); int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value); int snr_info(uint32_t tti, uint16_t rnti, float snr); int ack_info(uint32_t tti, uint16_t rnti, bool ack); diff --git a/srsenb/hdr/mac/mac_metrics.h b/srsenb/hdr/mac/mac_metrics.h index ba5821ea9..e11eda350 100644 --- a/srsenb/hdr/mac/mac_metrics.h +++ b/srsenb/hdr/mac/mac_metrics.h @@ -45,6 +45,7 @@ struct mac_metrics_t int dl_buffer; float dl_cqi; float dl_ri; + float dl_pmi; float phr; }; diff --git a/srsenb/hdr/mac/scheduler.h b/srsenb/hdr/mac/scheduler.h index f9316b139..898997449 100644 --- a/srsenb/hdr/mac/scheduler.h +++ b/srsenb/hdr/mac/scheduler.h @@ -103,9 +103,11 @@ public: int dl_rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue); int dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code); + int dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dedicated); int dl_ack_info(uint32_t tti, uint16_t rnti, bool ack); int dl_rach_info(uint32_t tti, uint32_t ra_id, uint16_t rnti, uint32_t estimated_size); int dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value); + int dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value); int dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value); int ul_crc_info(uint32_t tti, uint16_t rnti, bool crc); diff --git a/srsenb/hdr/mac/scheduler_harq.h b/srsenb/hdr/mac/scheduler_harq.h index 2e09136f9..9e1c65c78 100644 --- a/srsenb/hdr/mac/scheduler_harq.h +++ b/srsenb/hdr/mac/scheduler_harq.h @@ -38,50 +38,50 @@ class harq_proc public: void config(uint32_t id, uint32_t max_retx, srslte::log* log_h); void set_max_retx(uint32_t max_retx); - void reset(); + void reset(uint32_t tb_idx); uint32_t get_id(); - bool is_empty(); + bool is_empty(uint32_t tb_idx); - void new_retx(uint32_t tti, int *mcs, int *tbs); + void new_retx(uint32_t tb_idx, uint32_t tti, int *mcs, int *tbs); - bool get_ack(); - void set_ack(bool ack); + bool get_ack(uint32_t tb_idx); + void set_ack(uint32_t tb_idx, bool ack); - uint32_t nof_tx(); - uint32_t nof_retx(); + uint32_t nof_tx(uint32_t tb_idx); + uint32_t nof_retx(uint32_t tb_idx); uint32_t get_tti(); - bool get_ndi(); + bool get_ndi(uint32_t tb_idx); protected: - void new_tx_common(uint32_t tti, int mcs, int tbs); - bool has_pending_retx_common(); + void new_tx_common(uint32_t tb_idx, uint32_t tti, int mcs, int tbs); + bool has_pending_retx_common(uint32_t tb_idx); - bool ack; + bool ack[SRSLTE_MAX_TB]; bool active; - bool ndi; + bool ndi[SRSLTE_MAX_TB]; uint32_t id; uint32_t max_retx; - uint32_t n_rtx; - uint32_t tx_cnt; + uint32_t n_rtx[SRSLTE_MAX_TB]; + uint32_t tx_cnt[SRSLTE_MAX_TB]; int tti; - int last_mcs; - int last_tbs; + int last_mcs[SRSLTE_MAX_TB]; + int last_tbs[SRSLTE_MAX_TB]; srslte::log* log_h; private: - bool ack_received; + bool ack_received[SRSLTE_MAX_TB]; }; class dl_harq_proc : public harq_proc { public: - void new_tx(uint32_t tti, int mcs, int tbs, uint32_t n_cce); + void new_tx(uint32_t tb_idx, uint32_t tti, int mcs, int tbs, uint32_t n_cce); uint32_t get_rbgmask(); void set_rbgmask(uint32_t new_mask); - bool has_pending_retx(uint32_t tti); - int get_tbs(); + bool has_pending_retx(uint32_t tb_idx, uint32_t tti); + int get_tbs(uint32_t tb_idx); uint32_t get_n_cce(); private: uint32_t rbgmask; diff --git a/srsenb/hdr/mac/scheduler_ue.h b/srsenb/hdr/mac/scheduler_ue.h index 4e4b28698..8b0304b09 100644 --- a/srsenb/hdr/mac/scheduler_ue.h +++ b/srsenb/hdr/mac/scheduler_ue.h @@ -68,8 +68,10 @@ public: void ul_phr(int phr); void mac_buffer_state(uint32_t ce_code); void ul_recv_len(uint32_t lcid, uint32_t len); + void set_dl_ant_info(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dedicated); void set_ul_cqi(uint32_t tti, uint32_t cqi, uint32_t ul_ch_code); void set_dl_ri(uint32_t tti, uint32_t ri); + void set_dl_pmi(uint32_t tti, uint32_t ri); void set_dl_cqi(uint32_t tti, uint32_t cqi); int set_ack_info(uint32_t tti, bool ack); void set_ul_crc(uint32_t tti, bool crc_res); @@ -107,9 +109,12 @@ public: void set_sr(); void unset_sr(); - int generate_format1(dl_harq_proc *h, sched_interface::dl_sched_data_t *data, uint32_t tti, uint32_t cfi); - int generate_format0(ul_harq_proc *h, sched_interface::ul_sched_data_t *data, uint32_t tti, bool cqi_request); - + int generate_format1(dl_harq_proc *h, sched_interface::dl_sched_data_t *data, uint32_t tti, uint32_t cfi); + int generate_format2a(dl_harq_proc *h, sched_interface::dl_sched_data_t *data, uint32_t tti, uint32_t cfi); + int generate_format2(dl_harq_proc *h, sched_interface::dl_sched_data_t *data, uint32_t tti, uint32_t cfi); + int generate_format0(ul_harq_proc *h, sched_interface::ul_sched_data_t *data, uint32_t tti, bool cqi_request); + + srslte_dci_format_t get_dci_format(); uint32_t get_aggr_level(uint32_t nof_bits); sched_dci_cce_t *get_locations(uint32_t current_cfi, uint32_t sf_idx); @@ -158,6 +163,8 @@ private: int power_headroom; uint32_t dl_ri; uint32_t dl_ri_tti; + uint32_t dl_pmi; + uint32_t dl_pmi_tti; uint32_t dl_cqi; uint32_t dl_cqi_tti; uint32_t cqi_request_tti; @@ -180,7 +187,8 @@ private: ul_harq_proc ul_harq[SCHED_MAX_HARQ_PROC]; bool phy_config_dedicated_enabled; - + LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT dl_ant_info; + }; } diff --git a/srsenb/hdr/mac/ue.h b/srsenb/hdr/mac/ue.h index 4b65063d5..3974ca52b 100644 --- a/srsenb/hdr/mac/ue.h +++ b/srsenb/hdr/mac/ue.h @@ -94,6 +94,7 @@ public: void metrics_tx(bool crc, uint32_t tbs); void metrics_phr(float phr); void metrics_dl_ri(uint32_t dl_cqi); + void metrics_dl_pmi(uint32_t dl_cqi); void metrics_dl_cqi(uint32_t dl_cqi); @@ -110,6 +111,7 @@ private: uint32_t phr_counter; uint32_t dl_cqi_counter; uint32_t dl_ri_counter; + uint32_t dl_pmi_counter; mac_metrics_t metrics; srslte::mac_pcap* pcap; diff --git a/srsenb/src/mac/mac.cc b/srsenb/src/mac/mac.cc index 23c2557ba..d1e6e01b4 100644 --- a/srsenb/src/mac/mac.cc +++ b/srsenb/src/mac/mac.cc @@ -305,6 +305,18 @@ int mac::crc_info(uint32_t tti, uint16_t rnti, uint32_t nof_bytes, bool crc) } } +int mac::set_dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info) { + log_h->step(tti); + + if (ue_db.count(rnti)) { + scheduler.dl_ant_info(rnti, dl_ant_info); + } else { + Error("User rnti=0x%x not found\n", rnti); + return -1; + } + return 0; +} + int mac::ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value) { log_h->step(tti); @@ -319,6 +331,20 @@ int mac::ri_info(uint32_t tti, uint16_t rnti, uint32_t ri_value) return 0; } +int mac::pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value) +{ + log_h->step(tti); + + if (ue_db.count(rnti)) { + scheduler.dl_pmi_info(tti, rnti, pmi_value); + ue_db[rnti]->metrics_dl_pmi(pmi_value); + } else { + Error("User rnti=0x%x not found\n", rnti); + return -1; + } + return 0; +} + int mac::cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) { log_h->step(tti); @@ -445,6 +471,7 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) // Copy grant info dl_sched_res->sched_grants[n].rnti = rnti; + dl_sched_res->sched_grants[n].dci_format = sched_result.data[i].dci_format; memcpy(&dl_sched_res->sched_grants[n].grant, &sched_result.data[i].dci, sizeof(srslte_ra_dl_dci_t)); memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.data[i].dci_location, sizeof(srslte_dci_location_t)); @@ -454,10 +481,10 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) if (sched_result.data[i].nof_pdu_elems > 0) { dl_sched_res->sched_grants[n].data[0] = ue_db[rnti]->generate_pdu(sched_result.data[i].pdu, sched_result.data[i].nof_pdu_elems, - sched_result.data[i].tbs); + sched_result.data[i].tbs[0]); if (pcap) { - pcap->write_dl_crnti(dl_sched_res->sched_grants[n].data[0], sched_result.data[i].tbs, rnti, true, tti); + pcap->write_dl_crnti(dl_sched_res->sched_grants[n].data[0], sched_result.data[i].tbs[0], rnti, true, tti); } } else { @@ -469,7 +496,8 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) // Copy RAR grants for (uint32_t i=0;isched_grants[n].rnti = sched_result.rar[i].rarnti; + dl_sched_res->sched_grants[n].rnti = sched_result.rar[i].rarnti; + dl_sched_res->sched_grants[n].dci_format = SRSLTE_DCI_FORMAT1A; // Force Format 1A memcpy(&dl_sched_res->sched_grants[n].grant, &sched_result.rar[i].dci, sizeof(srslte_ra_dl_dci_t)); memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.rar[i].dci_location, sizeof(srslte_dci_location_t)); @@ -481,7 +509,7 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) if (pcap) { - pcap->write_dl_ranti(dl_sched_res->sched_grants[n].data[0], sched_result.data[i].tbs, dl_sched_res->sched_grants[n].rnti, true, tti); + pcap->write_dl_ranti(dl_sched_res->sched_grants[n].data[0], sched_result.data[i].tbs[0], dl_sched_res->sched_grants[n].rnti, true, tti); } n++; @@ -490,7 +518,8 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) // Copy SI and Paging grants for (uint32_t i=0;isched_grants[n].rnti = (sched_result.bc[i].type == sched_interface::dl_sched_bc_t::BCCH ) ? SRSLTE_SIRNTI : SRSLTE_PRNTI; + dl_sched_res->sched_grants[n].rnti = (sched_result.bc[i].type == sched_interface::dl_sched_bc_t::BCCH ) ? SRSLTE_SIRNTI : SRSLTE_PRNTI; + dl_sched_res->sched_grants[n].dci_format = SRSLTE_DCI_FORMAT1A; // Force Format 1A memcpy(&dl_sched_res->sched_grants[n].grant, &sched_result.bc[i].dci, sizeof(srslte_ra_dl_dci_t)); memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.bc[i].dci_location, sizeof(srslte_dci_location_t)); diff --git a/srsenb/src/mac/scheduler.cc b/srsenb/src/mac/scheduler.cc index 298ce9625..dd787a28d 100644 --- a/srsenb/src/mac/scheduler.cc +++ b/srsenb/src/mac/scheduler.cc @@ -238,6 +238,19 @@ int sched::dl_mac_buffer_state(uint16_t rnti, uint32_t ce_code) return ret; } +int sched::dl_ant_info(uint16_t rnti, LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *dl_ant_info) { + pthread_mutex_lock(&mutex); + int ret = 0; + if (ue_db.count(rnti)) { + ue_db[rnti].set_dl_ant_info(dl_ant_info); + } else { + Error("User rnti=0x%x not found\n", rnti); + ret = -1; + } + pthread_mutex_unlock(&mutex); + return ret; +} + int sched::dl_ack_info(uint32_t tti, uint16_t rnti, bool ack) { pthread_mutex_lock(&mutex); @@ -280,6 +293,20 @@ int sched::dl_ri_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) return ret; } +int sched::dl_pmi_info(uint32_t tti, uint16_t rnti, uint32_t pmi_value) +{ + pthread_mutex_lock(&mutex); + int ret = 0; + if (ue_db.count(rnti)) { + ue_db[rnti].set_dl_pmi(tti, pmi_value); + } else { + Error("User rnti=0x%x not found\n", rnti); + ret = -1; + } + pthread_mutex_unlock(&mutex); + return ret; +} + int sched::dl_cqi_info(uint32_t tti, uint16_t rnti, uint32_t cqi_value) { pthread_mutex_lock(&mutex); @@ -611,19 +638,34 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST]) uint16_t rnti = (uint16_t) iter->first; dl_harq_proc *h = dl_metric->get_user_allocation(user); - + srslte_dci_format_t dci_format = user->get_dci_format(); + data[nof_data_elems].dci_format = dci_format; + if (h) { // Try to schedule DCI first if (generate_dci(&data[nof_data_elems].dci_location, user->get_locations(current_cfi, sf_idx), - user->get_aggr_level(srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1, cfg.cell.nof_prb, cfg.cell.nof_ports)), user)) + user->get_aggr_level(srslte_dci_format_sizeof(dci_format, cfg.cell.nof_prb, cfg.cell.nof_ports)), user)) { - bool is_newtx = h->is_empty(); - int tbs = user->generate_format1(h, &data[nof_data_elems], current_tti, current_cfi); + bool is_newtx = h->is_empty(0); + int tbs = 0; + switch(dci_format) { + case SRSLTE_DCI_FORMAT1: + tbs = user->generate_format1(h, &data[nof_data_elems], current_tti, current_cfi); + break; + case SRSLTE_DCI_FORMAT2: + tbs = user->generate_format2(h, &data[nof_data_elems], current_tti, current_cfi); + break; + case SRSLTE_DCI_FORMAT2A: + tbs = user->generate_format2a(h, &data[nof_data_elems], current_tti, current_cfi); + break; + default: + Error("DCI format (%d) not implemented\n", dci_format); + } if (tbs >= 0) { log_h->info("SCHED: DL %s rnti=0x%x, pid=%d, mask=0x%x, dci=%d,%d, n_rtx=%d, tbs=%d, buffer=%d\n", !is_newtx?"retx":"tx", rnti, h->get_id(), h->get_rbgmask(), - data[nof_data_elems].dci_location.L, data[nof_data_elems].dci_location.ncce, h->nof_retx(), + data[nof_data_elems].dci_location.L, data[nof_data_elems].dci_location.ncce, h->nof_retx(0), tbs, user->get_pending_dl_new_data(current_tti)); nof_data_elems++; } else { @@ -633,7 +675,7 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST]) tbs, user->get_pending_dl_new_data(current_tti)); } } else { - h->reset(); + h->reset(0); Warning("SCHED: Could not schedule DL DCI for rnti=0x%x, pid=%d\n", rnti, h->get_id()); } } @@ -721,7 +763,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched /* Indicate PHICH acknowledgment if needed */ if (h->has_pending_ack()) { - sched_result->phich[nof_phich_elems].phich = h->get_ack()?ul_sched_phich_t::ACK:ul_sched_phich_t::NACK; + sched_result->phich[nof_phich_elems].phich = h->get_ack(0)?ul_sched_phich_t::ACK:ul_sched_phich_t::NACK; sched_result->phich[nof_phich_elems].rnti = rnti; nof_phich_elems++; } @@ -778,7 +820,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched if (h) { ul_harq_proc::ul_alloc_t alloc = h->get_alloc(); - bool is_newtx = h->is_empty(); + bool is_newtx = h->is_empty(0); bool needs_pdcch = !h->is_adaptive_retx() && !is_rar; // Set number of retx @@ -797,7 +839,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched user->get_locations(current_cfi, sf_idx), aggr_level)) { - h->reset(); + h->reset(0); log_h->warning("SCHED: Could not schedule UL DCI rnti=0x%x, pid=%d, L=%d\n", rnti, h->get_id(), aggr_level); sched_result->pusch[nof_dci_elems].needs_pdcch = false; @@ -824,7 +866,7 @@ int sched::ul_sched(uint32_t tti, srsenb::sched_interface::ul_sched_res_t* sched is_newtx?"tx":"retx", rnti, h->get_id(), sched_result->pusch[nof_dci_elems].dci_location.L, sched_result->pusch[nof_dci_elems].dci_location.ncce, - alloc.RB_start, alloc.RB_start+alloc.L, h->nof_retx(), sched_result->pusch[nof_dci_elems].tbs, + alloc.RB_start, alloc.RB_start+alloc.L, h->nof_retx(0), sched_result->pusch[nof_dci_elems].tbs, user->get_pending_ul_new_data(current_tti),pending_data_before, user->get_pending_ul_old_data()); nof_dci_elems++; diff --git a/srsenb/src/mac/scheduler_harq.cc b/srsenb/src/mac/scheduler_harq.cc index a6ae70d19..cbb66c669 100644 --- a/srsenb/src/mac/scheduler_harq.cc +++ b/srsenb/src/mac/scheduler_harq.cc @@ -50,7 +50,9 @@ void harq_proc::config(uint32_t id_, uint32_t max_retx_, srslte::log* log_h_) log_h = log_h_; id = id_; max_retx = max_retx_; - ndi = false; + for (int i = 0; i < SRSLTE_MAX_TB; i++) { + ndi[i] = false; + } } void harq_proc::set_max_retx(uint32_t max_retx_) { @@ -63,57 +65,57 @@ uint32_t harq_proc::get_id() return id; } -void harq_proc::reset() +void harq_proc::reset(uint32_t tb_idx) { active = false; - ack = true; - ack_received = false; - n_rtx = 0; + ack[tb_idx] = true; + ack_received[tb_idx] = false; + n_rtx[tb_idx] = 0; tti = 0; - last_mcs = -1; - last_tbs = -1; - tx_cnt = 0; + last_mcs[tb_idx] = -1; + last_tbs[tb_idx] = -1; + tx_cnt[tb_idx] = 0; } -bool harq_proc::is_empty() +bool harq_proc::is_empty(uint32_t tb_idx) { - return !active || (active && ack && ack_received); + return !active || (active && ack[tb_idx] && ack_received[tb_idx]); } -bool harq_proc::has_pending_retx_common() +bool harq_proc::has_pending_retx_common(uint32_t tb_idx) { - return !ack && n_rtx < max_retx; + return !ack[tb_idx] && n_rtx[tb_idx] < max_retx; } uint32_t harq_proc::get_tti() { - return tti; + return (uint32_t) tti; } -bool harq_proc::get_ack() +bool harq_proc::get_ack(uint32_t tb_idx) { - return ack; + return ack[tb_idx]; } -void harq_proc::set_ack(bool ack_) +void harq_proc::set_ack(uint32_t tb_idx, bool ack_) { - ack = ack_; - ack_received = true; - log_h->debug("ACK=%d received pid=%d, n_rtx=%d, max_retx=%d\n", ack_, id, n_rtx, max_retx); - if (n_rtx + 1 >= max_retx) { - Warning("SCHED: discarting TB pid=%d, tti=%d, maximum number of retx exceeded (%d)\n", id, tti, max_retx); + ack[tb_idx] = ack_; + ack_received[tb_idx] = true; + log_h->debug("ACK=%d received pid=%d, tb_idx=%d, n_rtx=%d, max_retx=%d\n", ack_, id, tb_idx, n_rtx[tb_idx], max_retx); + if (n_rtx[tb_idx] + 1 >= max_retx) { + Warning("SCHED: discarting TB %d pid=%d, tti=%d, maximum number of retx exceeded (%d)\n", tb_idx, id, tti, max_retx); active = false; } } -void harq_proc::new_tx_common(uint32_t tti_, int mcs, int tbs) +void harq_proc::new_tx_common(uint32_t tb_idx, uint32_t tti_, int mcs, int tbs) { - reset(); - ndi = !ndi; + reset(tb_idx); + ndi[tb_idx] = !ndi[tb_idx]; tti = tti_; - tx_cnt++; - last_mcs = mcs; - last_tbs = tbs; + tx_cnt[tb_idx]++; + last_mcs[tb_idx] = mcs; + last_tbs[tb_idx] = tbs; if (max_retx) { active = true; @@ -122,42 +124,42 @@ void harq_proc::new_tx_common(uint32_t tti_, int mcs, int tbs) } } -void harq_proc::new_retx(uint32_t tti_, int *mcs, int *tbs) +void harq_proc::new_retx(uint32_t tb_idx, uint32_t tti_, int *mcs, int *tbs) { - ack_received = false; + ack_received[tb_idx] = false; tti = tti_; - n_rtx++; + n_rtx[tb_idx]++; if (mcs) { - *mcs = last_mcs; + *mcs = last_mcs[tb_idx]; } if (tbs) { - *tbs = last_tbs; + *tbs = last_tbs[tb_idx]; } } -uint32_t harq_proc::nof_tx() +uint32_t harq_proc::nof_tx(uint32_t tb_idx) { - return tx_cnt; + return tx_cnt[tb_idx]; } -uint32_t harq_proc::nof_retx() +uint32_t harq_proc::nof_retx(uint32_t tb_idx) { - return n_rtx; + return n_rtx[tb_idx]; } -bool harq_proc::get_ndi() +bool harq_proc::get_ndi(uint32_t tb_idx) { - return ndi; + return ndi[tb_idx]; } /****************************************************** * UE::DL HARQ class * ******************************************************/ -void dl_harq_proc::new_tx(uint32_t tti, int mcs, int tbs, uint32_t n_cce_) +void dl_harq_proc::new_tx(uint32_t tb_idx, uint32_t tti, int mcs, int tbs, uint32_t n_cce_) { n_cce = n_cce_; - new_tx_common(tti, mcs, tbs); + new_tx_common(tb_idx, tti, mcs, tbs); } uint32_t dl_harq_proc::get_n_cce() @@ -175,14 +177,14 @@ void dl_harq_proc::set_rbgmask(uint32_t new_mask) rbgmask = new_mask; } -bool dl_harq_proc::has_pending_retx(uint32_t current_tti) +bool dl_harq_proc::has_pending_retx(uint32_t tb_idx, uint32_t current_tti) { - return srslte_tti_interval(current_tti, tti) >= 8 && has_pending_retx_common(); + return srslte_tti_interval(current_tti, tti) >= 8 && has_pending_retx_common(tb_idx); } -int dl_harq_proc::get_tbs() +int dl_harq_proc::get_tbs(uint32_t tb_idx) { - return last_tbs; + return last_tbs[tb_idx]; } @@ -215,7 +217,7 @@ bool ul_harq_proc::is_adaptive_retx() void ul_harq_proc::new_tx(uint32_t tti_, int mcs, int tbs) { need_ack = true; - new_tx_common(tti_, mcs, tbs); + new_tx_common(0, tti_, mcs, tbs); pending_data = tbs; } @@ -225,7 +227,7 @@ bool ul_harq_proc::has_pending_ack() bool ret = need_ack; // Reset if already received a positive ACK - if (active && ack) { + if (active && ack[0]) { active = false; } if (!active) { @@ -244,9 +246,9 @@ void ul_harq_proc::reset_pending_data() } - uint32_t ul_harq_proc::get_pending_data() +uint32_t ul_harq_proc::get_pending_data() { - return pending_data; + return (uint32_t) pending_data; } void ul_harq_proc::set_rar_mcs(uint32_t mcs) diff --git a/srsenb/src/mac/scheduler_metric.cc b/srsenb/src/mac/scheduler_metric.cc index 708ab2dd8..ee3f44e6f 100644 --- a/srsenb/src/mac/scheduler_metric.cc +++ b/srsenb/src/mac/scheduler_metric.cc @@ -212,7 +212,7 @@ void ul_metric_rr::new_tti(std::map &ue_db, uint32_t nof_rb_, nof_users_with_data = 0; for(std::map::iterator iter=ue_db.begin(); iter!=ue_db.end(); ++iter) { sched_ue *user = (sched_ue*) &iter->second; - if (user->get_pending_ul_new_data(current_tti) || !user->get_ul_harq(current_tti)->is_empty()) { + if (user->get_pending_ul_new_data(current_tti) || !user->get_ul_harq(current_tti)->is_empty(0)) { user->ue_idx = nof_users_with_data; nof_users_with_data++; } @@ -284,7 +284,7 @@ ul_harq_proc* ul_metric_rr::get_user_allocation(sched_ue *user) uint32_t pending_data = user->get_pending_ul_new_data(current_tti); ul_harq_proc *h = user->get_ul_harq(current_tti); - if (pending_data || !h->is_empty()) { + if (pending_data || !h->is_empty(0)) { if (nof_users_with_data) { if ((current_tti%nof_users_with_data) != user->ue_idx) { return NULL; @@ -294,7 +294,7 @@ ul_harq_proc* ul_metric_rr::get_user_allocation(sched_ue *user) // Schedule retx if we have space - if (!h->is_empty()) { + if (!h->is_empty(0)) { ul_harq_proc::ul_alloc_t alloc = h->get_alloc(); @@ -313,7 +313,7 @@ ul_harq_proc* ul_metric_rr::get_user_allocation(sched_ue *user) } } // If could not schedule the reTx, or there wasn't any pending retx, find an empty PID - if (h->is_empty()) { + if (h->is_empty(0)) { // Allocate resources based on pending data if (pending_data) { uint32_t pending_rb = user->get_required_prb_ul(pending_data); diff --git a/srsenb/src/mac/scheduler_ue.cc b/srsenb/src/mac/scheduler_ue.cc index 8abb86d88..974791957 100644 --- a/srsenb/src/mac/scheduler_ue.cc +++ b/srsenb/src/mac/scheduler_ue.cc @@ -109,8 +109,8 @@ void sched_ue::reset() ul_cqi_tti = 0; cqi_request_tti = 0; for (int i=0;iset_ack(crc_res); + get_ul_harq(tti)->set_ack(0, crc_res); } void sched_ue::set_dl_ri(uint32_t tti, uint32_t ri) @@ -329,10 +329,21 @@ void sched_ue::set_dl_ri(uint32_t tti, uint32_t ri) dl_ri_tti = tti; } +void sched_ue::set_dl_pmi(uint32_t tti, uint32_t pmi) +{ + dl_pmi = pmi; + dl_pmi_tti = tti; +} + void sched_ue::set_dl_cqi(uint32_t tti, uint32_t cqi) { - dl_cqi = cqi; - dl_cqi_tti = tti; + dl_cqi = cqi; + dl_cqi_tti = tti; +} + +void sched_ue::set_dl_ant_info(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *d) +{ + memcpy(&dl_ant_info, d, sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT)); } void sched_ue::set_ul_cqi(uint32_t tti, uint32_t cqi, uint32_t ul_ch_code) @@ -363,10 +374,10 @@ void sched_ue::tpc_dec() { // Generates a Format1 grant -int sched_ue::generate_format1(dl_harq_proc *h, - sched_interface::dl_sched_data_t *data, - uint32_t tti, - uint32_t cfi) +int sched_ue::generate_format1(dl_harq_proc *h, + sched_interface::dl_sched_data_t *data, + uint32_t tti, + uint32_t cfi) { srslte_ra_dl_dci_t *dci = &data->dci; bzero(dci, sizeof(srslte_ra_dl_dci_t)); @@ -385,7 +396,7 @@ int sched_ue::generate_format1(dl_harq_proc *h, if (is_first_dl_tx()) { need_conres_ce = true; } - if (h->is_empty()) { + if (h->is_empty(0)) { uint32_t req_bytes = get_pending_dl_new_data(tti); @@ -401,11 +412,11 @@ int sched_ue::generate_format1(dl_harq_proc *h, mcs = fixed_mcs_dl; } - h->new_tx(tti, mcs, tbs, data->dci_location.ncce); + h->new_tx(0, tti, mcs, tbs, data->dci_location.ncce); Debug("SCHED: Alloc format1 new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes); } else { - h->new_retx(tti, &mcs, &tbs); + h->new_retx(0, tti, &mcs, &tbs); Debug("SCHED: Alloc format1 previous mcs=%d, tbs=%d\n", mcs, tbs); } @@ -431,19 +442,159 @@ int sched_ue::generate_format1(dl_harq_proc *h, if (tbs > 0) { dci->harq_process = h->get_id(); dci->mcs_idx = mcs; - dci->rv_idx = sched::get_rvidx(h->nof_retx()); - dci->ndi = h->get_ndi(); - dci->tpc_pucch = next_tpc_pucch; + dci->rv_idx = sched::get_rvidx(h->nof_retx(0)); + dci->ndi = h->get_ndi(0); + dci->tpc_pucch = next_tpc_pucch; next_tpc_pucch = 1; - data->tbs = tbs; + data->tbs[0] = tbs; dci->tb_en[0] = true; dci->tb_en[1] = false; } return tbs; } +// Generates a Format2a grant +int sched_ue::generate_format2a(dl_harq_proc *h, + sched_interface::dl_sched_data_t *data, + uint32_t tti, + uint32_t cfi) +{ + srslte_ra_dl_dci_t *dci = &data->dci; + bzero(dci, sizeof(srslte_ra_dl_dci_t)); -int sched_ue::generate_format0(ul_harq_proc *h, + uint32_t sf_idx = tti%10; + + int mcs = 0; + int tbs = 0; + + dci->alloc_type = SRSLTE_RA_ALLOC_TYPE0; + dci->type0_alloc.rbg_bitmask = h->get_rbgmask(); + + if (h->is_empty(0)) { + + uint32_t req_bytes = get_pending_dl_new_data(tti); + + uint32_t nof_prb = format1_count_prb(h->get_rbgmask(), cell.nof_prb); + srslte_ra_dl_grant_t grant; + srslte_ra_dl_dci_to_grant_prb_allocation(dci, &grant, cell.nof_prb); + uint32_t nof_ctrl_symbols = cfi+(cell.nof_prb<10?1:0); + uint32_t nof_re = srslte_ra_dl_grant_nof_re(&grant, cell, sf_idx, nof_ctrl_symbols); + if (fixed_mcs_dl < 0) { + tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs); + } else { + tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl), nof_prb)/8; + mcs = fixed_mcs_dl; + } + + h->new_tx(0, tti, mcs, tbs, data->dci_location.ncce); + + Debug("SCHED: Alloc format1 new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes); + } else { + h->new_retx(0, tti, &mcs, &tbs); + Debug("SCHED: Alloc format1 previous mcs=%d, tbs=%d\n", mcs, tbs); + } + + int rem_tbs = tbs; + int x = 0; + do { + x = alloc_pdu(rem_tbs, &data->pdu[data->nof_pdu_elems]); + rem_tbs -= x; + if (x) { + data->nof_pdu_elems++; + } + } while(rem_tbs > 0 && x > 0); + + data->rnti = rnti; + + if (tbs > 0) { + dci->harq_process = h->get_id(); + dci->mcs_idx = mcs; + dci->rv_idx = sched::get_rvidx(h->nof_retx(0)); + dci->ndi = h->get_ndi(0); + dci->tpc_pucch = next_tpc_pucch; + next_tpc_pucch = 1; + data->tbs[0] = tbs; + dci->tb_en[0] = true; + dci->tb_en[1] = false; + } + return tbs; +} + +// Generates a Format2 grant +int sched_ue::generate_format2(dl_harq_proc *h, + sched_interface::dl_sched_data_t *data, + uint32_t tti, + uint32_t cfi) +{ + srslte_ra_dl_dci_t *dci = &data->dci; + bzero(dci, sizeof(srslte_ra_dl_dci_t)); + + uint32_t sf_idx = tti%10; + + int mcs = 0; + int tbs = 0; + + dci->alloc_type = SRSLTE_RA_ALLOC_TYPE0; + dci->type0_alloc.rbg_bitmask = h->get_rbgmask(); + + if (h->is_empty(0)) { + + uint32_t req_bytes = get_pending_dl_new_data(tti); + + uint32_t nof_prb = format1_count_prb(h->get_rbgmask(), cell.nof_prb); + srslte_ra_dl_grant_t grant; + srslte_ra_dl_dci_to_grant_prb_allocation(dci, &grant, cell.nof_prb); + uint32_t nof_ctrl_symbols = cfi+(cell.nof_prb<10?1:0); + uint32_t nof_re = srslte_ra_dl_grant_nof_re(&grant, cell, sf_idx, nof_ctrl_symbols); + if (fixed_mcs_dl < 0) { + tbs = alloc_tbs_dl(nof_prb, nof_re, req_bytes, &mcs); + } else { + tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(fixed_mcs_dl), nof_prb)/8; + mcs = fixed_mcs_dl; + } + + h->new_tx(0, tti, mcs, tbs, data->dci_location.ncce); + + Debug("SCHED: Alloc format2 new mcs=%d, tbs=%d, nof_prb=%d, req_bytes=%d\n", mcs, tbs, nof_prb, req_bytes); + } else { + h->new_retx(0, tti, &mcs, &tbs); + Debug("SCHED: Alloc format2 previous mcs=%d, tbs=%d\n", mcs, tbs); + } + + int rem_tbs = tbs; + int x = 0; + do { + x = alloc_pdu(rem_tbs, &data->pdu[data->nof_pdu_elems]); + rem_tbs -= x; + if (x) { + data->nof_pdu_elems++; + } + } while(rem_tbs > 0 && x > 0); + + data->rnti = rnti; + + if (tbs > 0) { + dci->pinfo = (uint8_t) (dl_pmi + 1); +/* if (SRSLTE_RA_DL_GRANT_NOF_TB(dci) == 1) { + dci->pinfo = (uint8_t) (dl_pmi + 1); + } else { + dci->pinfo = (uint8_t) (dl_pmi & 1); + }*/ + dci->harq_process = h->get_id(); + dci->mcs_idx = mcs; + dci->rv_idx = sched::get_rvidx(h->nof_retx(0)); + dci->ndi = h->get_ndi(0); + dci->tpc_pucch = next_tpc_pucch; + next_tpc_pucch = 1; + data->tbs[0] = tbs; + dci->tb_en[0] = true; + dci->tb_en[1] = false; + } + return tbs; +} + + +int sched_ue::generate_format0(ul_harq_proc *h, sched_interface::ul_sched_data_t *data, uint32_t tti, bool cqi_request) @@ -459,7 +610,7 @@ int sched_ue::generate_format0(ul_harq_proc *h, if (h->get_rar_mcs(&mcs)) { tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs), allocation.L)/8; h->new_tx(tti, mcs, tbs); - } else if (h->is_empty()) { + } else if (h->is_empty(0)) { uint32_t req_bytes = get_pending_ul_new_data(tti); @@ -475,7 +626,7 @@ int sched_ue::generate_format0(ul_harq_proc *h, h->new_tx(tti, mcs, tbs); } else { - h->new_retx(tti, &mcs, NULL); + h->new_retx(0, tti, &mcs, NULL); tbs = srslte_ra_tbs_from_idx(srslte_ra_tbs_idx_from_mcs(mcs), allocation.L)/8; } @@ -486,8 +637,8 @@ int sched_ue::generate_format0(ul_harq_proc *h, dci->type2_alloc.L_crb = allocation.L; dci->type2_alloc.RB_start = allocation.RB_start; dci->mcs_idx = mcs; - dci->rv_idx = sched::get_rvidx(h->nof_retx()); - dci->ndi = h->get_ndi(); + dci->rv_idx = sched::get_rvidx(h->nof_retx(0)); + dci->ndi = h->get_ndi(0); dci->cqi_request = cqi_request; dci->freq_hop_fl = srslte_ra_ul_dci_t::SRSLTE_RA_PUSCH_HOP_DISABLED; dci->tpc_pusch = next_tpc_pusch; @@ -518,7 +669,7 @@ uint32_t sched_ue::get_max_retx() { bool sched_ue::is_first_dl_tx() { for (int i=0;i 0) { + if (dl_harq[i].nof_tx(0) > 0) { return false; } } @@ -666,7 +817,7 @@ dl_harq_proc* sched_ue::get_pending_dl_harq(uint32_t tti) int oldest_idx=-1; uint32_t oldest_tti = 0; for (int i=0;i oldest_tti) { oldest_idx = i; @@ -684,7 +835,7 @@ dl_harq_proc* sched_ue::get_pending_dl_harq(uint32_t tti) dl_harq_proc* sched_ue::get_empty_dl_harq() { for (int i=0;icell.nof_prb) * sizeof(cf_t)); } if (srslte_enb_dl_init(&enb_dl, phy->cell.nof_prb)) { fprintf(stderr, "Error initiating ENB DL\n"); @@ -566,6 +567,10 @@ int phch_worker::decode_pucch(uint32_t tti_rx) needs_cqi = true; cqi_value.type = SRSLTE_CQI_TYPE_WIDEBAND; uci_data.uci_cqi_len = srslte_cqi_size(&cqi_value); + if (tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + //uci_data.uci_dif_cqi_len = 3; + uci_data.uci_pmi_len = 2; + } } } @@ -589,6 +594,17 @@ int phch_worker::decode_pucch(uint32_t tti_rx) srslte_cqi_value_unpack(uci_data.uci_cqi, &cqi_value); phy->mac->cqi_info(tti_rx, rnti, cqi_value.wideband.wideband_cqi); sprintf(cqi_ri_str, ", cqi=%d", cqi_value.wideband.wideband_cqi); + + if (uci_data.uci_pmi_len) { + uint8_t *ptr = uci_data.uci_pmi; + uint32_t packed_pmi = uci_data.uci_pmi[0]; + if (uci_data.uci_pmi_len > 1) { + packed_pmi = (packed_pmi << 1) + uci_data.uci_pmi[1]; + } + phy->mac->pmi_info(tti_rx, rnti, packed_pmi); + sprintf(cqi_ri_str, "%s, pmi=%c", cqi_ri_str, packed_pmi + 0x30); + } + } log_h->info("PUCCH: rnti=0x%x, corr=%.2f, n_pucch=%d, n_prb=%d%s%s%s\n", rnti, @@ -656,35 +672,16 @@ int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_gra { /* For each grant... */ for (uint32_t i=0;irnti; if (rnti) { - bool dedicated_acknowledged = ue_db[grants[i].rnti].dedicated_ack; - bool antenna_info_present = ue_db[grants[i].rnti].dedicated.antenna_info_present; - LIBLTE_RRC_TRANSMISSION_MODE_ENUM tx_mode = ue_db[grants[i].rnti].dedicated.antenna_info_explicit_value.tx_mode; - - srslte_dci_format_t format = SRSLTE_DCI_FORMAT1; - switch(grants[i].grant.alloc_type) { - case SRSLTE_RA_ALLOC_TYPE0: - case SRSLTE_RA_ALLOC_TYPE1: - if (dedicated_acknowledged && antenna_info_present && tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { - format = SRSLTE_DCI_FORMAT2A; - } else if (dedicated_acknowledged && antenna_info_present && tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { - format = SRSLTE_DCI_FORMAT2; - } else { - format = SRSLTE_DCI_FORMAT1; - } - break; - case SRSLTE_RA_ALLOC_TYPE2: - format = SRSLTE_DCI_FORMAT1A; - break; - } - if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, format, grants[i].location, rnti, sf_idx)) { + if (srslte_enb_dl_put_pdcch_dl(&enb_dl, &grants[i].grant, grant->dci_format, grants[i].location, rnti, sf_idx)) { fprintf(stderr, "Error putting PDCCH %d\n",i); 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), + Info("PDCCH: DL DCI %s rnti=0x%x, cce_index=%d, L=%d, tti_tx=%d\n", srslte_dci_format_string(grant->dci_format), rnti, grants[i].location.ncce, (1<info_hex(ptr, len, - "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx=%d\n", + "PDSCH: rnti=0x%x, l_crb=%2d, %s, harq=%d, tbs=%d, mcs=%d, rv=%d, tti_tx=%d, tx_scheme=%s%s\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); + phy_grant.mcs[0].tbs/8, phy_grant.mcs[0].idx, grants[i].grant.rv_idx, tti_tx, srslte_mimotype2str(mimo_type), pinfo_str); } int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, grants[i].grant.rv_idx_1}; - if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffers, rnti, rv, sf_idx, grants[i].data, mimo_type, 0)) { + if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffers, rnti, rv, sf_idx, grants[i].data, mimo_type)) { fprintf(stderr, "Error putting PDSCH %d\n",i); return SRSLTE_ERROR; } diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 90e175095..54a8b2663 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -864,6 +864,7 @@ void rrc::ue::handle_rrc_con_setup_complete(LIBLTE_RRC_CONNECTION_SETUP_COMPLETE // Acknowledge Dedicated Configuration parent->phy->set_conf_dedicated_ack(rnti, true); + parent->mac->phy_config_enabled(rnti, true); if(has_tmsi) { parent->s1ap->initial_ue(rnti, pdu, m_tmsi, mmec); @@ -1211,7 +1212,8 @@ void rrc::ue::send_connection_setup(bool is_setup) // Configure PHY layer parent->phy->set_config_dedicated(rnti, phy_cfg); parent->phy->set_conf_dedicated_ack(rnti, false); - parent->mac->phy_config_enabled(rnti, true); + parent->mac->set_dl_ant_info(rnti, &phy_cfg->antenna_info_explicit_value); + parent->mac->phy_config_enabled(rnti, false); rr_cfg->drb_to_add_mod_list_size = 0; rr_cfg->drb_to_release_list_size = 0; diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 312ec57b1..4ccbbae69 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -374,7 +374,6 @@ void phch_worker::compute_ri() { float sinr = 0.0f; uint8 packed_pmi = 0; srslte_ue_dl_ri_pmi_select(&ue_dl, &uci_data.uci_ri, &packed_pmi, &sinr); - srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, 2); if (uci_data.uci_ri == 0) { uci_data.uci_pmi_len = 2; uci_data.uci_dif_cqi_len = 0; @@ -382,6 +381,8 @@ void phch_worker::compute_ri() { uci_data.uci_pmi_len = 1; uci_data.uci_dif_cqi_len = 3; } + srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, uci_data.uci_pmi_len); + Info("pmi=%d\n", packed_pmi); /* If only one antenna in TM4 print limitation warning */ if (ue_dl.nof_rx_antennas < 2) { @@ -615,9 +616,13 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL snprintf(timestr, 64, ", dec_time=%4d us", (int) t[0].tv_usec); #endif - snprintf(commonstr, 128, "PDSCH: l_crb=%2d, harq=%d, snr=%.1f dB, tx_scheme=%s", grant->nof_prb, harq_pid, - 10 * log10(srslte_chest_dl_get_snr(&ue_dl.chest)), srslte_mimotype2str(mimo_type)); + char pinfo_str[16] = {0}; + if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + snprintf(pinfo_str, 15, ", pinfo=%x", grant->pinfo); + } + snprintf(commonstr, 128, "PDSCH: l_crb=%2d, harq=%d, snr=%.1f dB, tx_scheme=%s%s", grant->nof_prb, harq_pid, + 10 * log10(srslte_chest_dl_get_snr(&ue_dl.chest)), srslte_mimotype2str(mimo_type), pinfo_str); for (int i=0;itb_en[i]) { snprintf(tbstr[i], 128, ", TB%d: tbs=%d, mcs=%d, rv=%d, crc=%s, it=%d", @@ -826,6 +831,16 @@ void phch_worker::set_uci_periodic_cqi() } Info("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db); } + if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + if (ue_dl.ri == 0) { + uci_data.uci_pmi_len = 2; + } else { + uci_data.uci_pmi_len = 1; + uci_data.uci_dif_cqi_len = 3; + } + uint8_t *ptr = uci_data.uci_pmi; + srslte_bit_unpack(ue_dl.pmi[ue_dl.ri], &ptr, uci_data.uci_pmi_len); + } uci_data.uci_cqi_len = srslte_cqi_value_pack(&cqi_report, uci_data.uci_cqi); rar_cqi_request = false; }