Commit 396cadfc authored by Florian Kaltenberger's avatar Florian Kaltenberger

adding API for USRP function issue_stream_cmd so that we can do timed reads in...

adding API for USRP function issue_stream_cmd so that we can do timed reads in the nr-ru. This functionality is only enabled using a new flag use_single_antenna_port_for_tdd in openair0_cfg

this flaf will also put TX and RX on the same TRX antenna port

further usrp time now synchronized on pps, even when not using gps
parent d15d86cf
...@@ -625,55 +625,80 @@ void *emulatedRF_thread(void *param) { ...@@ -625,55 +625,80 @@ void *emulatedRF_thread(void *param) {
void rx_rf(RU_t *ru,int *frame,int *slot) { void rx_rf(RU_t *ru,int *frame,int *slot) {
RU_proc_t *proc = &ru->proc; RU_proc_t *proc = &ru->proc;
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config;
void *rxp[ru->nb_rx]; void *rxp[ru->nb_rx];
unsigned int rxs; unsigned int rxs, siglen;
int i; int i;
uint32_t samples_per_slot = fp->get_samples_per_slot(*slot,fp); uint32_t samples_per_slot = fp->get_samples_per_slot(*slot,fp);
openair0_timestamp ts,old_ts; openair0_timestamp ts;
AssertFatal(*slot<fp->slots_per_frame && *slot>=0, "slot %d is illegal (%d)\n",*slot,fp->slots_per_frame); AssertFatal(*slot<fp->slots_per_frame && *slot>=0, "slot %d is illegal (%d)\n",*slot,fp->slots_per_frame);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
for (i=0; i<ru->nb_rx; i++) for (i=0; i<ru->nb_rx; i++)
rxp[i] = (void *)&ru->common.rxdata[i][fp->get_samples_slot_timestamp(*slot,fp,0)]; rxp[i] = (void *)&ru->common.rxdata[i][fp->get_samples_slot_timestamp(*slot,fp,0)];
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); //when the USRP starts, it initializes the timestamp to 0. We wait 1 frames until we program the first rx.
old_ts = proc->timestamp_rx; if (proc->first_rx==1) {
LOG_D(PHY,"Reading %d samples for slot %d (%p)\n",samples_per_slot,*slot,rxp[0]); proc->timestamp_rx = fp->samples_per_frame;
proc->first_rx = 0;
if(emulate_rf) {
wait_on_condition(&proc->mutex_emulateRF,&proc->cond_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread");
release_thread(&proc->mutex_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread");
rxs = samples_per_slot;
ts = old_ts + rxs;
} else {
rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
&ts,
rxp,
samples_per_slot,
ru->nb_rx);
} }
else {
//we always advance the timestamp by samples_per_slot, even if we have not read the (full) slot. This is to keep the timestamp updated even when there is no RX.
proc->timestamp_rx += fp->get_samples_per_slot(*slot%fp->slots_per_frame,fp);
}
int slot_type = nr_slot_select(cfg,*frame,*slot%fp->slots_per_frame);
if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT || IS_SOFTMODEM_RFSIM) {
if (slot_type == NR_MIXED_SLOT) {
uint16_t rxsymb = 0;
for(uint16_t symbol_count =0;symbol_count<fp->symbols_per_slot;symbol_count++) {
if (cfg->tdd_table.max_tdd_periodicity_list[*slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==1)
rxsymb++;
}
AssertFatal(rxsymb>0,"illegal rxsymb %d\n",rxsymb);
//TODO: this has to be adapted for numerology!=1
siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (rxsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples);
proc->timestamp_rx += fp->get_samples_per_slot(*slot%fp->slots_per_frame,fp) - siglen;
//TODO: the 3rd parameter has to be adapted for arbitrary TDD configurations
ru->rfdevice.trx_issue_stream_cmd(&ru->rfdevice,
proc->timestamp_rx,
siglen+2*fp->get_samples_per_slot(*slot,fp));
}
else {
siglen = samples_per_slot;
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); LOG_D(PHY,"Reading %d samples for slot %d at timestamp %ld\n",siglen,*slot,proc->timestamp_rx);
proc->timestamp_rx = ts-ru->ts_offset;
//AssertFatal(rxs == fp->samples_per_subframe,
//"rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_subframe,rxs);
if (rxs != samples_per_slot) LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n",samples_per_slot,rxs);
if (proc->first_rx == 1) { if(emulate_rf) {
ru->ts_offset = proc->timestamp_rx; wait_on_condition(&proc->mutex_emulateRF,&proc->cond_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread");
proc->timestamp_rx = 0; release_thread(&proc->mutex_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread");
} else { rxs = siglen;
if (proc->timestamp_rx - old_ts != fp->get_samples_per_slot((*slot-1)%fp->slots_per_frame,fp)) { }
LOG_D(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - samples_per_slot,ru->ts_offset); else {
ru->ts_offset += (proc->timestamp_rx - old_ts - samples_per_slot); rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
proc->timestamp_rx = ts-ru->ts_offset; &ts,
rxp,
siglen,
ru->nb_rx);
} }
//AssertFatal(rxs == siglen,"rx_rf: Asked for %d samples, got %d from USRP\n",siglen,rxs);
if (rxs != siglen) LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n",siglen,rxs);
} }
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
uint32_t idx_sf = proc->timestamp_rx / fp->samples_per_subframe;
proc->tti_rx = (idx_sf * fp->slots_per_subframe + (int)round((float)(proc->timestamp_rx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame); proc->frame_rx = *frame;
proc->tti_rx = *slot;
// synchronize first reception to frame 0 subframe 0 // synchronize first reception to frame 0 subframe 0
LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, slot %d.%d / %d\n", LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, slot %d.%d / %d\n",
ru->idx, ru->idx,
...@@ -687,29 +712,9 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { ...@@ -687,29 +712,9 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_RX0_RU, proc->tti_rx );
} }
if (proc->first_rx == 0) {
if (proc->tti_rx != *slot) {
LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->tti_rx %d, slot %d)\n",(long long unsigned int)proc->timestamp_rx,proc->tti_rx,*slot);
exit_fun("Exiting");
}
if (proc->frame_rx != *frame) {
LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",(long long unsigned int)proc->timestamp_rx,proc->frame_rx,*frame);
exit_fun("Exiting");
}
} else {
proc->first_rx = 0;
*frame = proc->frame_rx;
*slot = proc->tti_rx;
}
//printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->tti_rx,subframe); //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->tti_rx,subframe);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
if (rxs != samples_per_slot) {
//exit_fun( "problem receiving samples" );
LOG_E(PHY, "problem receiving samples\n");
}
} }
...@@ -735,7 +740,7 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { ...@@ -735,7 +740,7 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
if(slot_type == NR_MIXED_SLOT) { if(slot_type == NR_MIXED_SLOT) {
txsymb = 0; txsymb = 0;
for(int symbol_count =0;symbol_count<NR_NUMBER_OF_SYMBOLS_PER_SLOT;symbol_count++) { for(int symbol_count =0;symbol_count<fp->symbols_per_slot;symbol_count++) {
if (cfg->tdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==0) if (cfg->tdd_table.max_tdd_periodicity_list[slot].max_num_of_symbol_per_slot_list[symbol_count].slot_config.value==0)
txsymb++; txsymb++;
} }
...@@ -920,6 +925,7 @@ int wakeup_synch(RU_t *ru) { ...@@ -920,6 +925,7 @@ int wakeup_synch(RU_t *ru) {
return(0); return(0);
} }
/*
void do_ru_synch(RU_t *ru) { void do_ru_synch(RU_t *ru) {
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
RU_proc_t *proc = &ru->proc; RU_proc_t *proc = &ru->proc;
...@@ -991,7 +997,7 @@ void do_ru_synch(RU_t *ru) { ...@@ -991,7 +997,7 @@ void do_ru_synch(RU_t *ru) {
ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0); ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0);
} }
*/
void wakeup_gNB_L1s(RU_t *ru) { void wakeup_gNB_L1s(RU_t *ru) {
...@@ -1150,6 +1156,9 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { ...@@ -1150,6 +1156,9 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) {
cfg->num_rb_dl=N_RB; cfg->num_rb_dl=N_RB;
cfg->tx_num_channels=ru->nb_tx; cfg->tx_num_channels=ru->nb_tx;
cfg->rx_num_channels=ru->nb_rx; cfg->rx_num_channels=ru->nb_rx;
cfg->clock_source=get_softmodem_params()->clock_source;
cfg->use_single_antenna_port_for_tdd=1; //TODO: make this parameterzable
for (i=0; i<ru->nb_tx; i++) { for (i=0; i<ru->nb_tx; i++) {
if (ru->if_frequency == 0) { if (ru->if_frequency == 0) {
...@@ -1481,7 +1490,7 @@ void *ru_thread( void *param ) { ...@@ -1481,7 +1490,7 @@ void *ru_thread( void *param ) {
} else LOG_I(PHY,"RU %d no asynch_south interface\n",ru->idx); } else LOG_I(PHY,"RU %d no asynch_south interface\n",ru->idx);
// if this is a slave RRU, try to synchronize on the DL frequency // if this is a slave RRU, try to synchronize on the DL frequency
if ((ru->is_slave) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru); //if ((ru->is_slave) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru);
} }
pthread_mutex_lock(&proc->mutex_FH1); pthread_mutex_lock(&proc->mutex_FH1);
......
...@@ -235,6 +235,8 @@ typedef struct { ...@@ -235,6 +235,8 @@ typedef struct {
double tx_sample_rate; double tx_sample_rate;
//! check for threequarter sampling rate //! check for threequarter sampling rate
int8_t threequarter_fs; int8_t threequarter_fs;
//! flag to indicate use of same antenna port for RX and TX (for TDD)
int8_t use_single_antenna_port_for_tdd;
} openair0_config_t; } openair0_config_t;
/*! \brief RF mapping */ /*! \brief RF mapping */
...@@ -357,6 +359,8 @@ struct openair0_device_t { ...@@ -357,6 +359,8 @@ struct openair0_device_t {
*/ */
int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps,int antenna_id); int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps,int antenna_id);
int (*trx_issue_stream_cmd)(openair0_device *device, openair0_timestamp ptimestamp, int nsamps);
/*! \brief print the device statistics /*! \brief print the device statistics
* \param device the hardware to use * \param device the hardware to use
* \returns 0 on success * \returns 0 on success
......
...@@ -104,7 +104,8 @@ typedef struct { ...@@ -104,7 +104,8 @@ typedef struct {
int64_t rx_count; int64_t rx_count;
int wait_for_first_pps; int wait_for_first_pps;
int use_gps; int use_gps;
int first_tx; //int first_tx;
//int first_rx;
//! timestamp of RX packet //! timestamp of RX packet
openair0_timestamp rx_timestamp; openair0_timestamp rx_timestamp;
} usrp_state_t; } usrp_state_t;
...@@ -278,31 +279,34 @@ static int trx_usrp_start(openair0_device *device) { ...@@ -278,31 +279,34 @@ static int trx_usrp_start(openair0_device *device) {
// set pin 5 (Shutdown LNA) to 1 when the radio is transmitting and receiveing (ATR_XX) // 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) // (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); s->usrp->set_gpio_attr("FP0", "ATR_XX", (1<<5), 0x7f);
// set the output pins to 0 // set the output pins to 1
s->usrp->set_gpio_attr("FP0", "OUT", 7<<7, 0xf80); s->usrp->set_gpio_attr("FP0", "OUT", 7<<7, 0xf80);
// init recv and send streaming s->wait_for_first_pps = 1;
uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
LOG_I(HW,"Time in secs now: %llu \n", s->usrp->get_time_now().to_ticks(s->sample_rate));
LOG_I(HW,"Time in secs last pps: %llu \n", s->usrp->get_time_last_pps().to_ticks(s->sample_rate));
if (s->use_gps == 1 || device->openair0_cfg[0].time_source == external) {
s->wait_for_first_pps = 1;
cmd.time_spec = s->usrp->get_time_last_pps() + uhd::time_spec_t(1.0);
} else {
s->wait_for_first_pps = 0;
cmd.time_spec = s->usrp->get_time_now() + uhd::time_spec_t(0.005);
}
cmd.stream_now = false; // start at constant delay
s->rx_stream->issue_stream_cmd(cmd);
/*s->tx_md.time_spec = cmd.time_spec + uhd::time_spec_t(1-(double)s->tx_forward_nsamps/s->sample_rate);
s->tx_md.has_time_spec = true;
s->tx_md.start_of_burst = true;
s->tx_md.end_of_burst = false;*/
s->rx_count = 0; s->rx_count = 0;
s->tx_count = 0; s->tx_count = 0;
//s->first_tx = 1;
//s->first_rx = 1;
s->rx_timestamp = 0; s->rx_timestamp = 0;
s->usrp->set_time_next_pps(uhd::time_spec_t(0.0));
// wait for the pps to change
uhd::time_spec_t time_last_pps = s->usrp->get_time_last_pps();
while (time_last_pps == s->usrp->get_time_last_pps()) {
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
}
// init recv and send streaming command
if (device->openair0_cfg->use_single_antenna_port_for_tdd==0) {
uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
cmd.time_spec = uhd::time_spec_t(1.0);
cmd.stream_now = false; // start at constant delay
s->rx_stream->issue_stream_cmd(cmd);
}
// else the issue stream mode command needs to be called every TDD period
return 0; return 0;
} }
/*! \brief Terminate operation of the USRP transceiver -- free all associated resources /*! \brief Terminate operation of the USRP transceiver -- free all associated resources
...@@ -318,6 +322,15 @@ static void trx_usrp_end(openair0_device *device) { ...@@ -318,6 +322,15 @@ static void trx_usrp_end(openair0_device *device) {
return; return;
iqrecorder_end(device); iqrecorder_end(device);
if (device->openair0_cfg->use_single_antenna_port_for_tdd==0) {
s->rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
//send a mini EOB packet
s->tx_md.end_of_burst = true;
s->tx_stream->send("", 0, s->tx_md);
s->tx_md.end_of_burst = false;
sleep(1);
}
} }
...@@ -465,7 +478,6 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp ...@@ -465,7 +478,6 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
int16x8_t buff_tmp[2][nsamps2]; int16x8_t buff_tmp[2][nsamps2];
#endif #endif
if (device->type == USRP_B200_DEV) {
if (cc>1) { if (cc>1) {
// receive multiple channels (e.g. RF A and RF B) // receive multiple channels (e.g. RF A and RF B)
std::vector<void *> buff_ptrs; std::vector<void *> buff_ptrs;
...@@ -478,7 +490,7 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp ...@@ -478,7 +490,7 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
samples_received=0; samples_received=0;
while (samples_received != nsamps) { while (samples_received != nsamps) {
samples_received += s->rx_stream->recv(buff_tmp[0]+samples_received, samples_received += s->rx_stream->recv((void*)((int32_t*)buff_tmp[0]+samples_received),
nsamps-samples_received, s->rx_md); nsamps-samples_received, s->rx_md);
if ((s->wait_for_first_pps == 0) && (s->rx_md.error_code!=uhd::rx_metadata_t::ERROR_CODE_NONE)) if ((s->wait_for_first_pps == 0) && (s->rx_md.error_code!=uhd::rx_metadata_t::ERROR_CODE_NONE))
...@@ -488,7 +500,6 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp ...@@ -488,7 +500,6 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
printf("sleep...\n"); //usleep(100); printf("sleep...\n"); //usleep(100);
} }
} }
if (samples_received == nsamps) s->wait_for_first_pps=0; if (samples_received == nsamps) s->wait_for_first_pps=0;
} }
...@@ -514,22 +525,10 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp ...@@ -514,22 +525,10 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
#endif #endif
} }
} }
} else if (device->type == USRP_X300_DEV) {
if (cc>1) {
// receive multiple channels (e.g. RF A and RF B)
std::vector<void *> buff_ptrs;
for (int i=0; i<cc; i++) buff_ptrs.push_back(buff[i]); if (samples_received < nsamps) {
LOG_E(HW,"[recv] received %d samples out of %d\n",samples_received,nsamps);
samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md,1.0);
} else {
// receive a single channel (e.g. from connector RF A)
samples_received = s->rx_stream->recv(buff[0], nsamps, s->rx_md,1.0);
} }
}
if (samples_received < nsamps)
LOG_E(HW,"[recv] received %d samples out of %d\n",samples_received,nsamps);
if ( s->rx_md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) if ( s->rx_md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE)
LOG_E(HW, "%s\n", s->rx_md.to_pp_string(true).c_str()); LOG_E(HW, "%s\n", s->rx_md.to_pp_string(true).c_str());
...@@ -551,6 +550,19 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp ...@@ -551,6 +550,19 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
return samples_received; return samples_received;
} }
static int trx_usrp_issue_stream_cmd(openair0_device *device, openair0_timestamp ptimestamp, int nsamps){
usrp_state_t *s = (usrp_state_t *)device->priv;
uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);
stream_cmd.num_samps = nsamps;
stream_cmd.stream_now = false;
stream_cmd.time_spec = uhd::time_spec_t::from_ticks(ptimestamp,s->sample_rate);
s->rx_stream->issue_stream_cmd(stream_cmd);
return 0;
}
/*! \brief Compares two variables within precision /*! \brief Compares two variables within precision
* \param a first variable * \param a first variable
* \param b second variable * \param b second variable
...@@ -1088,11 +1100,17 @@ extern "C" { ...@@ -1088,11 +1100,17 @@ extern "C" {
s->tx_stream = s->usrp->get_tx_stream(stream_args_tx); s->tx_stream = s->usrp->get_tx_stream(stream_args_tx);
/* Setting TX/RX BW after streamers are created due to USRP calibration issue */ /* Setting TX/RX BW after streamers are created due to USRP calibration issue */
for(int i=0; i<((int) s->usrp->get_tx_num_channels()) && i<openair0_cfg[0].tx_num_channels; i++) for(int i=0; i<((int) s->usrp->get_tx_num_channels()) && i<openair0_cfg[0].tx_num_channels; i++) {
s->usrp->set_tx_bandwidth(openair0_cfg[0].tx_bw,i); s->usrp->set_tx_bandwidth(openair0_cfg[0].tx_bw,i);
if (device->openair0_cfg->use_single_antenna_port_for_tdd==1)
for(int i=0; i<((int) s->usrp->get_rx_num_channels()) && i<openair0_cfg[0].rx_num_channels; i++) s->usrp->set_tx_antenna("TX/RX",i);
}
for(int i=0; i<((int) s->usrp->get_rx_num_channels()) && i<openair0_cfg[0].rx_num_channels; i++) {
s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i); s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i);
if (device->openair0_cfg->use_single_antenna_port_for_tdd==1)
s->usrp->set_rx_antenna("TX/RX",i);
}
for (int i=0; i<openair0_cfg[0].rx_num_channels; i++) { for (int i=0; i<openair0_cfg[0].rx_num_channels; i++) {
LOG_I(HW,"RX Channel %d\n",i); LOG_I(HW,"RX Channel %d\n",i);
...@@ -1116,6 +1134,7 @@ extern "C" { ...@@ -1116,6 +1134,7 @@ extern "C" {
LOG_I(HW,"Device timestamp: %f...\n", s->usrp->get_time_now().get_real_secs()); LOG_I(HW,"Device timestamp: %f...\n", s->usrp->get_time_now().get_real_secs());
device->trx_write_func = trx_usrp_write; device->trx_write_func = trx_usrp_write;
device->trx_read_func = trx_usrp_read; device->trx_read_func = trx_usrp_read;
device->trx_issue_stream_cmd = trx_usrp_issue_stream_cmd;
s->sample_rate = openair0_cfg[0].sample_rate; s->sample_rate = openair0_cfg[0].sample_rate;
// TODO: // TODO:
......
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