diff --git a/srsapps/radio/include/srsapps/radio/radio.h b/srsapps/radio/include/srsapps/radio/radio.h index 8a98ba44d..8f192a3a6 100644 --- a/srsapps/radio/include/srsapps/radio/radio.h +++ b/srsapps/radio/include/srsapps/radio/radio.h @@ -42,6 +42,7 @@ namespace srslte { public: virtual void get_time(srslte_timestamp_t *now) = 0; virtual bool tx(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) = 0; + virtual bool tx_end() = 0; virtual bool rx_now(void *buffer, uint32_t nof_samples, srslte_timestamp_t *rxd_time) = 0; virtual bool rx_at(void *buffer, uint32_t nof_samples, srslte_timestamp_t rx_time) = 0; diff --git a/srsapps/radio/include/srsapps/radio/radio_uhd.h b/srsapps/radio/include/srsapps/radio/radio_uhd.h index 22ae95756..e7b33e6e3 100644 --- a/srsapps/radio/include/srsapps/radio/radio_uhd.h +++ b/srsapps/radio/include/srsapps/radio/radio_uhd.h @@ -49,6 +49,7 @@ namespace srslte { void get_time(srslte_timestamp_t *now); bool tx(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time); + bool tx_end(); bool rx_now(void *buffer, uint32_t nof_samples, srslte_timestamp_t *rxd_time); bool rx_at(void *buffer, uint32_t nof_samples, srslte_timestamp_t rx_time); @@ -72,7 +73,17 @@ namespace srslte { private: void *uhd; - bool is_first; + + static const double lo_offset = 8e6; // LO offset (in Hz) + static const double burst_settle_time = 0.4e-3; // Start of burst settle time (off->on RF transition time) + const static uint32_t burst_settle_max_samples = 12288; // 30.72 MHz is maximum frequency + + srslte_timestamp_t end_of_burst_time; + bool is_start_of_burst; + uint32_t burst_settle_samples; + double burst_settle_time_rounded; // settle time rounded to sample time + cf_t zeros[burst_settle_max_samples]; + double cur_tx_srate; }; } diff --git a/srsapps/radio/src/radio_uhd.cc b/srsapps/radio/src/radio_uhd.cc index 0ba16daf1..a5a0cd17a 100644 --- a/srsapps/radio/src/radio_uhd.cc +++ b/srsapps/radio/src/radio_uhd.cc @@ -28,7 +28,6 @@ #include "srslte/srslte.h" #include "srsapps/radio/radio_uhd.h" - namespace srslte { bool radio_uhd::init() @@ -57,7 +56,6 @@ void radio_uhd::set_tx_rx_gain_offset(float offset) { bool radio_uhd::init_agc(char *args) { - is_first = true; printf("Opening UHD device with threaded RX Gain control ...\n"); if (cuhd_open_th(args, &uhd, true)) { fprintf(stderr, "Error opening uhd\n"); @@ -65,6 +63,11 @@ bool radio_uhd::init_agc(char *args) } cuhd_set_rx_gain(uhd, 40); cuhd_set_tx_gain(uhd, 40); + + burst_settle_samples = 0; + burst_settle_time_rounded = 0; + is_start_of_burst = true; + return true; } bool radio_uhd::rx_at(void* buffer, uint32_t nof_samples, srslte_timestamp_t rx_time) @@ -88,14 +91,31 @@ void radio_uhd::get_time(srslte_timestamp_t *now) { bool radio_uhd::tx(void* buffer, uint32_t nof_samples, srslte_timestamp_t tx_time) { - if (cuhd_send_timed2(uhd, buffer, nof_samples, tx_time.full_secs, tx_time.frac_secs, is_first, false) > 0) { - is_first = false; + if (is_start_of_burst) { + if (burst_settle_samples != 0) { + srslte_timestamp_t tx_time_pad; + srslte_timestamp_copy(&tx_time_pad, &tx_time); + srslte_timestamp_sub(&tx_time_pad, 0, burst_settle_time_rounded); + cuhd_send_timed2(uhd, zeros, burst_settle_samples, tx_time_pad.full_secs, tx_time_pad.frac_secs, true, false); + } + is_start_of_burst = false; + srslte_timestamp_copy(&end_of_burst_time, &tx_time); + srslte_timestamp_add(&end_of_burst_time, 0, nof_samples*cur_tx_srate); + } + + if (cuhd_send_timed2(uhd, buffer, nof_samples, tx_time.full_secs, tx_time.frac_secs, false, false) > 0) { return true; } else { return false; } } +bool radio_uhd::tx_end() +{ + cuhd_send_timed2(uhd, zeros, burst_settle_samples, end_of_burst_time.full_secs, end_of_burst_time.frac_secs, false, true); + is_start_of_burst = true; +} + void radio_uhd::set_rx_freq(float freq) { cuhd_set_rx_freq(uhd, freq); @@ -118,8 +138,7 @@ void radio_uhd::set_rx_srate(float srate) void radio_uhd::set_tx_freq(float freq) { - //cuhd_set_tx_freq(uhd, freq); - cuhd_set_tx_freq_offset(uhd, freq, 8e6); + cuhd_set_tx_freq_offset(uhd, freq, lo_offset); } void radio_uhd::set_tx_gain(float gain) @@ -139,7 +158,13 @@ float radio_uhd::get_rx_gain() void radio_uhd::set_tx_srate(float srate) { - cuhd_set_tx_srate(uhd, srate); + cur_tx_srate = cuhd_set_tx_srate(uhd, srate); + burst_settle_samples = (uint32_t) (cur_tx_srate * burst_settle_time); + if (burst_settle_samples > burst_settle_max_samples) { + burst_settle_samples = burst_settle_max_samples; + fprintf(stderr, "Error setting TX srate %.1f MHz. Maximum frequency for zero prepadding is 30.72 MHz\n", srate*1e-6); + } + burst_settle_time_rounded = (double) burst_settle_samples/cur_tx_srate; } void radio_uhd::start_rx() diff --git a/srsapps/ue/phy/include/srsapps/ue/phy/phy.h b/srsapps/ue/phy/include/srsapps/ue/phy/phy.h index 45f862b8f..564a4da16 100644 --- a/srsapps/ue/phy/include/srsapps/ue/phy/phy.h +++ b/srsapps/ue/phy/include/srsapps/ue/phy/phy.h @@ -167,6 +167,8 @@ private: float old_gain; uint32_t sr_tx_tti; + bool is_first_of_burst; + }; } diff --git a/srsapps/ue/phy/include/srsapps/ue/phy/ul_buffer.h b/srsapps/ue/phy/include/srsapps/ue/phy/ul_buffer.h index b08faecf7..615ce3151 100644 --- a/srsapps/ue/phy/include/srsapps/ue/phy/ul_buffer.h +++ b/srsapps/ue/phy/include/srsapps/ue/phy/ul_buffer.h @@ -59,11 +59,9 @@ namespace ue { bool generate_data(); bool generate_data(ul_sched_grant *pusch_grant, uint8_t *payload); bool generate_data(ul_sched_grant *pusch_grant, srslte_softbuffer_tx_t *softbuffer, uint8_t *payload); - bool send(radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time, bool normalize_amp); bool send(radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time); - bool send_zeros(radio* radio_handler, float time_adv_sec, srslte_timestamp_t rx_time); static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission - + static const bool normalize_amp = true; private: log *log_h; phy_params *params_db; diff --git a/srsapps/ue/phy/src/phy.cc b/srsapps/ue/phy/src/phy.cc index 313d260d5..3406633ea 100644 --- a/srsapps/ue/phy/src/phy.cc +++ b/srsapps/ue/phy/src/phy.cc @@ -74,6 +74,7 @@ bool phy::init_(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_, l dl_buffer_queue = new queue(6, sizeof(dl_buffer)); do_agc = do_agc_; last_gain = 1e4; + time_adv_sec = 0; // Set default params params_db.set_param(phy_params::CELLSEARCH_TIMEOUT_PSS_NFRAMES, 100); @@ -143,8 +144,8 @@ bool phy::send_prach(uint32_t preamble_idx, int allowed_subframe, int target_pow if (phy_state == RXTX) { srslte_agc_lock(&ue_sync.agc, true); old_gain = radio_handler->get_tx_gain(); - radio_handler->set_tx_gain(0); - Info("Stopped AGC. Set TX gain to %.1f dB\n", 0); + radio_handler->set_tx_gain(10); + Info("Stopped AGC. Set TX gain to %.1f dB\n", radio_handler->get_tx_gain()); return prach_buffer.prepare_to_send(preamble_idx, allowed_subframe, target_power_dbm); } return false; @@ -508,7 +509,8 @@ void phy::run_rx_tx_state() phy_state = IDLE; break; case 1: - is_sfn_synched = true; + is_sfn_synched = true; + is_first_of_burst = true; break; case 0: break; @@ -520,7 +522,7 @@ void phy::run_rx_tx_state() bool tx_zeros = true; - // Prepare transmission for the next tti + // Advance transmission time for the next tti srslte_timestamp_add(&last_rx_time, 0, 1e-3); // Generate scheduling request if we have to @@ -543,17 +545,15 @@ void phy::run_rx_tx_state() get_ul_buffer_adv(current_tti)->generate_data(); } // And transmit - get_ul_buffer_adv(current_tti)->send(radio_handler, time_adv_sec, cfo, last_rx_time); + get_ul_buffer_adv(current_tti)->send(radio_handler, time_adv_sec, cfo, last_rx_time); + is_first_of_burst = false; } else { - // Transmit zeros to avoid transitions. - // FIXME: This keeps the TX RF chain always on. Should transmit zeros only before a true transmission - get_ul_buffer_adv(current_tti)->send_zeros(radio_handler, time_adv_sec, last_rx_time); + if (!is_first_of_burst) { + radio_handler->tx_end(); + is_first_of_burst = true; + } } - - // send ul buffer if we have to - // Generate PUCCH if no UL grant - // Receive alligned buffer for the current tti get_dl_buffer(current_tti)->recv_ue_sync(&ue_sync, &last_rx_time); diff --git a/srsapps/ue/phy/src/prach.cc b/srsapps/ue/phy/src/prach.cc index 066d3174a..820283e1b 100644 --- a/srsapps/ue/phy/src/prach.cc +++ b/srsapps/ue/phy/src/prach.cc @@ -160,7 +160,6 @@ bool prach::send(radio *radio_handler, float cfo, srslte_timestamp_t rx_time) } } - // transmit radio_handler->tx(signal_buffer, len, tx_time); Info("PRACH transmitted CFO: %f, preamble=%d, len=%d rx_time=%f, tx_time=%f, PeakAmplitude=%.2f\n", cfo*15000, preamble_idx, len, rx_time.frac_secs, tx_time.frac_secs, max); diff --git a/srsapps/ue/phy/src/ul_buffer.cc b/srsapps/ue/phy/src/ul_buffer.cc index 7d55fa349..f7e039538 100644 --- a/srsapps/ue/phy/src/ul_buffer.cc +++ b/srsapps/ue/phy/src/ul_buffer.cc @@ -49,7 +49,7 @@ bool ul_buffer::init_cell(srslte_cell_t cell_, phy_params *params_db_, log *log_ if (!srslte_ue_ul_init(&ue_ul, cell)) { srslte_ue_ul_set_normalization(&ue_ul, false); signal_buffer = (cf_t*) srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); - cell_initiated = signal_buffer?true:false; + cell_initiated = (signal_buffer)?true:false; srslte_ue_ul_set_cfo_enable(&ue_ul, false); bzero(&uci_data, sizeof(srslte_uci_data_t)); uci_pending = false; @@ -218,21 +218,9 @@ bool ul_buffer::generate_data(ul_sched_grant *grant, srslte_softbuffer_tx_t *sof int nof_tx = 0; -bool ul_buffer::send_zeros(srslte::radio* radio_handler, float time_adv_sec, srslte_timestamp_t rx_time) -{ - bzero(signal_buffer, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb)); - send(radio_handler, time_adv_sec, 0, rx_time, false); -} - bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time) -{ - send(radio_handler, time_adv_sec, cfo, rx_time, true); -} - -bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time, bool normalize_amp) -{ - - // send packet through usrp +{ + // send packet next timeslot minus time advance srslte_timestamp_t tx_time; srslte_timestamp_copy(&tx_time, &rx_time); srslte_timestamp_add(&tx_time, 0, tx_advance_sf*1e-3 - time_adv_sec); @@ -256,7 +244,7 @@ bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo srslte_vec_sc_prod_cfc(signal_buffer, 0.9/max, signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb)); } - Info("TX CFO: %f, len=%d, rx_time= %.6f tx_time = %.6f TA: %.1f us PeakAmplitude=%.2f PKT#%d\n", + Info("TX CFO: %f, len=%d, rx_time= %.6f tx_time = %.6f TA: %.1f PeakAmplitude=%.2f PKT#%d\n", cfo*15000, SRSLTE_SF_LEN_PRB(cell.nof_prb), srslte_timestamp_real(&rx_time), srslte_timestamp_real(&tx_time), time_adv_sec*1000000, max, nof_tx); diff --git a/srslte/examples/usrp_txrx.c b/srslte/examples/usrp_txrx.c index b0b79ad4e..f86ce4e26 100644 --- a/srslte/examples/usrp_txrx.c +++ b/srslte/examples/usrp_txrx.c @@ -98,6 +98,7 @@ int main(int argc, char **argv) { parse_args(argc, argv); uint32_t flen = srslte_sampling_freq_hz(nof_prb)/1000; + uint32_t nsamples_adv = 3000; cf_t *rx_buffer = malloc(sizeof(cf_t)*flen*nof_frames); if (!rx_buffer) { @@ -105,11 +106,13 @@ int main(int argc, char **argv) { exit(-1); } - cf_t *tx_buffer = malloc(sizeof(cf_t)*flen); + cf_t *tx_buffer = malloc(sizeof(cf_t)*(flen+nsamples_adv)); if (!tx_buffer) { perror("malloc"); exit(-1); } + bzero(tx_buffer, sizeof(cf_t)*(flen+nsamples_adv)); + cf_t *zeros = calloc(sizeof(cf_t),flen); if (!zeros) { perror("calloc"); @@ -132,24 +135,28 @@ int main(int argc, char **argv) { cuhd_set_tx_freq_offset(uhd, uhd_freq, 8e6); sleep(1); - srslte_vec_load_file(input_filename, tx_buffer, flen*sizeof(cf_t)); + srslte_vec_load_file(input_filename, &tx_buffer[nsamples_adv], flen*sizeof(cf_t)); srslte_timestamp_t tstamp; cuhd_start_rx_stream(uhd); uint32_t nframe=0; + float burst_settle_time = (float) nsamples_adv/srslte_sampling_freq_hz(nof_prb); + + printf("timeadv=%f\n",burst_settle_time); + while(nframeusrp = uhd::usrp::multi_usrp::make(_args);// + ", master_clock_rate=30720000, num_recv_frames=512"); + handler->usrp = uhd::usrp::multi_usrp::make(_args + ", master_clock_rate=30720000, num_recv_frames=512"); // handler->usrp = uhd::usrp::multi_usrp::make(_args + ", master_clock_rate=50000000" + ", num_recv_frames=512"); handler->usrp->set_clock_source("internal"); diff --git a/srslte/lib/ue/src/ue_ul.c b/srslte/lib/ue/src/ue_ul.c index 97ec24e35..982b386aa 100644 --- a/srslte/lib/ue/src/ue_ul.c +++ b/srslte/lib/ue/src/ue_ul.c @@ -374,6 +374,41 @@ int srslte_ue_ul_pusch_encode_cfg(srslte_ue_ul_t *q, srslte_pusch_cfg_t *cfg, ret = SRSLTE_SUCCESS; } - return ret; - -} \ No newline at end of file + return ret; +} + +/* Obtains Scheduling Request channel assignment as defined in Table 10.1-5, 36.213 */ +int srslte_ue_ul_sr_config(uint32_t I_sr, uint32_t *sr_periodicity, uint32_t *sr_N_offset) { + if (sr_periodicity && sr_N_offset) { + if (I_sr < 5) { + *sr_periodicity = 5; + *sr_N_offset = I_sr; + } else if (I_sr < 15) { + *sr_periodicity = 10; + *sr_N_offset = I_sr-5; + } else if (I_sr < 35) { + *sr_periodicity = 20; + *sr_N_offset = I_sr-15; + } else if (I_sr < 75) { + *sr_periodicity = 40; + *sr_N_offset = I_sr-35; + } else if (I_sr < 155) { + *sr_periodicity = 80; + *sr_N_offset = I_sr-75; + } else if (I_sr < 157) { + *sr_periodicity = 2; + *sr_N_offset = I_sr-155; + } else if (I_sr == 157) { + *sr_periodicity = 1; + *sr_N_offset = I_sr-157; + } else { + return SRSLTE_ERROR; + } + } else { + return SRSLTE_ERROR_INVALID_INPUTS; + } + return SRSLTE_SUCCESS; +} + + +