Commit faba9ac2 authored by Florian Kaltenberger's avatar Florian Kaltenberger Committed by Robert Schmidt

Make USRP GPIO control more flexible

- adding support for x410 GPIO
parent 214aa505
...@@ -733,7 +733,7 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { ...@@ -733,7 +733,7 @@ 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)); 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 sf_extension = 0;
int siglen=fp->get_samples_per_slot(slot,fp); int siglen=fp->get_samples_per_slot(slot,fp);
int flags = 0; int flags=0,flags_burst=0,flags_gpio=0;
if (cfg->cell_config.frame_duplex_type.value == TDD && !get_softmodem_params()->continuous_tx) { 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); int slot_type = nr_slot_select(cfg,frame,slot%fp->slots_per_frame);
...@@ -760,39 +760,37 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { ...@@ -760,39 +760,37 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
} }
//+ ru->end_of_burst_delay; //+ ru->end_of_burst_delay;
flags = 3; // end of burst flags_burst = 3; // end of burst
} else if (slot_type == NR_DOWNLINK_SLOT) { } 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 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); int nextslot_type = nr_slot_select(cfg,frame,(slot+1)%fp->slots_per_frame);
if (prevslot_type == NR_UPLINK_SLOT) { if (prevslot_type == NR_UPLINK_SLOT) {
flags = 2; // start of burst flags_burst = 2; // start of burst
sf_extension = ru->sf_extension; sf_extension = ru->sf_extension;
} else if (nextslot_type == NR_UPLINK_SLOT) { } else if (nextslot_type == NR_UPLINK_SLOT) {
flags = 3; // end of burst flags_burst = 3; // end of burst
} else { } else {
flags = 1; // middle of burst flags_burst = 1; // middle of burst
} }
} }
} else { // FDD } else { // FDD
if (proc->first_tx == 1) { if (proc->first_tx == 1) {
flags = 2; // start of burst flags_burst = 2; // start of burst
} else { } else {
flags = 1; // middle of burst flags_burst = 1; // middle of burst
} }
} }
if (flags) {
if (fp->freq_range==nr_FR2) { 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 // 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; int beam=0;
if (slot%10==0) { if (slot%10==0) {
if ( ru->common.beam_id && (ru->common.beam_id[0][slot*fp->symbols_per_slot] < 8)) { 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; beam = ru->common.beam_id[0][slot*fp->symbols_per_slot];
} }
} }
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==0 || slot==40) beam=0|8;
...@@ -800,9 +798,12 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { ...@@ -800,9 +798,12 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
if (slot==20 || slot==60) beam=2|8; if (slot==20 || slot==60) beam=2|8;
if (slot==30 || slot==70) beam=3|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]); flags_gpio = beam & 0x1000; //enable change of gpio
} }
flags = flags_burst | flags_gpio<<4;
if (proc->first_tx == 1) proc->first_tx = 0; if (proc->first_tx == 1) proc->first_tx = 0;
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS, flags ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS, flags );
...@@ -825,7 +826,7 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { ...@@ -825,7 +826,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))); (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 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
//AssertFatal(txs == 0,"trx write function error %d\n", txs); //AssertFatal(txs == 0,"trx write function error %d\n", txs);
}
} }
// this is for RU with local RF unit // this is for RU with local RF unit
......
#!/bin/sh #!/bin/sh
echo "building ctags for openair1 and openair2 ..." 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
...@@ -315,7 +315,7 @@ typedef struct { ...@@ -315,7 +315,7 @@ typedef struct {
int cc; int cc;
signed char first_packet; signed char first_packet;
signed char last_packet; signed char last_packet;
int flags_msb; int flags_gpio;
} openair0_write_package_t; } openair0_write_package_t;
typedef struct { typedef struct {
......
...@@ -59,7 +59,6 @@ ...@@ -59,7 +59,6 @@
/** @addtogroup _USRP_PHY_RF_INTERFACE_ /** @addtogroup _USRP_PHY_RF_INTERFACE_
* @{ * @{
*/ */
int gpio789=0;
extern int usrp_tx_thread; extern int usrp_tx_thread;
...@@ -88,6 +87,9 @@ typedef struct { ...@@ -88,6 +87,9 @@ typedef struct {
//! TX forward samples. We use usrp_time_offset to get this value //! TX forward samples. We use usrp_time_offset to get this value
int tx_forward_nsamps; //166 for 20Mhz int tx_forward_nsamps; //166 for 20Mhz
//! gpio bank to use
std::string gpio_bank;
// -------------------------------- // --------------------------------
// Debug and output control // Debug and output control
// -------------------------------- // --------------------------------
...@@ -258,27 +260,41 @@ static int sync_to_gps(openair0_device *device) { ...@@ -258,27 +260,41 @@ static int sync_to_gps(openair0_device *device) {
return EXIT_SUCCESS; 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 /*! \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 @param device pointer to the device structure specific to the RF hardware target
*/ */
static int trx_usrp_start(openair0_device *device) { static int trx_usrp_start(openair0_device *device) {
usrp_state_t *s = (usrp_state_t *)device->priv; usrp_state_t *s = (usrp_state_t *)device->priv;
if (device->type != USRP_X400_DEV) { s->gpio_bank = "FP0"; //good for B210, X310 and N310
// 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);
}
#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 = "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->wait_for_first_pps = 1;
s->rx_count = 0; s->rx_count = 0;
s->tx_count = 0; s->tx_count = 0;
...@@ -373,8 +389,8 @@ static int trx_usrp_write(openair0_device *device, ...@@ -373,8 +389,8 @@ static int trx_usrp_write(openair0_device *device,
usrp_state_t *s = (usrp_state_t *)device->priv; usrp_state_t *s = (usrp_state_t *)device->priv;
int nsamps2; // aligned to upper 32 or 16 byte boundary int nsamps2; // aligned to upper 32 or 16 byte boundary
int flags_lsb = flags&0xff; int flags_burst = flags&0xf;
int flags_msb = (flags>>8)&0xff; int flags_gpio = (flags>>4)&0x1fff; //MSB to enable sending GPIO command, 12 LSB carry GPIO values
int end; int end;
openair0_thread_t *write_thread = &device->write_thread; openair0_thread_t *write_thread = &device->write_thread;
...@@ -384,28 +400,28 @@ static int trx_usrp_write(openair0_device *device, ...@@ -384,28 +400,28 @@ static int trx_usrp_write(openair0_device *device,
bool first_packet_state=false,last_packet_state=false; bool first_packet_state=false,last_packet_state=false;
if (flags_lsb == 2) { // start of burst if (flags_burst == 2) { // start of burst
// s->tx_md.start_of_burst = true; // s->tx_md.start_of_burst = true;
// s->tx_md.end_of_burst = false; // s->tx_md.end_of_burst = false;
first_packet_state = true; first_packet_state = true;
last_packet_state = false; last_packet_state = false;
} else if (flags_lsb == 3) { // end of burst } else if (flags_burst == 3) { // end of burst
//s->tx_md.start_of_burst = false; //s->tx_md.start_of_burst = false;
//s->tx_md.end_of_burst = true; //s->tx_md.end_of_burst = true;
first_packet_state = false; first_packet_state = false;
last_packet_state = true; last_packet_state = true;
} else if (flags_lsb == 4) { // start and end } else if (flags_burst == 4) { // start and end
// s->tx_md.start_of_burst = true; // s->tx_md.start_of_burst = true;
// s->tx_md.end_of_burst = true; // s->tx_md.end_of_burst = true;
first_packet_state = true; first_packet_state = true;
last_packet_state = true; last_packet_state = true;
} else if (flags_lsb==1) { // middle of burst } else if (flags_burst==1) { // middle of burst
// s->tx_md.start_of_burst = false; // s->tx_md.start_of_burst = false;
// s->tx_md.end_of_burst = false; // s->tx_md.end_of_burst = false;
first_packet_state = false; first_packet_state = false;
last_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.has_time_spec = false;
// s->tx_md.start_of_burst = false; // s->tx_md.start_of_burst = false;
// s->tx_md.end_of_burst = true; // s->tx_md.end_of_burst = true;
...@@ -449,12 +465,11 @@ static int trx_usrp_write(openair0_device *device, ...@@ -449,12 +465,11 @@ static int trx_usrp_write(openair0_device *device,
s->tx_count++; s->tx_count++;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHING_GPIO,1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHING_GPIO,1);
// bit 3 enables gpio (for backward compatibility) // bit 13 enables gpio
if (flags_msb&8) { if (flags_gpio&0x1000) {
// push GPIO bits 7-9 from flags_msb // push GPIO bits
int gpio789=(flags_msb&7)<<7;
s->usrp->set_command_time(s->tx_md.time_spec); 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(); s->usrp->clear_command_time();
} }
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHING_GPIO,0); 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 ...@@ -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].cc = cc;
write_package[end].first_packet = first_packet_state; write_package[end].first_packet = first_packet_state;
write_package[end].last_packet = last_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++) for (int i = 0; i < cc; i++)
write_package[end].buff[i] = buff[i]; write_package[end].buff[i] = buff[i];
write_thread->count_write++; write_thread->count_write++;
...@@ -526,7 +541,7 @@ void *trx_usrp_write_thread(void * arg){ ...@@ -526,7 +541,7 @@ void *trx_usrp_write_thread(void * arg){
int cc; int cc;
signed char first_packet; signed char first_packet;
signed char last_packet; signed char last_packet;
int flags_msb; int flags_gpio;
while(1){ while(1){
pthread_mutex_lock(&write_thread->mutex_write); pthread_mutex_lock(&write_thread->mutex_write);
...@@ -544,7 +559,7 @@ void *trx_usrp_write_thread(void * arg){ ...@@ -544,7 +559,7 @@ void *trx_usrp_write_thread(void * arg){
cc = write_package[start].cc; cc = write_package[start].cc;
first_packet = write_package[start].first_packet; first_packet = write_package[start].first_packet;
last_packet = write_package[start].last_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->start = (write_thread->start + 1)% MAX_WRITE_THREAD_PACKAGE;
write_thread->count_write--; write_thread->count_write--;
pthread_mutex_unlock(&write_thread->mutex_write); pthread_mutex_unlock(&write_thread->mutex_write);
...@@ -589,11 +604,10 @@ void *trx_usrp_write_thread(void * arg){ ...@@ -589,11 +604,10 @@ void *trx_usrp_write_thread(void * arg){
s->tx_count++; s->tx_count++;
// bit 3 enables gpio (for backward compatibility) // bit 3 enables gpio (for backward compatibility)
if (flags_msb&8) { if (flags_gpio&0x1000) {
// push GPIO bits 7-9 from flags_msb // push GPIO bits
int gpio789=(flags_msb&7)<<7;
s->usrp->set_command_time(s->tx_md.time_spec); 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(); s->usrp->clear_command_time();
} }
...@@ -740,11 +754,6 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp ...@@ -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); s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
*ptimestamp = s->rx_timestamp; *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; recplay_state_t *recPlay=device->recplay_state;
if ( recPlay != NULL) { // record mode if ( recPlay != NULL) { // record mode
......
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