Commit 90918b20 authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/usrp_gpio_framework' into integration_2023_w05

parents e7fec943 e38b2433
......@@ -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;
......
......@@ -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;
}
......
......@@ -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;
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;
// 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 ( 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
......
......@@ -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)
......
#!/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
......@@ -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 {
......
......@@ -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;
}
......
......@@ -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<std::string> 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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment