diff --git a/executables/lte-ru.c b/executables/lte-ru.c index 8d54d13ded..80a4162f00 100644 --- a/executables/lte-ru.c +++ b/executables/lte-ru.c @@ -742,7 +742,8 @@ void tx_rf(RU_t *ru, if ((SF_type == SF_DL) || (SF_type == SF_S) ) { - int siglen=fp->samples_per_tti,flags=1; + int siglen=fp->samples_per_tti; + radio_tx_burst_flag_t flags = TX_BURST_MIDDLE; if (SF_type == SF_S) { int txsymb = fp->dl_symbols_in_S_subframe+(ru->is_slave==0 ? 1 : 0); @@ -757,13 +758,13 @@ void tx_rf(RU_t *ru, siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples) + ru->end_of_burst_delay; - flags=3; // end of burst + flags = TX_BURST_END; } if (fp->frame_type == TDD && SF_type == SF_DL && prevSF_type == SF_UL) { - flags = 2; // start of burst + flags = TX_BURST_START; sf_extension = ru->sf_extension; } @@ -781,24 +782,24 @@ void tx_rf(RU_t *ru, LOG_E(PHY,"%d.%d late_control : %d\n",frame,subframe,late_control); switch (late_control) { case STATE_BURST_TERMINATE: - flags=10; // end of burst and no time spec + flags = TX_BURST_END_NO_TIME_SPEC; late_control=STATE_BURST_STOP_1; break; case STATE_BURST_STOP_1: - flags=0; // no send + flags = TX_BURST_INVALID; late_control=STATE_BURST_STOP_2; return;//no send break; case STATE_BURST_STOP_2: - flags=0; // no send + flags = TX_BURST_INVALID; late_control=STATE_BURST_RESTART; return;//no send break; case STATE_BURST_RESTART: - flags=2; // start burst + flags = TX_BURST_START; late_control=STATE_BURST_NORMAL; break; diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 8cd23b7159..2912ec7648 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -694,7 +694,8 @@ void ocp_tx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { if ((SF_type == SF_DL) || (SF_type == SF_S)) { - int siglen=fp->samples_per_tti,flags=1; + int siglen=fp->samples_per_tti; + radio_tx_burst_flag_t flags = TX_BURST_MIDDLE; if (SF_type == SF_S) { /* end_of_burst_delay is used to stop TX only "after a while". @@ -707,13 +708,13 @@ void ocp_tx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (fp->dl_symbols_in_S_subframe - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples) + ru->end_of_burst_delay; - flags=3; // end of burst + flags = TX_BURST_END; } if (fp->frame_type == TDD && SF_type == SF_DL && prevSF_type == SF_UL) { - flags = 2; // start of burst + flags = TX_BURST_START; sf_extension = ru->sf_extension; } diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 96ec7e2759..48cf6ebe31 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -733,7 +733,8 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { T_INT(0), T_BUFFER(&ru->common.txdata[0][fp->get_samples_slot_timestamp(slot,fp,0)], fp->samples_per_subframe * 4)); int sf_extension = 0; int siglen=fp->get_samples_per_slot(slot,fp); - int flags = 0; + radio_tx_burst_flag_t flags_burst = TX_BURST_INVALID; + radio_tx_gpio_flag_t flags_gpio = 0; if (cfg->cell_config.frame_duplex_type.value == TDD && !get_softmodem_params()->continuous_tx) { int slot_type = nr_slot_select(cfg,frame,slot%fp->slots_per_frame); @@ -760,49 +761,41 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { } //+ ru->end_of_burst_delay; - flags = 3; // end of burst + flags_burst = TX_BURST_END; } else if (slot_type == NR_DOWNLINK_SLOT) { int prevslot_type = nr_slot_select(cfg,frame,(slot+(fp->slots_per_frame-1))%fp->slots_per_frame); int nextslot_type = nr_slot_select(cfg,frame,(slot+1)%fp->slots_per_frame); if (prevslot_type == NR_UPLINK_SLOT) { - flags = 2; // start of burst + flags_burst = TX_BURST_START; sf_extension = ru->sf_extension; } else if (nextslot_type == NR_UPLINK_SLOT) { - flags = 3; // end of burst + flags_burst = TX_BURST_END; } else { - flags = 1; // middle of burst + flags_burst = TX_BURST_MIDDLE; } } } else { // FDD - if (proc->first_tx == 1) { - flags = 2; // start of burst - } else { - flags = 1; // middle of burst - } + flags_burst = proc->first_tx == 1 ? TX_BURST_START : TX_BURST_MIDDLE; } - if (flags) { if (fp->freq_range==nr_FR2) { - // the beam index is written in bits 8-10 of the flags - // bit 11 enables the gpio programming - // currently we switch beams every 10 slots (should = 1 TDD period in FR2) and we take the beam index of the first symbol of the first slot of this period - int beam=0; + // currently we switch beams at the beginning of a slot and we take the beam index of the first symbol of this slot + // we only send the beam to the gpio if the beam is different from the previous slot - if (slot%10==0) { - if ( ru->common.beam_id && (ru->common.beam_id[0][slot*fp->symbols_per_slot] < 8)) { - beam = ru->common.beam_id[0][slot*fp->symbols_per_slot] | 8; + if ( ru->common.beam_id) { + int prev_slot = (slot - 1 + fp->slots_per_frame) % fp->slots_per_frame; + const uint8_t *beam_ids = ru->common.beam_id[0]; + int prev_beam = beam_ids[prev_slot * fp->symbols_per_slot]; + int beam = beam_ids[slot * fp->symbols_per_slot]; + if (prev_beam != beam) { + flags_gpio = beam | TX_GPIO_CHANGE; // enable change of gpio + LOG_D(HW, "slot %d, beam %d\n", slot, ru->common.beam_id[0][slot * fp->symbols_per_slot]); } } - - /* - if (slot==0 || slot==40) beam=0|8; - if (slot==10 || slot==50) beam=1|8; - if (slot==20 || slot==60) beam=2|8; - if (slot==30 || slot==70) beam=3|8; - */ - flags |= beam<<8; - LOG_D(HW,"slot %d, beam %d\n",slot,ru->common.beam_id[0][slot*fp->symbols_per_slot]); } + + const int flags = flags_burst | flags_gpio << 4; + if (proc->first_tx == 1) proc->first_tx = 0; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS, flags ); @@ -825,7 +818,7 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { (long long unsigned int)(timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension),frame,slot,proc->frame_tx_unwrap,slot, flags, siglen+sf_extension, txs,10*log10((double)signal_energy(txp[0],siglen+sf_extension))); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); //AssertFatal(txs == 0,"trx write function error %d\n", txs); - } + } // this is for RU with local RF unit diff --git a/executables/nr-ue.c b/executables/nr-ue.c index cd64a66287..61e12a158f 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -509,7 +509,7 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD) { txp[i] = (void *)&UE->common_vars.txdata[i][UE->frame_parms.get_samples_slot_timestamp( proc->nr_slot_tx, &UE->frame_parms, 0)]; - radio_tx_flag_t flags = Invalid; + radio_tx_burst_flag_t flags = TX_BURST_INVALID; NR_UE_MAC_INST_t *mac = get_mac_inst(0); @@ -531,13 +531,13 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD) { uint8_t first_tx_slot = tdd_period - num_UL_slots; if (slot_tx_usrp % tdd_period == first_tx_slot) - flags = StartOfBurst; + flags = TX_BURST_START; else if (slot_tx_usrp % tdd_period == first_tx_slot + num_UL_slots - 1) - flags = EndOfBurst; + flags = TX_BURST_END; else if (slot_tx_usrp % tdd_period > first_tx_slot) - flags = MiddleOfBurst; + flags = TX_BURST_MIDDLE; } else { - flags = MiddleOfBurst; + flags = TX_BURST_MIDDLE; } if (flags || IS_SOFTMODEM_RFSIM) diff --git a/maketags b/maketags index 5c7232320a..87f445dd21 100755 --- a/maketags +++ b/maketags @@ -1,4 +1,4 @@ #!/bin/sh echo "building ctags for openair1 and openair2 ..." -ctags -e -R --exclude=openair1/DOCS/ --exclude=openair2/DOCS/ --exclude=openair1/SIMULATION/ --exclude=targets/DOCS/ --exclude=targets/PROJECTS/ openair1 openair2 openair3 targets cmake_targets common nfapi executables +ctags -e -R --exclude=openair1/DOCS/ --exclude=openair2/DOCS/ --exclude=openair1/SIMULATION/ --exclude=targets/DOCS/ --exclude=targets/PROJECTS/ openair1 openair2 openair3 targets cmake_targets common nfapi executables sdr diff --git a/radio/COMMON/common_lib.h b/radio/COMMON/common_lib.h index 3733914ef4..9492e036b7 100644 --- a/radio/COMMON/common_lib.h +++ b/radio/COMMON/common_lib.h @@ -152,11 +152,19 @@ typedef enum { /*! \brief Radio Tx burst flags */ typedef enum { - Invalid = 0, - MiddleOfBurst, - StartOfBurst, - EndOfBurst -} radio_tx_flag_t; + TX_BURST_INVALID = 0, + TX_BURST_MIDDLE = 1, + TX_BURST_START = 2, + TX_BURST_END = 3, + TX_BURST_START_AND_END = 4, + TX_BURST_END_NO_TIME_SPEC = 10, +} radio_tx_burst_flag_t; + +/*! \brief Radio TX GPIO flags: MSB to enable sending GPIO command, 12 LSB carry GPIO values */ +typedef enum { + /* first 12 bits reserved for beams */ + TX_GPIO_CHANGE = 0x1000, +} radio_tx_gpio_flag_t; /*! \brief Structure used for initializing UDP read threads */ typedef struct { @@ -315,7 +323,7 @@ typedef struct { int cc; signed char first_packet; signed char last_packet; - int flags_msb; + radio_tx_gpio_flag_t flags_gpio; } openair0_write_package_t; typedef struct { diff --git a/radio/IRIS/USERSPACE/LIB/iris_lib.cpp b/radio/IRIS/USERSPACE/LIB/iris_lib.cpp index 051efe7a53..32a2f51db0 100644 --- a/radio/IRIS/USERSPACE/LIB/iris_lib.cpp +++ b/radio/IRIS/USERSPACE/LIB/iris_lib.cpp @@ -164,9 +164,9 @@ trx_iris_write(openair0_device *device, openair0_timestamp timestamp, void **buf return nsamps; } - if (flags == 2 || flags == 1) { // start of burst + if (flags == TX_BURST_START || flags == TX_BURST_MIDDLE) - } else if (flags == 3 || flags == 4) { + } else if (flags == TX_BURST_END || flags == TX_BURST_START_AND_END) { flag |= SOAPY_SDR_END_BURST; } diff --git a/radio/USRP/USERSPACE/LIB/usrp_lib.cpp b/radio/USRP/USERSPACE/LIB/usrp_lib.cpp index 1f6fbd34b1..d175295fce 100644 --- a/radio/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/radio/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -59,7 +59,6 @@ /** @addtogroup _USRP_PHY_RF_INTERFACE_ * @{ */ -int gpio789=0; extern int usrp_tx_thread; @@ -88,6 +87,9 @@ typedef struct { //! TX forward samples. We use usrp_time_offset to get this value int tx_forward_nsamps; //166 for 20Mhz + //! gpio bank to use + char *gpio_bank; + // -------------------------------- // Debug and output control // -------------------------------- @@ -258,27 +260,41 @@ static int sync_to_gps(openair0_device *device) { return EXIT_SUCCESS; } +#define ATR_MASK 0x7f //pins controlled by ATR +#define ATR_RX 0x50 //data[4] and data[6] +#define ATR_XX 0x20 //data[5] +#define MAN_MASK ATR_MASK^0xFFF //manually controlled pins + /*! \brief Called to start the USRP transceiver. Return 0 if OK, < 0 if error @param device pointer to the device structure specific to the RF hardware target */ static int trx_usrp_start(openair0_device *device) { usrp_state_t *s = (usrp_state_t *)device->priv; - if (device->type != USRP_X400_DEV) { - // setup GPIO for TDD, GPIO(4) = ATR_RX - //set data direction register (DDR) to output - s->usrp->set_gpio_attr("FP0", "DDR", 0xfff, 0xfff); - //set lower 7 bits to be controlled automatically by ATR (the rest 5 bits are controlled manually) - s->usrp->set_gpio_attr("FP0", "CTRL", 0x7f,0xfff); - //set pins 4 (RX_TX_Switch) and 6 (Shutdown PA) to 1 when the radio is only receiving (ATR_RX) - s->usrp->set_gpio_attr("FP0", "ATR_RX", (1<<4)|(1<<6), 0x7f); - // set pin 5 (Shutdown LNA) to 1 when the radio is transmitting and receiveing (ATR_XX) - // (we use full duplex here, because our RX is on all the time - this might need to change later) - s->usrp->set_gpio_attr("FP0", "ATR_XX", (1<<5), 0x7f); - // set the output pins to 1 - s->usrp->set_gpio_attr("FP0", "OUT", 7<<7, 0xf80); - } + s->gpio_bank = (char *) "FP0"; //good for B210, X310 and N310 +#if UHD_VERSION>4000000 + if (device->type == USRP_X400_DEV) { + // Set every pin on GPIO0 to be controlled by DB0_RF0 + std::vector sxx{12, "DB0_RF0"}; + s->gpio_bank = (char *) "GPIO0"; + s->usrp->set_gpio_src(s->gpio_bank, sxx); + } +#endif + + // setup GPIO for TDD, GPIO(4) = ATR_RX + //set data direction register (DDR) to output + s->usrp->set_gpio_attr(s->gpio_bank, "DDR", 0xfff, 0xfff); + //set bits to be controlled automatically by ATR + s->usrp->set_gpio_attr(s->gpio_bank, "CTRL", ATR_MASK, 0xfff); + //set bits to 1 when the radio is only receiving (ATR_RX) + s->usrp->set_gpio_attr(s->gpio_bank, "ATR_RX", ATR_RX, ATR_MASK); + // set bits to 1 when the radio is transmitting and receiveing (ATR_XX) + // (we use full duplex here, because our RX is on all the time - this might need to change later) + s->usrp->set_gpio_attr(s->gpio_bank, "ATR_XX", ATR_XX, ATR_MASK); + // set all other pins to manual + s->usrp->set_gpio_attr(s->gpio_bank, "OUT", MAN_MASK, 0xfff); + s->wait_for_first_pps = 1; s->rx_count = 0; s->tx_count = 0; @@ -373,8 +389,8 @@ static int trx_usrp_write(openair0_device *device, usrp_state_t *s = (usrp_state_t *)device->priv; int nsamps2; // aligned to upper 32 or 16 byte boundary - int flags_lsb = flags&0xff; - int flags_msb = (flags>>8)&0xff; + radio_tx_burst_flag_t flags_burst = (radio_tx_burst_flag_t) (flags & 0xf); + radio_tx_gpio_flag_t flags_gpio = (radio_tx_gpio_flag_t) ((flags >> 4) & 0x1fff); int end; openair0_thread_t *write_thread = &device->write_thread; @@ -384,28 +400,28 @@ static int trx_usrp_write(openair0_device *device, bool first_packet_state=false,last_packet_state=false; - if (flags_lsb == 2) { // start of burst + if (flags_burst == TX_BURST_START) { // s->tx_md.start_of_burst = true; // s->tx_md.end_of_burst = false; first_packet_state = true; last_packet_state = false; - } else if (flags_lsb == 3) { // end of burst + } else if (flags_burst == TX_BURST_END) { //s->tx_md.start_of_burst = false; //s->tx_md.end_of_burst = true; first_packet_state = false; last_packet_state = true; - } else if (flags_lsb == 4) { // start and end + } else if (flags_burst == TX_BURST_START_AND_END) { // s->tx_md.start_of_burst = true; // s->tx_md.end_of_burst = true; first_packet_state = true; last_packet_state = true; - } else if (flags_lsb==1) { // middle of burst + } else if (flags_burst == TX_BURST_MIDDLE) { // s->tx_md.start_of_burst = false; // s->tx_md.end_of_burst = false; first_packet_state = false; last_packet_state = false; } - else if (flags_lsb==10) { // fail safe mode + else if (flags_burst==10) { // fail safe mode // s->tx_md.has_time_spec = false; // s->tx_md.start_of_burst = false; // s->tx_md.end_of_burst = true; @@ -449,12 +465,11 @@ static int trx_usrp_write(openair0_device *device, s->tx_count++; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHING_GPIO,1); - // bit 3 enables gpio (for backward compatibility) - if (flags_msb&8) { - // push GPIO bits 7-9 from flags_msb - int gpio789=(flags_msb&7)<<7; + // bit 13 enables gpio + if ((flags_gpio & TX_GPIO_CHANGE) != 0) { + // push GPIO bits s->usrp->set_command_time(s->tx_md.time_spec); - s->usrp->set_gpio_attr("FP0", "OUT", gpio789, 0x380); + s->usrp->set_gpio_attr(s->gpio_bank, "OUT", flags_gpio, MAN_MASK); s->usrp->clear_command_time(); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHING_GPIO,0); @@ -489,7 +504,7 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHI write_package[end].cc = cc; write_package[end].first_packet = first_packet_state; write_package[end].last_packet = last_packet_state; - write_package[end].flags_msb = flags_msb; + write_package[end].flags_gpio = flags_gpio; for (int i = 0; i < cc; i++) write_package[end].buff[i] = buff[i]; write_thread->count_write++; @@ -526,7 +541,7 @@ void *trx_usrp_write_thread(void * arg){ int cc; signed char first_packet; signed char last_packet; - int flags_msb; + int flags_gpio; while(1){ pthread_mutex_lock(&write_thread->mutex_write); @@ -544,7 +559,7 @@ void *trx_usrp_write_thread(void * arg){ cc = write_package[start].cc; first_packet = write_package[start].first_packet; last_packet = write_package[start].last_packet; - flags_msb = write_package[start].flags_msb; + flags_gpio = write_package[start].flags_gpio; write_thread->start = (write_thread->start + 1)% MAX_WRITE_THREAD_PACKAGE; write_thread->count_write--; pthread_mutex_unlock(&write_thread->mutex_write); @@ -589,11 +604,10 @@ void *trx_usrp_write_thread(void * arg){ s->tx_count++; // bit 3 enables gpio (for backward compatibility) - if (flags_msb&8) { - // push GPIO bits 7-9 from flags_msb - int gpio789=(flags_msb&7)<<7; + if (flags_gpio&0x1000) { + // push GPIO bits s->usrp->set_command_time(s->tx_md.time_spec); - s->usrp->set_gpio_attr("FP0", "OUT", gpio789, 0x380); + s->usrp->set_gpio_attr(s->gpio_bank, "OUT", flags_gpio, MAN_MASK); s->usrp->clear_command_time(); } @@ -740,11 +754,6 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate); *ptimestamp = s->rx_timestamp; - // push GPIO bits 7-9 from flags_msb - /*s->usrp->set_command_time(uhd::time_spec_t::from_ticks((s->rx_timestamp+(2*nsamps)),s->sample_rate)); - s->usrp->set_gpio_attr("FP0", "OUT", gpio789<<7, 0x380); - s->usrp->clear_command_time(); - gpio789 = (gpio789+1)&7;*/ recplay_state_t *recPlay=device->recplay_state; if ( recPlay != NULL) { // record mode @@ -992,7 +1001,7 @@ extern "C" { int choffset = 0; if ( device->priv == NULL) { - s=(usrp_state_t *)calloc(sizeof(usrp_state_t),1); + s=(usrp_state_t *)calloc(1, sizeof(usrp_state_t)); device->priv=s; AssertFatal( s!=NULL,"USRP device: memory allocation failure\n"); } else {