diff --git a/lib/include/srslte/interfaces/ue_nr_interfaces.h b/lib/include/srslte/interfaces/ue_nr_interfaces.h index 0468a606d..cddd1698b 100644 --- a/lib/include/srslte/interfaces/ue_nr_interfaces.h +++ b/lib/include/srslte/interfaces/ue_nr_interfaces.h @@ -15,6 +15,7 @@ #include "srslte/common/interfaces_common.h" #include "srslte/interfaces/mac_interface_types.h" +#include #include namespace srsue { @@ -46,12 +47,26 @@ public: virtual int sf_indication(const uint32_t tti) = 0; ///< FIXME: rename to slot indication + // Query the MAC for the current RNTI to look for + virtual uint16_t get_dl_sched_rnti(const uint32_t tti) = 0; + virtual uint16_t get_ul_sched_rnti(const uint32_t tti) = 0; + /// Indicate succussfully received TB to MAC. The TB buffer is allocated in the PHY and handed as unique_ptr to MAC virtual void tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) = 0; /// Indicate reception of UL grant (only TBS is provided). Buffer for resulting MAC PDU is provided by MAC and is /// passed as pointer to PHY during tx_reuqest virtual void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant) = 0; + + /** + * @brief Indicate the successful transmission of a PRACH. + * @param tti The TTI from the PHY viewpoint at which the PRACH was sent over-the-air (not to the radio). + * @param s_id The index of the first OFDM symbol of the specified PRACH (0 <= s_id < 14). + * @param t_id The index of the first slot of the specified PRACH (0 <= t_id < 80). + * @param f_id The index of the specified PRACH in the frequency domain (0 <= f_id < 8). + * @param ul_carrier_id The UL carrier used for Msg1 transmission (0 for NUL carrier, and 1 for SUL carrier). + */ + virtual void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id) = 0; }; class mac_interface_rrc_nr @@ -77,6 +92,13 @@ public: uint8_t* data; // always a pointer in our case } tx_request_t; + // MAC informs PHY about UL grant included in RAR PDU + virtual int set_ul_grant(std::array) = 0; + + // MAC instructs PHY to send a PRACH at the next given occasion + virtual void send_prach(uint32_t prach_occasion, uint32_t preamble_index, int preamble_received_target_power) = 0; + + // MAC instructs PHY to transmit MAC TB at the given TTI virtual int tx_request(const tx_request_t& request) = 0; }; diff --git a/srsue/hdr/phy/vnf_phy_nr.h b/srsue/hdr/phy/vnf_phy_nr.h index 3bbf1c890..d5b245d8c 100644 --- a/srsue/hdr/phy/vnf_phy_nr.h +++ b/srsue/hdr/phy/vnf_phy_nr.h @@ -48,6 +48,8 @@ public: // MAC interface int tx_request(const tx_request_t& request); + int set_ul_grant(std::array) { return SRSLTE_SUCCESS; }; + void send_prach(uint32_t prach_occasion, uint32_t preamble_index, int preamble_received_target_power){}; private: std::unique_ptr vnf; diff --git a/srsue/hdr/stack/mac_nr/mac_nr.h b/srsue/hdr/stack/mac_nr/mac_nr.h index aa3c6e581..01beae532 100644 --- a/srsue/hdr/stack/mac_nr/mac_nr.h +++ b/srsue/hdr/stack/mac_nr/mac_nr.h @@ -40,22 +40,25 @@ public: void stop(); void reset(); - void run_tti(const uint32_t tti); - uint16_t get_dl_sched_rnti(uint32_t tti); - uint16_t get_ul_sched_rnti(uint32_t tti); - void bch_decoded_ok(uint32_t tti, srslte::unique_byte_buffer_t payload); - int sf_indication(const uint32_t tti); + /// Interface for PHY + uint16_t get_dl_sched_rnti(const uint32_t tti); + uint16_t get_ul_sched_rnti(const uint32_t tti); + int sf_indication(const uint32_t tti); void tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant); - void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant); + void prach_sent(const uint32_t tti, + const uint32_t s_id, + const uint32_t t_id, + const uint32_t f_id, + const uint32_t ul_carrier_id); + /// Stack interface void timer_expired(uint32_t timer_id); - void get_metrics(mac_metrics_t* metrics); /// Interface for RRC (RRC -> MAC) @@ -69,9 +72,13 @@ public: void process_pdus(); private: + void write_pcap(const uint32_t cc_idx, mac_nr_grant_dl_t& grant); // If PCAPs are enabled for this MAC void handle_pdu(srslte::unique_byte_buffer_t pdu); void get_ul_data(const mac_nr_grant_ul_t& grant, phy_interface_stack_nr::tx_request_t* tx_request); + // temporary helper + void handle_rar_pdu(mac_nr_grant_dl_t& grant); + bool is_si_opportunity(); bool is_paging_opportunity(); diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index 2f5c331df..8b2c6c736 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -127,6 +127,11 @@ public: { // ignored, timing will be handled by EUTRA } + + void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id) final + { + mac_nr.prach_sent(tti, s_id, t_id, f_id, ul_carrier_id); + } #endif // Interface for GW diff --git a/srsue/hdr/stack/ue_stack_nr.h b/srsue/hdr/stack/ue_stack_nr.h index 4007dc74b..ab842b44b 100644 --- a/srsue/hdr/stack/ue_stack_nr.h +++ b/srsue/hdr/stack/ue_stack_nr.h @@ -74,13 +74,19 @@ public: void run_tti(uint32_t tti) final; // MAC interface for PHY - int sf_indication(const uint32_t tti) + uint16_t get_dl_sched_rnti(const uint32_t tti) { return mac->get_dl_sched_rnti(tti); } + uint16_t get_ul_sched_rnti(const uint32_t tti) { return mac->get_ul_sched_rnti(tti); } + int sf_indication(const uint32_t tti) { run_tti(tti); return SRSLTE_SUCCESS; } void tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) final { mac->tb_decoded(cc_idx, grant); } void new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant) final { mac->new_grant_ul(cc_idx, grant); } + void prach_sent(uint32_t tti, uint32_t s_id, uint32_t t_id, uint32_t f_id, uint32_t ul_carrier_id) + { + mac->prach_sent(tti, s_id, t_id, f_id, ul_carrier_id); + } // Interface for GW void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) final; diff --git a/srsue/src/stack/mac_nr/mac_nr.cc b/srsue/src/stack/mac_nr/mac_nr.cc index 24bb8d240..8160d50a3 100644 --- a/srsue/src/stack/mac_nr/mac_nr.cc +++ b/srsue/src/stack/mac_nr/mac_nr.cc @@ -11,6 +11,7 @@ */ #include "srsue/hdr/stack/mac_nr/mac_nr.h" +#include "srslte/mac/mac_rar_pdu_nr.h" namespace srsue { @@ -69,7 +70,7 @@ void mac_nr::run_tti(const uint32_t tti) logger.debug("Running MAC tti=%d", tti); } -uint16_t mac_nr::get_ul_sched_rnti(uint32_t tti) +uint16_t mac_nr::get_ul_sched_rnti(const uint32_t tti) { return crnti; } @@ -85,7 +86,7 @@ bool mac_nr::is_paging_opportunity() return false; } -uint16_t mac_nr::get_dl_sched_rnti(uint32_t tti) +uint16_t mac_nr::get_dl_sched_rnti(const uint32_t tti) { // Priority: SI-RNTI, P-RNTI, RA-RNTI, Temp-RNTI, CRNTI if (is_si_opportunity()) { @@ -141,6 +142,33 @@ int mac_nr::sf_indication(const uint32_t tti) return SRSLTE_SUCCESS; } +void mac_nr::prach_sent(const uint32_t tti, + const uint32_t s_id, + const uint32_t t_id, + const uint32_t f_id, + const uint32_t ul_carrier_id) +{ + // TODO: indicate to RA proc +} + +// This function handles all PCAP writing for a decoded DL TB +void mac_nr::write_pcap(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) +{ + if (pcap) { + for (uint32_t i = 0; i < SRSLTE_MAX_CODEWORDS; ++i) { + if (grant.tb[i] != nullptr) { + if (SRSLTE_RNTI_ISRAR(grant.rnti)) { // TODO: replace with proc_ra->get_rar_rnti() + pcap->write_dl_ra_rnti_nr(grant.tb[i]->msg, grant.tb[i]->N_bytes, grant.rnti, true, grant.tti); + } else if (grant.rnti == SRSLTE_PRNTI) { + pcap->write_dl_pch_nr(grant.tb[i]->msg, grant.tb[i]->N_bytes, grant.rnti, true, grant.tti); + } else { + pcap->write_dl_crnti_nr(grant.tb[i]->msg, grant.tb[i]->N_bytes, grant.rnti, true, grant.tti); + } + } + } + } +} + /** * \brief Called from PHY after decoding a TB * @@ -151,29 +179,46 @@ int mac_nr::sf_indication(const uint32_t tti) */ void mac_nr::tb_decoded(const uint32_t cc_idx, mac_nr_grant_dl_t& grant) { - if (SRSLTE_RNTI_ISRAR(grant.rnti)) { - // TODO: deliver to RA procedure - } else if (grant.rnti == SRSLTE_PRNTI) { - // Send PCH payload to RLC - // rlc->write_pdu_pcch(pch_payload_buffer, grant.tb[0].tbs); - - if (pcap) { - // pcap->write_dl_pch(pch_payload_buffer, grant.tb[0].tbs, true, grant.tti); - } + write_pcap(cc_idx, grant); + + // handle PDU + if (SRSLTE_RNTI_ISRAR(grant.rnti)) { // TODO: replace with proc_ra->get_rar_rnti() + // TODO: pass to RA proc + handle_rar_pdu(grant); } else { + // Push DL PDUs to queue for back-ground processing for (uint32_t i = 0; i < SRSLTE_MAX_CODEWORDS; ++i) { if (grant.tb[i] != nullptr) { - if (pcap) { - pcap->write_dl_crnti_nr(grant.tb[i]->msg, grant.tb[i]->N_bytes, grant.rnti, true, grant.tti); - } pdu_queue.push(std::move(grant.tb[i])); } } } + metrics[cc_idx].rx_pkts++; stack_task_dispatch_queue.push([this]() { process_pdus(); }); } +// Temporary helper until RA proc is complete +void mac_nr::handle_rar_pdu(mac_nr_grant_dl_t& grant) +{ + for (uint32_t i = 0; i < SRSLTE_MAX_CODEWORDS; ++i) { + if (grant.tb[i] != nullptr) { + srslte::mac_rar_pdu_nr pdu; + if (!pdu.unpack(grant.tb[i]->msg, grant.tb[i]->N_bytes)) { + logger.warning("Error unpacking RAR PDU"); + return; + } + logger.info(pdu.to_string()); + + for (auto& subpdu : pdu.get_subpdus()) { + if (subpdu.has_rapid() && subpdu.get_rapid() == 0 /* selected preamble */) { + phy->set_ul_grant(subpdu.get_ul_grant()); + } + } + } + } +} + void mac_nr::new_grant_ul(const uint32_t cc_idx, const mac_nr_grant_ul_t& grant) { phy_interface_stack_nr::tx_request_t tx_request = {};