From 6895bfa70aeee15db5b814aa46afc82a05392df3 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 16 Dec 2019 12:36:00 +0100 Subject: [PATCH] SRSUE initial PHY worker test --- srsue/test/phy/CMakeLists.txt | 17 +++ srsue/test/phy/phy_worker_test.cc | 233 ++++++++++++++++++++++++++++++ 2 files changed, 250 insertions(+) create mode 100644 srsue/test/phy/phy_worker_test.cc diff --git a/srsue/test/phy/CMakeLists.txt b/srsue/test/phy/CMakeLists.txt index 77dc5cff5..62f1beeae 100644 --- a/srsue/test/phy/CMakeLists.txt +++ b/srsue/test/phy/CMakeLists.txt @@ -29,6 +29,23 @@ link_directories( ${SEC_LIBRARY_DIRS} ) +add_executable(phy_worker_test phy_worker_test.cc) +target_link_libraries(phy_worker_test + srsue_phy + srsue_stack + srsue_upper + srsue_mac + srsue_rrc + srslte_common + srslte_phy + srslte_radio + srslte_upper + rrc_asn1 + ${CMAKE_THREAD_LIBS_INIT} + ${Boost_LIBRARIES}) +add_test(phy_worker_test phy_worker_test) + + add_executable(scell_search_test scell_search_test.cc) target_link_libraries(scell_search_test srsue_phy diff --git a/srsue/test/phy/phy_worker_test.cc b/srsue/test/phy/phy_worker_test.cc new file mode 100644 index 000000000..a606574bb --- /dev/null +++ b/srsue/test/phy/phy_worker_test.cc @@ -0,0 +1,233 @@ +/* + * Copyright 2013-2019 Software Radio Systems Limited + * + * This file is part of srsLTE. + * + * 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 + +class phy_test_bench +{ +private: + // Dummy classes + class dummy_stack : public srsue::stack_interface_phy_lte + { + private: + srslte::log_filter log_h; + uint16_t rnti = 0x3c; + + public: + // Local test access methods + explicit dummy_stack(srslte::logger& logger) : log_h("stack", &logger) {} + void set_rnti(uint16_t rnti_) { rnti = rnti_; } + + // Implemented methods + void in_sync() override { log_h.info("in-sync received\n"); } + void out_of_sync() override { log_h.info("out-of-sync received\n"); } + void new_phy_meas(float rsrp, float rsrq, uint32_t tti, int earfcn, int pci) override + { + log_h.info("New measurement earfcn=%d; pci=%d; rsrp=%+.1fdBm; rsrq=%+.1fdB;\n", earfcn, pci, rsrp, rsrq); + } + uint16_t get_dl_sched_rnti(uint32_t tti) override { return rnti; } + uint16_t get_ul_sched_rnti(uint32_t tti) override { return rnti; } + void new_grant_ul(uint32_t cc_idx, mac_grant_ul_t grant, tb_action_ul_t* action) override + { + action->tb.enabled = true; + } + void new_grant_dl(uint32_t cc_idx, mac_grant_dl_t grant, tb_action_dl_t* action) override + { + for (auto& i : action->tb) { + i.enabled = true; + } + } + void tb_decoded(uint32_t cc_idx, mac_grant_dl_t grant, bool* ack) override {} + void bch_decoded_ok(uint8_t* payload, uint32_t len) override {} + void mch_decoded(uint32_t len, bool crc) override {} + void new_mch_dl(srslte_pdsch_grant_t phy_grant, tb_action_dl_t* action) override {} + void set_mbsfn_config(uint32_t nof_mbsfn_services) override {} + void run_tti(const uint32_t tti) override { log_h.info("Run TTI %d\n", tti); } + }; + + class dummy_radio : public srslte::radio_interface_phy + { + private: + srslte::log_filter log_h; + std::vector ring_buffers; + float base_srate = 0.0f; + float tx_srate = 0.0f; + float rx_srate = 0.0f; + float rx_gain = 0.0f; + float tx_freq = 0.0f; + float rx_freq = 0.0f; + cf_t* temp_buffer = nullptr; + uint64_t rx_timestamp = 0; + + public: + dummy_radio(srslte::logger& logger, uint32_t nof_channels, float base_srate_) : + log_h("radio", &logger), + ring_buffers(nof_channels), + base_srate(base_srate_) + { + // Create Ring buffers + for (auto& rb : ring_buffers) { + if (srslte_ringbuffer_init(&rb, (uint32_t)sizeof(cf_t) * SRSLTE_SF_LEN_MAX)) { + perror("init softbuffer"); + } + } + + // Create temporal buffer + } + + void write_ring_buffers(cf_t** buffer, uint32_t nsamples) + { + for (uint32_t i = 0; i < ring_buffers.size(); i++) { + if (srslte_ringbuffer_write_timed(&ring_buffers[i], buffer[i], sizeof(cf_t) * nsamples, 1000) < 0) { + perror("writing ring buffer"); + } + } + } + + bool tx(const uint32_t& radio_idx, + cf_t** buffer, + const uint32_t& nof_samples, + const srslte_timestamp_t& tx_time) override + { + return false; + } + void tx_end() override {} + bool + rx_now(const uint32_t& radio_idx, cf_t** buffer, const uint32_t& nof_samples, srslte_timestamp_t* rxd_time) override + { + if (base_srate > rx_srate) { + // Decimate + uint32_t decimation = base_srate / rx_srate; + for (uint32_t i = 0; i < ring_buffers.size(); i++) { + } + } + return true; + } + void set_tx_freq(const uint32_t& radio_idx, const uint32_t& channel_idx, const double& freq) override + { + tx_freq = (float)freq; + } + void set_rx_freq(const uint32_t& radio_idx, const uint32_t& channel_idx, const double& freq) override + { + rx_freq = (float)freq; + } + float set_rx_gain_th(const float& gain) override + { + rx_gain = srslte_convert_dB_to_amplitude(gain); + return srslte_convert_amplitude_to_dB(rx_gain); + } + void set_rx_gain(const uint32_t& radio_idx, const float& gain) override + { + rx_gain = srslte_convert_dB_to_amplitude(gain); + } + void set_tx_srate(const uint32_t& radio_idx, const double& srate) override { tx_srate = (float)srate; } + void set_rx_srate(const uint32_t& radio_idx, const double& srate) override { rx_srate = (float)srate; } + float get_rx_gain(const uint32_t& radio_idx) override { return srslte_convert_amplitude_to_dB(rx_gain); } + double get_freq_offset() override { return 0; } + double get_tx_freq(const uint32_t& radio_idx) override { return tx_freq; } + double get_rx_freq(const uint32_t& radio_idx) override { return rx_freq; } + float get_max_tx_power() override { return 0; } + float get_tx_gain_offset() override { return 0; } + float get_rx_gain_offset() override { return 0; } + bool is_continuous_tx() override { return false; } + bool get_is_start_of_burst(const uint32_t& radio_idx) override { return false; } + bool is_init() override { return false; } + void reset() override {} + srslte_rf_info_t* get_info(const uint32_t& radio_idx) override { return nullptr; } + }; + + // Common instances + srslte::logger_stdout main_logger; + + // Dummy instances + dummy_stack stack; + dummy_radio radio; + + // Phy Instances + srsue::phy phy; + + // eNb + srslte_enb_dl_t enb_dl = {}; + cf_t* enb_dl_buffer[SRSLTE_MAX_PORTS] = {}; + srslte_dl_sf_cfg_t dl_sf_cfg = {}; + uint64_t sfn = 0; // System Frame Number + uint32_t sf_len = 0; + +public: + explicit phy_test_bench(const srsue::phy_args_t& phy_args, const srslte_cell_t& cell) : + stack(main_logger), + radio(main_logger, cell.nof_ports, srslte_sampling_freq_hz(cell.nof_prb)), + phy(&main_logger) + { + // Deduce physical attributes + sf_len = SRSLTE_SF_LEN_PRB(cell.nof_prb); + + // Initialise UE + phy.init(phy_args, &stack, &radio); + + // Initialise DL baseband buffers + for (uint32_t i = 0; i < phy_args.nof_rx_ant; i++) { + enb_dl_buffer[i] = srslte_vec_cf_malloc(sf_len); + if (!enb_dl_buffer[i]) { + perror("malloc"); + } + } + + // Initialise eNb DL + srslte_enb_dl_init(&enb_dl, enb_dl_buffer, cell.nof_prb); + srslte_enb_dl_set_cell(&enb_dl, cell); + } + + void run_dl_tti() + { + // Generate baseband signal + srslte_enb_dl_put_base(&enb_dl, &dl_sf_cfg); + + // Write baseband to radio + radio.write_ring_buffers(enb_dl_buffer, sf_len); + + // Increase TTI + dl_sf_cfg.tti++; + + // Increase System Frame number + if (dl_sf_cfg.tti >= 10240) { + dl_sf_cfg.tti = 0; + sfn++; + } + } +}; + +int main(int argc, char** argv) +{ + int ret = SRSLTE_SUCCESS; + srslte_cell_t cell = {.nof_prb = 6, + .nof_ports = 1, + .id = 1, + .cp = SRSLTE_CP_NORM, + .phich_length = SRSLTE_PHICH_NORM, + .phich_resources = SRSLTE_PHICH_R_1, + .frame_type = SRSLTE_FDD}; + srsue::phy_args_t phy_args = {}; + + phy_test_bench phy_test(phy_args, cell); + + return ret; +}