Commit d2190230 authored by Florian Kaltenberger's avatar Florian Kaltenberger

first version of RX timed read. to be tested

parent 27266ddc
......@@ -625,55 +625,68 @@ void *emulatedRF_thread(void *param) {
void rx_rf(RU_t *ru,int *frame,int *slot) {
RU_proc_t *proc = &ru->proc;
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];
unsigned int rxs;
unsigned int rxs, siglen;
int i;
uint32_t samples_per_slot = fp->get_samples_per_slot(*slot,fp);
openair0_timestamp ts,old_ts;
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++)
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 );
old_ts = proc->timestamp_rx;
LOG_D(PHY,"Reading %d samples for slot %d (%p)\n",samples_per_slot,*slot,rxp[0]);
if (proc->first_rx==1) {
proc->timestamp_rx = 0;
proc->first_rx = 0;
}
int slot_type = nr_slot_select(cfg,*frame,*slot%fp->slots_per_frame);
if (slot_type == NR_DOWNLINK_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);
siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + (rxsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples);
}
else {
siglen = samples_per_slot;
}
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 = siglen;
}
else {
rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
&ts,
proc->timestamp_rx,
rxp,
samples_per_slot,
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);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
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);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
if (proc->first_rx == 1) {
ru->ts_offset = proc->timestamp_rx;
proc->timestamp_rx = 0;
} else {
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);
ru->ts_offset += (proc->timestamp_rx - old_ts - samples_per_slot);
proc->timestamp_rx = ts-ru->ts_offset;
}
}
//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 += samples_per_slot;
proc->frame_rx = *frame;
proc->tti_rx = *slot;
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_subframe*10))&1023;
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);
// 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",
ru->idx,
......@@ -687,29 +700,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 );
}
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);
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 +728,7 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
if(slot_type == NR_MIXED_SLOT) {
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)
txsymb++;
}
......@@ -920,6 +913,7 @@ int wakeup_synch(RU_t *ru) {
return(0);
}
/*
void do_ru_synch(RU_t *ru) {
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
RU_proc_t *proc = &ru->proc;
......@@ -991,7 +985,7 @@ void do_ru_synch(RU_t *ru) {
ru->rfdevice.trx_set_freq_func(&ru->rfdevice,ru->rfdevice.openair0_cfg,0);
}
*/
void wakeup_gNB_L1s(RU_t *ru) {
......@@ -1480,7 +1474,7 @@ void *ru_thread( void *param ) {
} 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 ((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);
......
......@@ -355,7 +355,7 @@ struct openair0_device_t {
* \param antenna_id Index of antenna for which to receive samples
* \returns the number of sample read
*/
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);
/*! \brief print the device statistics
* \param device the hardware to use
......
......@@ -106,6 +106,7 @@ typedef struct {
int wait_for_first_pps;
int use_gps;
int first_tx;
int first_rx;
//! timestamp of RX packet
openair0_timestamp rx_timestamp;
uint32_t recplay_mode;
......@@ -284,7 +285,7 @@ static int trx_usrp_start(openair0_device *device) {
// 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 0
// set the output pins to 1
s->usrp->set_gpio_attr("FP0", "OUT", 7<<7, 0xf80);
// init recv and send streaming
......@@ -526,7 +527,7 @@ static int trx_usrp_write(openair0_device *device,
* \param antenna_id Index of antenna for which to receive samples
* \returns the number of sample read
*/
static int trx_usrp_read_recplay(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
static int trx_usrp_read_recplay(openair0_device *device, openair0_timestamp ptimestamp, void **buff, int nsamps, int cc) {
int samples_received=0;
static unsigned int cur_samples;
static int64_t wrap_count;
......@@ -555,11 +556,11 @@ static int trx_usrp_read_recplay(openair0_device *device, openair0_timestamp *pt
if (s->recplay_state->use_mmap) {
if (cur_samples < s->recplay_state->nb_samples) {
*ptimestamp = (s->recplay_state->ms_sample[0].ts + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000))) + wrap_ts;
//*ptimestamp = (s->recplay_state->ms_sample[0].ts + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000))) + wrap_ts;
if (cur_samples == 0) {
std::cerr << "starting subframes file with wrap_count=" << wrap_count << " wrap_ts=" << wrap_ts
<< " ts=" << *ptimestamp << std::endl;
<< " ts=" << ptimestamp << std::endl;
}
memcpy(buff[0], &s->recplay_state->ms_sample[cur_samples].samples[0], nsamps*4);
......@@ -583,11 +584,11 @@ static int trx_usrp_read_recplay(openair0_device *device, openair0_timestamp *pt
ts0 = s->recplay_state->ms_sample->ts;
}
*ptimestamp = ts0 + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000)) + wrap_ts;
//*ptimestamp = ts0 + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000)) + wrap_ts;
if (cur_samples == 0) {
std::cerr << "starting subframes file with wrap_count=" << wrap_count << " wrap_ts=" << wrap_ts
<< " ts=" << *ptimestamp << std::endl;
<< " ts=" << ptimestamp << std::endl;
}
memcpy(buff[0], &s->recplay_state->ms_sample->samples[0], nsamps*4);
......@@ -626,7 +627,7 @@ static int trx_usrp_read_recplay(openair0_device *device, openair0_timestamp *pt
* \param antenna_id Index of antenna for which to receive samples
* \returns the number of sample read
*/
static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
static int trx_usrp_read(openair0_device *device, openair0_timestamp ptimestamp, void **buff, int nsamps, int cc) {
usrp_state_t *s = (usrp_state_t *)device->priv;
int samples_received=0;
int nsamps2; // aligned to upper 32 or 16 byte boundary
......@@ -643,7 +644,16 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
int16x8_t buff_tmp[2][nsamps2];
#endif
if (device->type == USRP_B200_DEV) {
if (ptimestamp==0)
s->usrp->set_time_now(uhd::time_spec_t(0.0));
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(ptimestamp,s->sample_rate);
s->rx_stream->issue_stream_cmd(stream_cmd);
if (cc>1) {
// receive multiple channels (e.g. RF A and RF B)
std::vector<void *> buff_ptrs;
......@@ -692,19 +702,6 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
#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]);
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);
......@@ -714,13 +711,12 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
s->rx_count += nsamps;
s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
*ptimestamp = s->rx_timestamp;
if (s->recplay_mode == RECPLAY_RECORDMODE) { // record mode
// Copy subframes to memory (later dump on a file)
if (s->recplay_state->nb_samples < s->recplay_state->u_sf_max) {
(s->recplay_state->ms_sample+s->recplay_state->nb_samples)->header = BELL_LABS_IQ_HEADER;
(s->recplay_state->ms_sample+s->recplay_state->nb_samples)->ts = *ptimestamp;
(s->recplay_state->ms_sample+s->recplay_state->nb_samples)->ts = ptimestamp;
memcpy((s->recplay_state->ms_sample+s->recplay_state->nb_samples)->samples, buff[0], nsamps*4);
s->recplay_state->nb_samples++;
} else exit_function(__FILE__, __FUNCTION__, __LINE__,"Recording reaches max iq limit\n");
......
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