mirror of https://github.com/PentHertz/srsLTE.git
Added pre/post padding for TX bursts.
This commit is contained in:
parent
3f871a14a3
commit
e093b3a7de
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -167,6 +167,8 @@ private:
|
|||
float old_gain;
|
||||
uint32_t sr_tx_tti;
|
||||
|
||||
bool is_first_of_burst;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(nframe<nof_frames) {
|
||||
printf("Rx subframe %d\n", nframe);
|
||||
cuhd_recv_with_time(uhd, &rx_buffer[flen*nframe], flen, true, &tstamp.full_secs, &tstamp.frac_secs);
|
||||
nframe++;
|
||||
if (nframe==9 || nframe==8) {
|
||||
srslte_timestamp_add(&tstamp, 0, 2e-3);
|
||||
srslte_timestamp_add(&tstamp, 0, 2e-3-burst_settle_time);
|
||||
if (nframe==8) {
|
||||
cuhd_send_timed2(uhd, zeros, flen, tstamp.full_secs, tstamp.frac_secs, true, false);
|
||||
//cuhd_send_timed2(uhd, zeros, flen, tstamp.full_secs, tstamp.frac_secs, true, false);
|
||||
printf("Transmitting zeros\n");
|
||||
} else {
|
||||
cuhd_send_timed2(uhd, tx_buffer, flen, tstamp.full_secs, tstamp.frac_secs, false, true);
|
||||
cuhd_send_timed2(uhd, tx_buffer, flen+nsamples_adv, tstamp.full_secs, tstamp.frac_secs, true, true);
|
||||
printf("Transmitting Signal\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,4 +149,10 @@ SRSLTE_API void srslte_ue_ul_reset(srslte_ue_ul_t *q);
|
|||
SRSLTE_API void srslte_ue_ul_set_rnti(srslte_ue_ul_t *q,
|
||||
uint16_t rnti);
|
||||
|
||||
/* Other static functions for UL PHY procedures defined in 36.213 */
|
||||
|
||||
SRSLTE_API int srslte_ue_ul_sr_config(uint32_t I_sr,
|
||||
uint32_t *sr_periodicity,
|
||||
uint32_t *sr_N_offset);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -162,7 +162,7 @@ int cuhd_open_(char *args, void **h, bool create_thread_gain, bool tx_gain_same_
|
|||
{
|
||||
cuhd_handler *handler = new cuhd_handler();
|
||||
std::string _args = std::string(args);
|
||||
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=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");
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue