diff --git a/lib/include/srslte/phy/enb/enb_dl.h b/lib/include/srslte/phy/enb/enb_dl.h index 7c3166e5c..b63cb6416 100644 --- a/lib/include/srslte/phy/enb/enb_dl.h +++ b/lib/include/srslte/phy/enb/enb_dl.h @@ -97,8 +97,8 @@ typedef struct { uint16_t rnti; srslte_ra_dl_dci_t grant; srslte_dci_location_t location; - srslte_softbuffer_tx_t *softbuffer; - uint8_t *data; + srslte_softbuffer_tx_t *softbuffers[SRSLTE_MAX_TB]; + uint8_t *data[SRSLTE_MAX_TB]; } srslte_enb_dl_pdsch_t; typedef struct { @@ -147,7 +147,7 @@ SRSLTE_API void srslte_enb_dl_put_base(srslte_enb_dl_t *q, uint32_t tti); SRSLTE_API void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q, - cf_t *signal_buffer); + cf_t *signal_buffer[SRSLTE_MAX_PORTS]); SRSLTE_API int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q, uint16_t rnti); diff --git a/lib/include/srslte/phy/rf/rf.h b/lib/include/srslte/phy/rf/rf.h index 860e0a257..c171e69d1 100644 --- a/lib/include/srslte/phy/rf/rf.h +++ b/lib/include/srslte/phy/rf/rf.h @@ -73,16 +73,12 @@ SRSLTE_API int srslte_rf_open(srslte_rf_t *h, SRSLTE_API int srslte_rf_open_multi(srslte_rf_t *h, char *args, - uint32_t nof_rx_antennas); + uint32_t nof_channels); SRSLTE_API int srslte_rf_open_devname(srslte_rf_t *h, char *devname, - char *args); - -SRSLTE_API int srslte_rf_open_devname_multi(srslte_rf_t *h, - char *devname, - char *args, - uint32_t nof_rx_antennas); + char *args, + uint32_t nof_channels); SRSLTE_API const char *srslte_rf_name(srslte_rf_t *h); diff --git a/lib/include/srslte/radio/radio.h b/lib/include/srslte/radio/radio.h index 329dd825a..2a34bd9a9 100644 --- a/lib/include/srslte/radio/radio.h +++ b/lib/include/srslte/radio/radio.h @@ -74,7 +74,7 @@ namespace srslte { agc_enabled = false; }; - bool init(char *args = NULL, char *devname = NULL); + bool init(char *args = NULL, char *devname = NULL, uint32_t nof_channels = 1); void stop(); void reset(); bool start_agc(bool tx_gain_same_rx); @@ -86,9 +86,10 @@ namespace srslte { void set_manual_calibration(rf_cal_t *calibration); void get_time(srslte_timestamp_t *now); - bool tx(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time); + bool tx_single(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time); + bool tx(void *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time); void tx_end(); - bool rx_now(void *buffer, uint32_t nof_samples, srslte_timestamp_t *rxd_time); + bool rx_now(void *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t *rxd_time); bool rx_at(void *buffer, uint32_t nof_samples, srslte_timestamp_t rx_time); void set_tx_gain(float gain); @@ -166,6 +167,7 @@ namespace srslte { uint32_t tti; bool agc_enabled; + uint32_t saved_nof_channels; char saved_args[128]; char saved_devname[128]; diff --git a/lib/src/phy/enb/enb_dl.c b/lib/src/phy/enb/enb_dl.c index 2ba179399..7b2723765 100644 --- a/lib/src/phy/enb/enb_dl.c +++ b/lib/src/phy/enb/enb_dl.c @@ -264,14 +264,15 @@ void srslte_enb_dl_put_base(srslte_enb_dl_t *q, uint32_t tti) } -void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q, cf_t *signal_buffer) +void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q, cf_t *signal_buffer[SRSLTE_MAX_PORTS]) { - - srslte_ofdm_tx_sf(&q->ifft, q->sf_symbols[0], signal_buffer); - // TODO: PAPR control float norm_factor = (float) sqrt(q->cell.nof_prb)/15; - srslte_vec_sc_prod_cfc(signal_buffer, q->tx_amp*norm_factor, signal_buffer, SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); + + for (int p = 0; p < SRSLTE_MAX_PORTS; p++) { + srslte_ofdm_tx_sf(&q->ifft, q->sf_symbols[p], signal_buffer[p]); + srslte_vec_sc_prod_cfc(signal_buffer[p], q->tx_amp*norm_factor, signal_buffer[p], (uint32_t) SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); + } } int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q, uint16_t rnti) diff --git a/lib/src/phy/rf/rf_imp.c b/lib/src/phy/rf/rf_imp.c index c1074ebc5..7149cec9d 100644 --- a/lib/src/phy/rf/rf_imp.c +++ b/lib/src/phy/rf/rf_imp.c @@ -98,11 +98,7 @@ const char* srslte_rf_get_devname(srslte_rf_t *rf) { return ((rf_dev_t*) rf->dev)->name; } -int srslte_rf_open_devname(srslte_rf_t *rf, char *devname, char *args) { - return srslte_rf_open_devname_multi(rf, devname, args, 1); -} - -int srslte_rf_open_devname_multi(srslte_rf_t *rf, char *devname, char *args, uint32_t nof_channels) { +int srslte_rf_open_devname(srslte_rf_t *rf, char *devname, char *args, uint32_t nof_channels) { /* Try to open the device if name is provided */ if (devname) { if (devname[0] != '\0') { @@ -186,12 +182,12 @@ void srslte_rf_register_error_handler(srslte_rf_t *rf, srslte_rf_error_handler_t int srslte_rf_open(srslte_rf_t *h, char *args) { - return srslte_rf_open_devname_multi(h, NULL, args, 1); + return srslte_rf_open_devname(h, NULL, args, 1); } -int srslte_rf_open_multi(srslte_rf_t *h, char *args, uint32_t nof_rx_antennas) +int srslte_rf_open_multi(srslte_rf_t *h, char *args, uint32_t nof_channels) { - return srslte_rf_open_devname_multi(h, NULL, args, nof_rx_antennas); + return srslte_rf_open_devname(h, NULL, args, nof_channels); } int srslte_rf_close(srslte_rf_t *rf) diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index b393a3ff4..c6abb8642 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -34,9 +34,9 @@ extern "C" { namespace srslte { -bool radio::init(char *args, char *devname) +bool radio::init(char *args, char *devname, uint32_t nof_channels) { - if (srslte_rf_open_devname(&rf_device, devname, args)) { + if (srslte_rf_open_devname(&rf_device, devname, args, nof_channels)) { fprintf(stderr, "Error opening RF device\n"); return false; } @@ -68,6 +68,7 @@ bool radio::init(char *args, char *devname) if (devname) { strncpy(saved_devname, devname, 128); } + saved_nof_channels = nof_channels; return true; } @@ -82,7 +83,7 @@ void radio::reset() printf("Resetting Radio...\n"); srslte_rf_close(&rf_device); sleep(3); - if (srslte_rf_open_devname(&rf_device, saved_devname, saved_args)) { + if (srslte_rf_open_devname(&rf_device, saved_devname, saved_args, saved_nof_channels)) { fprintf(stderr, "Error opening RF device\n"); } } @@ -137,9 +138,9 @@ bool radio::rx_at(void* buffer, uint32_t nof_samples, srslte_timestamp_t rx_time return false; } -bool radio::rx_now(void* buffer, uint32_t nof_samples, srslte_timestamp_t* rxd_time) +bool radio::rx_now(void* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t* rxd_time) { - if (srslte_rf_recv_with_time(&rf_device, buffer, nof_samples, true, + if (srslte_rf_recv_with_time_multi(&rf_device, buffer, nof_samples, true, rxd_time?&rxd_time->full_secs:NULL, rxd_time?&rxd_time->frac_secs:NULL) > 0) { return true; } else { @@ -186,10 +187,18 @@ bool radio::is_first_of_burst() { #define BLOCKING_TX true -bool radio::tx(void* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) -{ - void *iq_samples[4] = {(void *) zeros, (void *) zeros, (void *) zeros, (void *) zeros}; +bool radio::tx_single(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) { + void *_buffer[SRSLTE_MAX_PORTS]; + _buffer[0] = buffer; + for (int p = 1; p < SRSLTE_MAX_PORTS; p++) { + _buffer[p] = zeros; + } + + return this->tx(_buffer, nof_samples, tx_time); +} + +bool radio::tx(void *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time) { if (!tx_adv_negative) { srslte_timestamp_sub(&tx_time, 0, tx_adv_sec); } else { @@ -202,7 +211,7 @@ bool radio::tx(void* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) srslte_timestamp_copy(&tx_time_pad, &tx_time); srslte_timestamp_sub(&tx_time_pad, 0, burst_preamble_time_rounded); save_trace(1, &tx_time_pad); - srslte_rf_send_timed_multi(&rf_device, iq_samples, burst_preamble_samples, tx_time_pad.full_secs, tx_time_pad.frac_secs, true, true, false); + srslte_rf_send_timed_multi(&rf_device, buffer, burst_preamble_samples, tx_time_pad.full_secs, tx_time_pad.frac_secs, true, true, false); is_start_of_burst = false; } } @@ -212,8 +221,7 @@ bool radio::tx(void* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) srslte_timestamp_add(&end_of_burst_time, 0, (double) nof_samples/cur_tx_srate); save_trace(0, &tx_time); - iq_samples[0] = buffer; - int ret = srslte_rf_send_timed_multi(&rf_device, (void**) iq_samples, nof_samples, + int ret = srslte_rf_send_timed_multi(&rf_device, buffer, nof_samples, tx_time.full_secs, tx_time.frac_secs, BLOCKING_TX, is_start_of_burst, false); is_start_of_burst = false; diff --git a/lib/src/radio/radio_multi.cc b/lib/src/radio/radio_multi.cc index 018a675ac..2ec7f891c 100644 --- a/lib/src/radio/radio_multi.cc +++ b/lib/src/radio/radio_multi.cc @@ -4,7 +4,7 @@ namespace srslte { bool radio_multi::init_multi(uint32_t nof_rx_antennas, char* args, char* devname) { - if (srslte_rf_open_devname_multi(&rf_device, devname, args, nof_rx_antennas)) { + if (srslte_rf_open_devname(&rf_device, devname, args, nof_rx_antennas)) { fprintf(stderr, "Error opening RF device\n"); return false; } diff --git a/srsenb/hdr/enb.h b/srsenb/hdr/enb.h index 7b1681cd6..c40fcebf4 100644 --- a/srsenb/hdr/enb.h +++ b/srsenb/hdr/enb.h @@ -66,6 +66,8 @@ typedef struct { s1ap_args_t s1ap; uint32_t n_prb; uint32_t pci; + uint32_t nof_ports; + uint32_t transmission_mode; }enb_args_t; typedef struct { diff --git a/srsenb/hdr/phy/phch_common.h b/srsenb/hdr/phy/phch_common.h index 00a59d969..391d8932e 100644 --- a/srsenb/hdr/phy/phch_common.h +++ b/srsenb/hdr/phy/phch_common.h @@ -65,7 +65,7 @@ public: void set_nof_mutex(uint32_t nof_mutex); - void worker_end(uint32_t tx_mutex_cnt, cf_t *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time); + void worker_end(uint32_t tx_mutex_cnt, cf_t *buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time); // Common objects srslte_cell_t cell; diff --git a/srsenb/hdr/phy/phch_worker.h b/srsenb/hdr/phy/phch_worker.h index 906e8b9d0..42e36113d 100644 --- a/srsenb/hdr/phy/phch_worker.h +++ b/srsenb/hdr/phy/phch_worker.h @@ -45,7 +45,7 @@ public: void stop(); void reset(); - cf_t *get_buffer_rx(); + cf_t *get_buffer_rx(uint32_t antenna_idx); void set_time(uint32_t tti, uint32_t tx_mutex_cnt, srslte_timestamp_t tx_time); int add_rnti(uint16_t rnti); @@ -87,8 +87,8 @@ private: bool initiated; bool running; - cf_t *signal_buffer_rx; - cf_t *signal_buffer_tx; + cf_t *signal_buffer_rx[SRSLTE_MAX_PORTS]; + cf_t *signal_buffer_tx[SRSLTE_MAX_PORTS]; uint32_t tti_rx, tti_tx, tti_sched_ul, sf_rx, sf_tx, sf_sched_ul, tx_mutex_cnt; srslte_enb_dl_t enb_dl; diff --git a/srsenb/hdr/upper/rrc.h b/srsenb/hdr/upper/rrc.h index e0b9dd158..2ea07a749 100644 --- a/srsenb/hdr/upper/rrc.h +++ b/srsenb/hdr/upper/rrc.h @@ -79,6 +79,7 @@ typedef struct { LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_STRUCT sibs[LIBLTE_RRC_MAX_SIB]; LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT mac_cnfg; LIBLTE_RRC_PUSCH_CONFIG_DEDICATED_STRUCT pusch_cfg; + LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT antenna_info; rrc_cfg_sr_t sr_cfg; rrc_cfg_cqi_t cqi_cfg; rrc_cfg_qci_t qci_cfg[MAX_NOF_QCI]; diff --git a/srsenb/src/enb.cc b/srsenb/src/enb.cc index 82b4e8145..fad7e1528 100644 --- a/srsenb/src/enb.cc +++ b/srsenb/src/enb.cc @@ -136,7 +136,7 @@ bool enb::init(all_args_t *args_) dev_args = (char*) args->rf.device_args.c_str(); } - if(!radio.init(dev_args, dev_name)) + if(!radio.init(dev_args, dev_name, args->enb.nof_ports)) { printf("Failed to find device %s with args %s\n", args->rf.device_name.c_str(), args->rf.device_args.c_str()); diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 3beb85a65..a7734cd0c 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -37,7 +37,7 @@ namespace srsenb { int enb::parse_cell_cfg(all_args_t *args, srslte_cell_t *cell) { cell->id = args->enb.pci; cell->cp = SRSLTE_CP_NORM; - cell->nof_ports = 1; + cell->nof_ports = args->enb.nof_ports; cell->nof_prb = args->enb.n_prb; LIBLTE_RRC_PHICH_CONFIG_STRUCT phichcfg; @@ -842,6 +842,30 @@ bool enb::sib_is_present(LIBLTE_RRC_SCHEDULING_INFO_STRUCT *sched_info, uint32_t int enb::parse_rr(all_args_t* args, rrc_cfg_t* rrc_cfg) { + + /* Transmission mode config section */ + if (args->enb.transmission_mode < 0 || args->enb.transmission_mode > LIBLTE_RRC_TRANSMISSION_MODE_N_ITEMS) { + ERROR("Invalid transmission mode (%d). Only indexes 1-4 are implemented.\n", args->enb.transmission_mode); + return SRSLTE_ERROR; + } + + bzero(&rrc_cfg->antenna_info, sizeof(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT)); + rrc_cfg->antenna_info.tx_mode = (LIBLTE_RRC_TRANSMISSION_MODE_ENUM) (args->enb.transmission_mode - 1); + + if (rrc_cfg->antenna_info.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { + rrc_cfg->antenna_info.ue_tx_antenna_selection_setup = LIBLTE_RRC_UE_TX_ANTENNA_SELECTION_OPEN_LOOP; + rrc_cfg->antenna_info.ue_tx_antenna_selection_setup_present = true; + + rrc_cfg->antenna_info.codebook_subset_restriction_choice = LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM3; + } else if (rrc_cfg->antenna_info.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + rrc_cfg->antenna_info.ue_tx_antenna_selection_setup = LIBLTE_RRC_UE_TX_ANTENNA_SELECTION_CLOSED_LOOP; + rrc_cfg->antenna_info.ue_tx_antenna_selection_setup_present = true; + + rrc_cfg->antenna_info.codebook_subset_restriction_choice = LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM4; + rrc_cfg->antenna_info.codebook_subset_restriction = 0b111111; + rrc_cfg->antenna_info.codebook_subset_restriction_present = true; + } + /* MAC config section */ parser::section mac_cnfg("mac_cnfg"); diff --git a/srsenb/src/mac/mac.cc b/srsenb/src/mac/mac.cc index 6c8458540..796d08025 100644 --- a/srsenb/src/mac/mac.cc +++ b/srsenb/src/mac/mac.cc @@ -434,20 +434,20 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) 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)); - dl_sched_res->sched_grants[n].softbuffer = ue_db[rnti]->get_tx_softbuffer(sched_result.data[i].dci.harq_process); + dl_sched_res->sched_grants[n].softbuffers[0] = ue_db[rnti]->get_tx_softbuffer(sched_result.data[i].dci.harq_process); // Get PDU if it's a new transmission if (sched_result.data[i].nof_pdu_elems > 0) { - dl_sched_res->sched_grants[n].data = ue_db[rnti]->generate_pdu(sched_result.data[i].pdu, + 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); if (pcap) { - pcap->write_dl_crnti(dl_sched_res->sched_grants[n].data, 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, rnti, true, tti); } } else { - dl_sched_res->sched_grants[n].data = NULL; + dl_sched_res->sched_grants[n].data[0] = NULL; } n++; } @@ -460,14 +460,14 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) memcpy(&dl_sched_res->sched_grants[n].location, &sched_result.rar[i].dci_location, sizeof(srslte_dci_location_t)); // Set softbuffer (there are no retx in RAR but a softbuffer is required) - dl_sched_res->sched_grants[n].softbuffer = &rar_softbuffer_tx; + dl_sched_res->sched_grants[n].softbuffers[0] = &rar_softbuffer_tx; // Assemble PDU - dl_sched_res->sched_grants[n].data = assemble_rar(sched_result.rar[i].grants, sched_result.rar[i].nof_grants, i, sched_result.rar[i].tbs); + dl_sched_res->sched_grants[n].data[0] = assemble_rar(sched_result.rar[i].grants, sched_result.rar[i].nof_grants, i, sched_result.rar[i].tbs); if (pcap) { - pcap->write_dl_ranti(dl_sched_res->sched_grants[n].data, 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, dl_sched_res->sched_grants[n].rnti, true, tti); } n++; @@ -482,20 +482,20 @@ int mac::get_dl_sched(uint32_t tti, dl_sched_t *dl_sched_res) // Set softbuffer if (sched_result.bc[i].type == sched_interface::dl_sched_bc_t::BCCH) { - dl_sched_res->sched_grants[n].softbuffer = &bcch_softbuffer_tx[sched_result.bc[i].index]; - dl_sched_res->sched_grants[n].data = assemble_si(sched_result.bc[i].index); + dl_sched_res->sched_grants[n].softbuffers[0] = &bcch_softbuffer_tx[sched_result.bc[i].index]; + dl_sched_res->sched_grants[n].data[0] = assemble_si(sched_result.bc[i].index); #ifdef WRITE_SIB_PCAP if (pcap) { pcap->write_dl_sirnti(dl_sched_res->sched_grants[n].data, sched_result.bc[i].tbs, true, tti); } #endif } else { - dl_sched_res->sched_grants[n].softbuffer = &pcch_softbuffer_tx; - dl_sched_res->sched_grants[n].data = pcch_payload_buffer; + dl_sched_res->sched_grants[n].softbuffers[0] = &pcch_softbuffer_tx; + dl_sched_res->sched_grants[n].data[0] = pcch_payload_buffer; rlc_h->read_pdu_pcch(pcch_payload_buffer, pcch_payload_buffer_len); if (pcap) { - pcap->write_dl_pch(dl_sched_res->sched_grants[n].data, sched_result.bc[i].tbs, true, tti); + pcap->write_dl_pch(dl_sched_res->sched_grants[n].data[0], sched_result.bc[i].tbs, true, tti); } } diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 528878388..7978e6ddc 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -75,9 +75,11 @@ void parse_args(all_args_t *args, int argc, char* argv[]) { ("enb.mnc", bpo::value(&mnc)->default_value("01"), "Mobile Network Code") ("enb.mme_addr", bpo::value(&args->enb.s1ap.mme_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connnection") ("enb.gtp_bind_addr", bpo::value(&args->enb.s1ap.gtp_bind_addr)->default_value("192.168.3.1"), "Local IP address to bind for GTP connection") - ("enb.phy_cell_id", bpo::value(&args->enb.pci)->default_value(0), "Physical Cell Identity (PCI)") + ("enb.phy_cell_id", bpo::value(&args->enb.pci)->default_value(0), "Physical Cell Identity (PCI)") ("enb.n_prb", bpo::value(&args->enb.n_prb)->default_value(25), "Number of PRB") - + ("enb.nof_ports", bpo::value(&args->enb.nof_ports)->default_value(1), "Number of ports") + ("enb.tm", bpo::value(&args->enb.transmission_mode)->default_value(1), "Transmission mode (1-8)") + ("enb_files.sib_config", bpo::value(&args->enb_files.sib_config)->default_value("sib.conf"), "SIB configuration files") ("enb_files.rr_config", bpo::value(&args->enb_files.rr_config)->default_value("rr.conf"), "RR configuration files") ("enb_files.drb_config", bpo::value(&args->enb_files.drb_config)->default_value("drb.conf"), "DRB configuration files") diff --git a/srsenb/src/phy/phch_common.cc b/srsenb/src/phy/phch_common.cc index e4d91581e..545ad576e 100644 --- a/srsenb/src/phy/phch_common.cc +++ b/srsenb/src/phy/phch_common.cc @@ -74,7 +74,7 @@ void phch_common::stop() { } } -void phch_common::worker_end(uint32_t tx_mutex_cnt, cf_t* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) +void phch_common::worker_end(uint32_t tx_mutex_cnt, cf_t* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time) { // Wait previous TTIs to be transmitted @@ -84,8 +84,8 @@ void phch_common::worker_end(uint32_t tx_mutex_cnt, cf_t* buffer, uint32_t nof_s pthread_mutex_lock(&tx_mutex[tx_mutex_cnt%nof_mutex]); } - radio->set_tti(tx_mutex_cnt); - radio->tx(buffer, nof_samples, tx_time); + radio->set_tti(tx_mutex_cnt); + radio->tx((void **) buffer, nof_samples, tx_time); // Trigger next transmission pthread_mutex_unlock(&tx_mutex[(tx_mutex_cnt+1)%nof_mutex]); diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 3a1fb8ca4..7b547c944 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -88,15 +88,17 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_) pthread_mutex_init(&mutex, NULL); // Init cell here - signal_buffer_rx = (cf_t*) srslte_vec_malloc(2*SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t)); - if (!signal_buffer_rx) { - fprintf(stderr, "Error allocating memory\n"); - return; - } - signal_buffer_tx = (cf_t*) srslte_vec_malloc(2*SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t)); - if (!signal_buffer_tx) { - fprintf(stderr, "Error allocating memory\n"); - return; + for(int p = 0; p < SRSLTE_MAX_PORTS; p++) { + signal_buffer_rx[p] = (cf_t *) srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); + if (!signal_buffer_rx) { + fprintf(stderr, "Error allocating memory\n"); + return; + } + signal_buffer_tx[p] = (cf_t *) srslte_vec_malloc(2 * SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t)); + if (!signal_buffer_tx) { + fprintf(stderr, "Error allocating memory\n"); + return; + } } if (srslte_enb_dl_init(&enb_dl, phy->cell.nof_prb)) { fprintf(stderr, "Error initiating ENB DL\n"); @@ -168,9 +170,9 @@ void phch_worker::reset() ue_db.clear(); } -cf_t* phch_worker::get_buffer_rx() +cf_t* phch_worker::get_buffer_rx(uint32_t antenna_idx) { - return signal_buffer_rx; + return signal_buffer_rx[antenna_idx]; } void phch_worker::set_time(uint32_t tti_, uint32_t tx_mutex_cnt_, srslte_timestamp_t tx_time_) @@ -287,7 +289,7 @@ void phch_worker::work_imp() } // Process UL signal - srslte_enb_ul_fft(&enb_ul, signal_buffer_rx); + srslte_enb_ul_fft(&enb_ul, signal_buffer_rx[0]); // Decode pending UL grants for the tti they were scheduled decode_pusch(ul_grants[sf_rx].sched_grants, ul_grants[sf_rx].nof_grants, sf_rx); @@ -649,6 +651,9 @@ int phch_worker::encode_pdcch_dl(srslte_enb_dl_pdsch_t *grants, uint32_t nof_gra int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants, uint32_t sf_idx) { + /* FIXME: currently, it assumes TM1, TM2 or TM3 */ + srslte_mimo_type_t mimo_type = (enb_dl.cell.nof_ports == 1) ? SRSLTE_MIMO_TYPE_SINGLE_ANTENNA : SRSLTE_MIMO_TYPE_TX_DIVERSITY; + for (uint32_t i=0;iinfo_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\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); } - srslte_softbuffer_tx_t *sb[SRSLTE_MAX_CODEWORDS] = {grants[i].softbuffer, NULL}; - uint8_t *d[SRSLTE_MAX_CODEWORDS] = {grants[i].data, NULL}; - int rv[SRSLTE_MAX_CODEWORDS] = {grants[i].grant.rv_idx, 0}; + 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, sb, rnti, rv, sf_idx, d, SRSLTE_MIMO_TYPE_SINGLE_ANTENNA, 0)) - { + if (srslte_enb_dl_put_pdsch(&enb_dl, &phy_grant, grants[i].softbuffers, rnti, rv, sf_idx, grants[i].data, mimo_type, 0)) { fprintf(stderr, "Error putting PDSCH %d\n",i); return SRSLTE_ERROR; } diff --git a/srsenb/src/phy/txrx.cc b/srsenb/src/phy/txrx.cc index 9427e3459..2a6929a20 100644 --- a/srsenb/src/phy/txrx.cc +++ b/srsenb/src/phy/txrx.cc @@ -77,7 +77,7 @@ void txrx::stop() void txrx::run_thread() { phch_worker *worker = NULL; - cf_t *buffer = NULL; + cf_t *buffer[SRSLTE_MAX_PORTS] = {NULL}; srslte_timestamp_t rx_time, tx_time; uint32_t sf_len = SRSLTE_SF_LEN_PRB(worker_com->cell.nof_prb); @@ -108,10 +108,12 @@ void txrx::run_thread() while (running) { tti = (tti+1)%10240; worker = (phch_worker*) workers_pool->wait_worker(tti); - if (worker) { - buffer = worker->get_buffer_rx(); + if (worker) { + for (int p = 0; p < SRSLTE_MAX_PORTS; p++){ + buffer[p] = worker->get_buffer_rx(p); + } - radio_h->rx_now(buffer, sf_len, &rx_time); + radio_h->rx_now((void **) buffer, sf_len, &rx_time); /* Compute TX time: Any transmission happens in TTI+4 thus advance 4 ms the reception time */ srslte_timestamp_copy(&tx_time, &rx_time); @@ -129,7 +131,7 @@ void txrx::run_thread() workers_pool->start_worker(worker); // Trigger prach worker execution - prach->new_tti(tti, buffer); + prach->new_tti(tti, buffer[0]); } else { // wait_worker() only returns NULL if it's being closed. Quit now to avoid unnecessary loops here diff --git a/srsue/hdr/phy/prach.h b/srsue/hdr/phy/prach.h index 67ccc0c94..2872c374c 100644 --- a/srsue/hdr/phy/prach.h +++ b/srsue/hdr/phy/prach.h @@ -45,11 +45,11 @@ namespace srsue { args = NULL; config = NULL; - signal_buffer = NULL; transmitted_tti = 0; target_power_dbm = 0; mem_initiated = false; cell_initiated = false; + bzero(signal_buffer, sizeof(signal_buffer)); } ~prach(); void init(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config, uint32_t max_prb, phy_args_t *args, srslte::log *log_h); @@ -78,7 +78,7 @@ namespace srsue { srslte_prach_t prach_obj; int transmitted_tti; srslte_cell_t cell; - cf_t *signal_buffer; + cf_t *signal_buffer[SRSLTE_MAX_PORTS]; srslte_cfo_t cfo_h; float target_power_dbm; diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index d49b1ced2..4a2f8a441 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -237,12 +237,12 @@ void phch_common::worker_end(uint32_t tti, bool tx_enable, radio_h->set_tti(tti); if (tx_enable) { - radio_h->tx(buffer, nof_samples, tx_time); + radio_h->tx_single(buffer, nof_samples, tx_time); is_first_of_burst = false; } else { if (TX_MODE_CONTINUOUS) { if (!is_first_of_burst) { - radio_h->tx(zeros, nof_samples, tx_time); + radio_h->tx_single(zeros, nof_samples, tx_time); } } else { if (!is_first_of_burst) { diff --git a/srsue/src/phy/prach.cc b/srsue/src/phy/prach.cc index 7c693fe7a..bd7550457 100644 --- a/srsue/src/phy/prach.cc +++ b/srsue/src/phy/prach.cc @@ -75,10 +75,12 @@ void prach::init(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config_, uint32_t max_prb, return; } srslte_cfo_set_tol(&cfo_h, 0); - signal_buffer = (cf_t*) srslte_vec_malloc(SRSLTE_PRACH_MAX_LEN*sizeof(cf_t)); - if (!signal_buffer) { - perror("malloc"); - return; + for (int p = 0; p < SRSLTE_MAX_PORTS; p++) { + signal_buffer[p] = (cf_t *) srslte_vec_malloc(SRSLTE_PRACH_MAX_LEN * sizeof(cf_t)); + if (!signal_buffer[p]) { + perror("malloc"); + return; + } } if (srslte_prach_init(&prach_obj, srslte_symbol_sz(max_prb))) { Error("Initiating PRACH library\n"); @@ -181,8 +183,8 @@ void prach::send(srslte::radio *radio_handler, float cfo, float pathloss, srslte // Get current TX gain float old_gain = radio_handler->get_tx_gain(); - // Correct CFO before transmission - srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, cfo / srslte_symbol_sz(cell.nof_prb)); + // Correct CFO before transmission FIXME: UL SISO Only + srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer[0], cfo / srslte_symbol_sz(cell.nof_prb)); // If power control is enabled, choose amplitude and power if (args->ul_pwr_ctrl_en) { @@ -193,10 +195,10 @@ void prach::send(srslte::radio *radio_handler, float cfo, float pathloss, srslte radio_handler->set_tx_power(tx_power); // Scale signal - float digital_power = srslte_vec_avg_power_cf(signal_buffer, len); + float digital_power = srslte_vec_avg_power_cf(signal_buffer[0], len); float scale = sqrtf(pow(10,tx_power/10)/digital_power); - srslte_vec_sc_prod_cfc(signal_buffer, scale, signal_buffer, len); + srslte_vec_sc_prod_cfc(signal_buffer[0], scale, signal_buffer[0], len); log_h->console("PRACH: Pathloss=%.2f dB, Target power %.2f dBm, TX_power %.2f dBm, TX_gain %.1f dB\n", pathloss, target_power_dbm, tx_power, radio_handler->get_tx_gain(), scale); @@ -207,8 +209,8 @@ void prach::send(srslte::radio *radio_handler, float cfo, float pathloss, srslte } Debug("TX PRACH: Power control for PRACH is disabled, setting gain to %.0f dB\n", prach_gain); } - - radio_handler->tx(signal_buffer, len, tx_time); + + radio_handler->tx((void **) signal_buffer, len, tx_time); radio_handler->tx_end(); Info("PRACH: Transmitted preamble=%d, CFO=%.2f KHz, tx_time=%f\n",