eNB transmits diversity by default if two cell ports are configured

This commit is contained in:
Xavier Arteaga 2017-10-10 13:24:23 +02:00
parent 51c2c041d7
commit e8da7160f0
21 changed files with 137 additions and 100 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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];

View File

@ -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)

View File

@ -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)

View File

@ -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;

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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];

View File

@ -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());

View File

@ -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");

View File

@ -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);
}
}

View File

@ -75,9 +75,11 @@ void parse_args(all_args_t *args, int argc, char* argv[]) {
("enb.mnc", bpo::value<string>(&mnc)->default_value("01"), "Mobile Network Code")
("enb.mme_addr", bpo::value<string>(&args->enb.s1ap.mme_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connnection")
("enb.gtp_bind_addr", bpo::value<string>(&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<uint32_t>(&args->enb.pci)->default_value(0), "Physical Cell Identity (PCI)")
("enb.phy_cell_id", bpo::value<uint32_t>(&args->enb.pci)->default_value(0), "Physical Cell Identity (PCI)")
("enb.n_prb", bpo::value<uint32_t>(&args->enb.n_prb)->default_value(25), "Number of PRB")
("enb.nof_ports", bpo::value<uint32_t>(&args->enb.nof_ports)->default_value(1), "Number of ports")
("enb.tm", bpo::value<uint32_t>(&args->enb.transmission_mode)->default_value(1), "Transmission mode (1-8)")
("enb_files.sib_config", bpo::value<string>(&args->enb_files.sib_config)->default_value("sib.conf"), "SIB configuration files")
("enb_files.rr_config", bpo::value<string>(&args->enb_files.rr_config)->default_value("rr.conf"), "RR configuration files")
("enb_files.drb_config", bpo::value<string>(&args->enb_files.drb_config)->default_value("drb.conf"), "DRB configuration files")

View File

@ -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]);

View File

@ -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;i<nof_grants;i++) {
uint16_t rnti = grants[i].rnti;
if (rnti) {
@ -676,25 +681,21 @@ int phch_worker::encode_pdsch(srslte_enb_dl_pdsch_t *grants, uint32_t nof_grants
if (LOG_THIS(rnti)) {
uint8_t x = 0;
uint8_t *ptr = grants[i].data;
uint8_t *ptr = grants[i].data[0];
uint32_t len = phy_grant.mcs[0].tbs / (uint32_t) 8;
if (!ptr) {
ptr = &x;
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",
"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;
}

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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",