Added pre/post padding for TX bursts.

This commit is contained in:
ismagom 2015-06-05 22:31:28 +02:00
parent 3f871a14a3
commit e093b3a7de
12 changed files with 121 additions and 49 deletions

View File

@ -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;

View File

@ -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;
};
}

View File

@ -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()

View File

@ -167,6 +167,8 @@ private:
float old_gain;
uint32_t sr_tx_tti;
bool is_first_of_burst;
};
}

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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");
}
}

View File

@ -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

View File

@ -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");

View File

@ -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;
}