Merge branch 'add_tx_zeros' into working_mac

Conflicts:
	srslte/lib/cuhd/src/cuhd_imp.cpp
This commit is contained in:
ismagom 2015-06-06 18:47:47 +02:00
commit e3dd3c3f88
25 changed files with 412 additions and 128 deletions

View File

@ -27,8 +27,8 @@ for n_rb=1:length(NULRB)
lib=srslte_prach(ueConfig,prachConfig);
[mat, info]=ltePRACH(ueConfig,prachConfig);
err=mean(abs(mat-lib));
if (err > 10^-3)
err=max(abs(mat-lib));
if (err > 2*10^-3)
disp(err)
a=1:100;
plot(a,real(lib(a)),a,real(mat(a)))

View File

@ -1,9 +1,9 @@
ueConfig=struct('NCellID',1,'NULRB',25,'NSubframe',8,'RNTI',71,'CyclicPrefixUL','Normal','NTxAnts',1,'Shortened',0);
ueConfig=struct('NCellID',1,'NULRB',25,'NSubframe',8,'RNTI',77,'CyclicPrefixUL','Normal','NTxAnts',1,'Shortened',0);
puschConfig=struct('NTurboDecIts',5,'NLayers',1,'OrthCover','Off','PRBSet',22,'Modulation','16QAM','RV',0);
TBS=336;
cfo=3400;
t0=128;
cfo=0;
t0=68;
x=[rx(t0:end); zeros(t0-1,1)];
subframe_rx=lteSCFDMADemodulate(ueConfig,x.*exp(-1i*2*pi*cfo/15000*transpose(1:length(x))/512));

View File

@ -1,5 +1,5 @@
ueConfig=struct('NCellID',1,'NULRB',25,'RNTI',77,'CyclicPrefixUL','Normal','NTxAnts',1,'Shortened',1);
puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',22,'Shortened',1);
puschConfig=struct('NLayers',1,'OrthCover','Off','PRBSet',22,'Shortened',0);
addpath('../../build/srslte/lib/phch/test')
@ -41,14 +41,17 @@ for i=1:length(TBs)
if (cqilen(c)>0 || TBs(i)>0)
[cw, info]=lteULSCH(ueConfig,puschConfig,trblkin);
cw_mat=ltePUSCH(ueConfig,puschConfig,cw);
drs=ltePUSCHDRS(ueConfig,puschConfig);
idx=ltePUSCHIndices(ueConfig,puschConfig);
drs_idx=ltePUSCHDRSIndices(ueConfig,puschConfig);
subframe_mat = lteULResourceGrid(ueConfig);
subframe_mat(idx)=cw_mat;
subframe_mat(drs_idx)=drs;
waveform = lteSCFDMAModulate(ueConfig,subframe_mat,0);
[waveform_lib, subframe_lib, cwlib]=srslte_pusch_encode(ueConfig,puschConfig,trblkin,ones(1,cqilen(c)),ri_bit,ack_bit);
err=mean(abs(waveform-waveform_lib));
if (err > 10^-3)
if (err > 10^-8)
disp(err)
error('Error!');
end

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,6 +73,17 @@ namespace srslte {
private:
void *uhd;
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()
@ -64,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)
@ -87,13 +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_timed(uhd, buffer, nof_samples, tx_time.full_secs, tx_time.frac_secs) > 0) {
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);
@ -116,7 +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, lo_offset);
}
void radio_uhd::set_tx_gain(float gain)
@ -136,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

@ -239,7 +239,6 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
}
// MAC control element for PHR
// TODO
printf("1 nof_subh=%d, rem_size=%d\n", pdu_msg.nof_subh(), pdu_msg.rem_size());
// data from any Logical Channel, except data from UL-CCCH;
// first only those with positive Bj
@ -252,15 +251,12 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
}
}
}
printf("2 nof_subh=%d, rem_size=%d\n", pdu_msg.nof_subh(), pdu_msg.rem_size());
// If resources remain, allocate regardless of their Bj value
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
while (allocate_sdu(lchid_sorted[i], &pdu_msg));
}
printf("3 nof_subh=%d, rem_size=%d\n", pdu_msg.nof_subh(), pdu_msg.rem_size());
bool send_bsr = bsr_procedure->generate_bsr_on_ul_grant(pdu_msg.rem_size(), &bsr);
// Insert Padding BSR if not inserted Regular/Periodic BSR
if (!bsr_payload_sz && send_bsr) {

View File

@ -202,7 +202,7 @@ void process_connsetup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *msg, srslte::ue::mac
// FIXME: There's an error parsing the connectionSetup message. This value is hard-coded:
phy->set_param(srslte::ue::phy_params::SR_PUCCH_RESINDEX,
phy->set_param(srslte::ue::phy_params::PUCCH_N_PUCCH_SR,
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_pucch_resource_idx);
phy->set_param(srslte::ue::phy_params::SR_CONFIG_INDEX,
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_cnfg_idx);

View File

@ -152,10 +152,7 @@ private:
bool do_agc;
double last_gain;
uint32_t sr_N_offset;
uint32_t sr_periodicity;
bool sr_enabled;
uint32_t sr_n_pucch;
bool sr_is_ready_to_send(uint32_t tti);
bool init_(radio *radio_handler, tti_sync *ttisync, log *log_h, bool do_agc);
@ -167,6 +164,8 @@ private:
float old_gain;
uint32_t sr_tx_tti;
bool is_first_of_burst;
};
}

View File

@ -77,7 +77,6 @@ namespace ue {
PUCCH_N_PUCCH_2,
PUCCH_N_PUCCH_SR,
SR_PUCCH_RESINDEX,
SR_CONFIG_INDEX,
UCI_I_OFFSET_ACK,

View File

@ -61,7 +61,7 @@ namespace ue {
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);
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

@ -40,8 +40,12 @@ namespace ue {
class ul_sched_grant : public sched_grant {
public:
ul_sched_grant(rnti_type_t type, uint16_t rnti) : sched_grant(type, rnti) {}
ul_sched_grant(uint16_t rnti) : sched_grant(rnti) {}
ul_sched_grant(rnti_type_t type, uint16_t rnti) : sched_grant(type, rnti) {
N_srs = 0;
}
ul_sched_grant(uint16_t rnti) : sched_grant(rnti) {
N_srs = 0;
}
uint32_t get_rv() {
return ul_dci.rv_idx;
@ -55,6 +59,13 @@ namespace ue {
void set_ndi(bool value) {
ul_dci.ndi = value;
}
void set_shortened(bool enabled) {
if (enabled) {
N_srs = 1;
} else {
N_srs = 0;
}
}
bool get_cqi_request() {
return ul_dci.cqi_request;
}
@ -85,7 +96,7 @@ namespace ue {
bool is_from_rar() {
return grant_is_from_rar;
}
bool create_from_dci(srslte_dci_msg_t *msg, srslte_cell_t cell, uint32_t N_srs, uint32_t n_rb_ho) {
bool create_from_dci(srslte_dci_msg_t *msg, srslte_cell_t cell, uint32_t n_rb_ho) {
grant_is_from_rar = false;
if (srslte_dci_msg_to_ul_grant(msg, cell, N_srs, n_rb_ho, &ul_dci, &grant)) {
return false;
@ -120,6 +131,7 @@ namespace ue {
uint32_t current_tx_nb;
uint16_t rnti;
bool grant_is_from_rar;
uint32_t N_srs;
};
}

View File

@ -116,7 +116,7 @@ bool dl_buffer::get_ul_grant(ul_sched_grant *grant)
if (srslte_ue_dl_find_ul_dci(&ue_dl, &dci_msg, cfi, tti%10, grant->get_rnti()) != 1) {
return false;
}
return grant->create_from_dci(&dci_msg, cell, 0, params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET));
return grant->create_from_dci(&dci_msg, cell, params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET));
}
}
}

View File

@ -74,6 +74,8 @@ 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;
sr_tx_tti = 0;
// Set default params
params_db.set_param(phy_params::CELLSEARCH_TIMEOUT_PSS_NFRAMES, 100);
@ -108,15 +110,14 @@ radio* phy::get_radio() {
}
void phy::set_timeadv_rar(uint32_t ta_cmd) {
ta_cmd=7;
n_ta = srslte_N_ta_new_rar(ta_cmd);
time_adv_sec = ((float) n_ta)/(15000.0*srslte_symbol_sz(cell.nof_prb));
time_adv_sec = ((float) n_ta)*SRSLTE_LTE_TS;
Info("Set TA RAR: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, time_adv_sec*1e6);
}
void phy::set_timeadv(uint32_t ta_cmd) {
n_ta = srslte_N_ta_new(n_ta, ta_cmd);
time_adv_sec = ((float) n_ta)/(15000.0*srslte_symbol_sz(cell.nof_prb));
time_adv_sec = ((float) n_ta)*SRSLTE_LTE_TS;
Info("Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, time_adv_sec*1e6);
}
@ -130,7 +131,6 @@ void phy::set_param(phy_params::phy_param_t param, int64_t value) {
params_db.set_param((uint32_t) param, value);
}
// FIXME: Add PRACH power control
bool phy::send_prach(uint32_t preamble_idx) {
return send_prach(preamble_idx, -1, 0);
@ -143,49 +143,16 @@ 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;
}
/* Send SR as soon as possible as defined in Section 10.2 of 36.213 */
/* Instruct the PHY to send a SR as soon as possible */
void phy::send_sr(bool enable)
{
if (enable) {
// Get sr_periodicity and sr_N_offset from table 10.1-5
uint32_t I_sr = params_db.get_param(phy_params::SR_CONFIG_INDEX);
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 {
Error("Invalid I_sr=%d\n", I_sr);
return;
}
sr_n_pucch = params_db.get_param(phy_params::SR_PUCCH_RESINDEX);
Info("SR I_sr=%d, periodicity=%d, N_offset=%d, n_pucch=%d\n", I_sr, sr_periodicity, sr_N_offset, sr_n_pucch);
sr_tx_tti = get_current_tti();
}
sr_enabled = enable;
}
@ -199,10 +166,12 @@ int phy::sr_last_tx_tti() {
bool phy::sr_is_ready_to_send(uint32_t tti_) {
if (sr_enabled) {
if ((10*tti_to_SFN(tti_)+tti_to_subf(tti_)-sr_N_offset)%sr_periodicity==0) {
// Get I_sr parameter
uint32_t I_sr = params_db.get_param(phy_params::SR_CONFIG_INDEX);
if (srslte_ue_ul_sr_send_tti(I_sr, tti_)) {
sr_enabled = false;
sr_tx_tti = tti_;
Debug("SR ready to send for TTI=%d\n", tti_);
Info("SR ready to send for TTI=%d\n", tti_);
return true;
}
}
@ -508,7 +477,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;
@ -518,28 +488,40 @@ void phy::run_rx_tx_state()
log_h->step(current_tti);
float cfo = srslte_ue_sync_get_cfo(&ue_sync)/15000;
// Prepare transmission for the next tti
srslte_timestamp_add(&last_rx_time, 0, 1e-3);
bool tx_zeros = true;
// send prach if we have to
if (prach_buffer.is_ready_to_send(current_tti)) {
prach_buffer.send(radio_handler, cfo, last_rx_time);
radio_handler->set_tx_gain(old_gain);
srslte_agc_lock(&ue_sync.agc, false);
Info("Restoring AGC. Set TX gain to %.1f dB\n", old_gain);
}
// Advance transmission time for the next tti
srslte_timestamp_add(&last_rx_time, 0, 1e-3);
// Generate scheduling request if we have to
if (sr_is_ready_to_send(current_tti+ul_buffer::tx_advance_sf)) {
get_ul_buffer_adv(current_tti)->generate_sr();
}
// send ul buffer if we have to
if (get_ul_buffer_adv(current_tti)->is_released() || get_ul_buffer_adv(current_tti)->uci_ready()) {
// Generate PUCCH if no UL grant
// Every subframe, TX a PRACH or a PUSCH/PUCCH
if (prach_buffer.is_ready_to_send(current_tti)) {
// send prach if we have to
prach_buffer.send(radio_handler, cfo, last_rx_time);
radio_handler->tx_end();
radio_handler->set_tx_gain(old_gain);
srslte_agc_lock(&ue_sync.agc, false);
Info("Restoring AGC. Set TX gain to %.1f dB\n", old_gain);
// If we don't transmit PRACH, check if need to transmit PUSCH/PUCCH
} else if (get_ul_buffer_adv(current_tti)->is_released() || get_ul_buffer_adv(current_tti)->uci_ready()) {
// If the packet was not generated by a call from MAC, means it's PUCCH. Generate now the signal
if (!get_ul_buffer_adv(current_tti)->is_released()) {
get_ul_buffer_adv(current_tti)->generate_data();
}
get_ul_buffer_adv(current_tti)->send(radio_handler, time_adv_sec, cfo, last_rx_time);
}
// And transmit
get_ul_buffer_adv(current_tti)->send(radio_handler, time_adv_sec, cfo, last_rx_time);
is_first_of_burst = false;
} else {
if (!is_first_of_burst) {
radio_handler->tx_end();
is_first_of_burst = true;
}
}
// Receive alligned buffer for the current tti
get_dl_buffer(current_tti)->recv_ue_sync(&ue_sync, &last_rx_time);

View File

@ -109,25 +109,11 @@ bool prach::is_ready_to_send(uint32_t current_tti_) {
if (initiated && preamble_idx >= 0 && preamble_idx < 64 && params_db != NULL) {
// consider the number of subframes the transmission must be anticipated
uint32_t current_tti = (current_tti_ + tx_advance_sf)%10240;
// Get SFN and sf_idx from the PRACH configuration index
uint32_t config_idx = (uint32_t) params_db->get_param(phy_params::PRACH_CONFIG_INDEX);
srslte_prach_sfn_t prach_sfn = srslte_prach_get_sfn(config_idx);
if (prach_sfn == SRSLTE_PRACH_SFN_EVEN && ((current_tti/10)%2)==0 ||
prach_sfn == SRSLTE_PRACH_SFN_ANY)
{
srslte_prach_sf_config_t sf_config;
srslte_prach_sf_config(config_idx, &sf_config);
for (int i=0;i<sf_config.nof_sf;i++) {
if ((current_tti%10) == sf_config.sf[i] && allowed_subframe == -1 ||
((current_tti%10) == sf_config.sf[i] && (current_tti%10) == allowed_subframe))
{
Info("PRACH Buffer: Ready to send at tti: %d (now is %d)\n", current_tti, current_tti_);
transmitted_tti = current_tti;
return true;
}
}
if (srslte_prach_send_tti(config_idx, current_tti, allowed_subframe)) {
Info("PRACH Buffer: Ready to send at tti: %d (now is %d)\n", current_tti, current_tti_);
transmitted_tti = current_tti;
return true;
}
}
return false;
@ -160,7 +146,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;
@ -219,29 +219,32 @@ bool ul_buffer::generate_data(ul_sched_grant *grant, srslte_softbuffer_tx_t *sof
int nof_tx = 0;
bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time)
{
// 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);
// Correct CFO before transmission
srslte_cfo_correct(&ue_ul.cfo, signal_buffer, signal_buffer, cfo / srslte_symbol_sz(cell.nof_prb));
if (cfo != 0) {
srslte_cfo_correct(&ue_ul.cfo, signal_buffer, signal_buffer, cfo / srslte_symbol_sz(cell.nof_prb));
}
// Compute peak
float max = 0;
float *t = (float*) signal_buffer;
for (int i=0;i<2*SRSLTE_SF_LEN_PRB(cell.nof_prb);i++) {
if (fabsf(t[i]) > max) {
max = fabsf(t[i]);
if (normalize_amp) {
float *t = (float*) signal_buffer;
for (int i=0;i<2*SRSLTE_SF_LEN_PRB(cell.nof_prb);i++) {
if (fabsf(t[i]) > max) {
max = fabsf(t[i]);
}
}
// Normalize before TX
srslte_vec_sc_prod_cfc(signal_buffer, 0.9/max, signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
// Normalize before TX
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

@ -87,6 +87,9 @@ IF(UHD_FOUND)
add_executable(usrp_capture_sync usrp_capture_sync.c)
target_link_libraries(usrp_capture_sync srslte srslte_uhd)
add_executable(usrp_txrx usrp_txrx.c)
target_link_libraries(usrp_txrx srslte srslte_uhd)
MESSAGE(STATUS " UHD examples will be installed.")
ELSE(UHD_FOUND)

173
srslte/examples/usrp_txrx.c Normal file
View File

@ -0,0 +1,173 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
#include <complex.h>
#include "srslte/cuhd/cuhd.h"
#include "srslte/srslte.h"
uint32_t nof_prb = 25;
uint32_t nof_frames = 20;
float uhd_rx_gain=40, uhd_tx_gain=40, uhd_freq=2.4e9;
char *uhd_args="";
char *output_filename = NULL;
char *input_filename = NULL;
void usage(char *prog) {
printf("Usage: %s -i [tx_signal_file] -o [rx_signal_file]\n", prog);
printf("\t-a UHD args [Default %s]\n", uhd_args);
printf("\t-f UHD TX/RX frequency [Default %.2f MHz]\n", uhd_freq/1e6);
printf("\t-g UHD RX gain [Default %.1f dB]\n", uhd_rx_gain);
printf("\t-G UHD TX gain [Default %.1f dB]\n", uhd_tx_gain);
printf("\t-p Number of UL RB [Default %d]\n", nof_prb);
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "ioafgp")) != -1) {
switch (opt) {
case 'a':
uhd_args = argv[optind];
break;
case 'o':
output_filename = argv[optind];
break;
case 'i':
input_filename = argv[optind];
break;
case 'f':
uhd_freq = atof(argv[optind]);
break;
case 'g':
uhd_rx_gain = atof(argv[optind]);
break;
case 'G':
uhd_tx_gain = atof(argv[optind]);
break;
case 'p':
nof_prb = atoi(argv[optind]);
if (!srslte_nofprb_isvalid(nof_prb)) {
fprintf(stderr, "Invalid number of UL RB %d\n", nof_prb);
exit(-1);
}
break;
default:
usage(argv[0]);
exit(-1);
}
}
if (!input_filename || !output_filename) {
usage(argv[0]);
exit(-1);
}
}
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) {
perror("malloc");
exit(-1);
}
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");
exit(-1);
}
// Send through UHD
void *uhd;
printf("Opening UHD device...\n");
if (cuhd_open(uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
exit(-1);
}
printf("Subframe len: %d samples\n", flen);
printf("Set TX/RX rate: %.2f MHz\n", cuhd_set_rx_srate(uhd, srslte_sampling_freq_hz(nof_prb)) / 1000000);
printf("Set RX gain: %.1f dB\n", cuhd_set_rx_gain(uhd, uhd_rx_gain));
printf("Set TX gain: %.1f dB\n", cuhd_set_tx_gain(uhd, uhd_tx_gain));
printf("Set TX/RX freq: %.2f MHz\n", cuhd_set_rx_freq(uhd, uhd_freq) / 1000000);
cuhd_set_tx_srate(uhd, srslte_sampling_freq_hz(nof_prb));
cuhd_set_tx_freq_offset(uhd, uhd_freq, 8e6);
sleep(1);
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-burst_settle_time);
if (nframe==8) {
//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+nsamples_adv, tstamp.full_secs, tstamp.frac_secs, true, true);
printf("Transmitting Signal\n");
}
}
}
srslte_vec_save_file(output_filename, &rx_buffer[10*flen], flen*sizeof(cf_t));
free(tx_buffer);
free(rx_buffer);
printf("Done\n");
exit(0);
}

View File

@ -103,6 +103,10 @@ SRSLTE_API uint32_t srslte_prach_get_preamble_format(uint32_t config_idx);
SRSLTE_API srslte_prach_sfn_t srslte_prach_get_sfn(uint32_t config_idx);
SRSLTE_API bool srslte_prach_send_tti(uint32_t config_idx,
uint32_t current_tti,
int allowed_subframe);
SRSLTE_API void srslte_prach_sf_config(uint32_t config_idx,
srslte_prach_sf_config_t *sf_config);

View File

@ -149,4 +149,9 @@ 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_send_tti(uint32_t I_sr,
uint32_t current_tti);
#endif

View File

@ -71,8 +71,9 @@ SRSLTE_API void srslte_vec_fprint_byte(FILE *stream, uint8_t *x, uint32_t len);
SRSLTE_API void srslte_vec_fprint_i(FILE *stream, int *x, uint32_t len);
SRSLTE_API void srslte_vec_fprint_hex(FILE *stream, uint8_t *x, uint32_t len);
/* Saves a vector to a file */
/* Saves/loads a vector to a file */
SRSLTE_API void srslte_vec_save_file(char *filename, void *buffer, uint32_t len);
SRSLTE_API void srslte_vec_load_file(char *filename, void *buffer, uint32_t len);
/* sum two vectors */
SRSLTE_API void srslte_vec_sum_ch(uint8_t *x, uint8_t *y, char *z, uint32_t len);

View File

@ -184,6 +184,30 @@ srslte_prach_sfn_t srslte_prach_get_sfn(uint32_t config_idx) {
}
}
/* Returns true if current_tti is a valid opportunity for PRACH transmission and the is an allowed subframe,
* or allowed_subframe == -1
*/
bool srslte_prach_send_tti(uint32_t config_idx, uint32_t current_tti, int allowed_subframe) {
// Get SFN and sf_idx from the PRACH configuration index
srslte_prach_sfn_t prach_sfn = srslte_prach_get_sfn(config_idx);
if ((prach_sfn == SRSLTE_PRACH_SFN_EVEN && ((current_tti/10)%2)==0) ||
prach_sfn == SRSLTE_PRACH_SFN_ANY)
{
srslte_prach_sf_config_t sf_config;
srslte_prach_sf_config(config_idx, &sf_config);
for (int i=0;i<sf_config.nof_sf;i++) {
if (((current_tti%10) == sf_config.sf[i] && allowed_subframe == -1) ||
((current_tti%10) == sf_config.sf[i] && (current_tti%10) == allowed_subframe))
{
return true;
}
}
}
return false;
}
void srslte_prach_sf_config(uint32_t config_idx, srslte_prach_sf_config_t *sf_config) {
memcpy(sf_config, &prach_sf_config[config_idx%16], sizeof(srslte_prach_sf_config_t));
}
@ -333,7 +357,7 @@ int srslte_prach_init(srslte_prach_t *p,
p->rsi = root_seq_index;
p->hs = high_speed_flag;
p->zczc = zero_corr_zone_config;
// Determine N_zc and N_cs
if(4 == preamble_format){
p->N_zc = 139;
@ -346,6 +370,8 @@ int srslte_prach_init(srslte_prach_t *p,
p->N_cs = prach_Ncs_unrestricted[p->zczc];
}
}
printf("Ncs=%d, zczc=%d, root_seq_index=%d, format=%d\n", p->N_cs, zero_corr_zone_config, root_seq_index, preamble_format);
// Set up containers
p->prach_bins = srslte_vec_malloc(sizeof(cf_t)*p->N_zc);
@ -476,7 +502,7 @@ int srslte_prach_detect(srslte_prach_t *p,
uint32_t N_rb_ul = prach_get_rb_ul(p->N_ifft_ul);
uint32_t k_0 = freq_offset*N_RB_SC - N_rb_ul*N_RB_SC/2 + p->N_ifft_ul/2;
uint32_t K = DELTA_F/DELTA_F_RA;
uint32_t begin = PHI + (K*k_0) + (K/2) + 1;
uint32_t begin = PHI + (K*k_0) + (K/2);
for(int i=0;i<p->N_zc;i++){
p->prach_bins[i] = signal[begin+i];

View File

@ -149,12 +149,12 @@ int main(int argc, char **argv) {
}
printf("Subframe len: %d samples\n", flen);
printf("Set TX/RX rate: %.2f MHz\n", cuhd_set_rx_srate(uhd, srslte_sampling_freq_hz(nof_prb)) / 1000000);
printf("Set TX/RX gain: %.1f dB\n", cuhd_set_rx_gain(uhd, uhd_gain));
printf("Set RX gain: %.1f dB\n", cuhd_set_rx_gain(uhd, uhd_gain));
printf("Set TX gain: %.1f dB\n", cuhd_set_tx_gain(uhd, uhd_gain));
printf("Set TX/RX freq: %.2f MHz\n", cuhd_set_rx_freq(uhd, uhd_freq) / 1000000);
cuhd_set_tx_srate(uhd, srslte_sampling_freq_hz(nof_prb));
cuhd_set_tx_gain(uhd, uhd_gain);
cuhd_set_tx_freq(uhd, uhd_freq);
cuhd_rx_wait_lo_locked(uhd);
cuhd_set_tx_freq_offset(uhd, uhd_freq, 8e6);
sleep(1);
cf_t *zeros = calloc(sizeof(cf_t),flen);
@ -167,8 +167,9 @@ int main(int argc, char **argv) {
cuhd_start_rx_stream(uhd);
uint32_t nframe=0;
while(nframe<nof_frames) {
printf("Rx subframe %d\n", nframe);
cuhd_recv_with_time(uhd, &buffer[flen*nframe], flen, true, &tstamp.full_secs, &tstamp.frac_secs);
nframe++;
if (nframe==9 || nframe==8) {
@ -177,11 +178,11 @@ int main(int argc, char **argv) {
cuhd_send_timed2(uhd, zeros, flen, tstamp.full_secs, tstamp.frac_secs, true, false);
printf("Transmitting zeros\n");
} else {
cuhd_send_timed2(uhd, preamble, flen, tstamp.full_secs, tstamp.frac_secs, false, true);
printf("Transmitting PRACH\n");
cuhd_send_timed2(uhd, preamble, flen, tstamp.full_secs, tstamp.frac_secs, true, true);
printf("Transmitting PRACH\n");
}
}
printf("Rx subframe %d\n", nframe);
}
if (f) {
fwrite(&buffer[10*flen], flen*sizeof(cf_t), 1, f);

View File

@ -374,6 +374,45 @@ int srslte_ue_ul_pusch_encode_cfg(srslte_ue_ul_t *q, srslte_pusch_cfg_t *cfg,
ret = SRSLTE_SUCCESS;
}
return ret;
}
return ret;
}
/* Returns 1 if a SR needs to be sent at current_tti given I_sr, as defined in Section 10.1 of 36.213 */
int srslte_ue_ul_sr_send_tti(uint32_t I_sr, uint32_t current_tti) {
uint32_t sr_periodicity;
uint32_t 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;
}
uint32_t sfn = current_tti/10;
uint32_t subf = current_tti%10;
if ((10*sfn+subf-sr_N_offset)%sr_periodicity==0) {
return 1;
} else {
return SRSLTE_SUCCESS;
}
}

View File

@ -331,6 +331,18 @@ void srslte_vec_save_file(char *filename, void *buffer, uint32_t len) {
}
}
void srslte_vec_load_file(char *filename, void *buffer, uint32_t len) {
FILE *f;
f = fopen(filename, "r");
if (f) {
fread(buffer, len, 1, f);
fclose(f);
} else {
perror("fopen");
}
}
void srslte_vec_conj_cc(cf_t *x, cf_t *y, uint32_t len) {
#ifndef HAVE_VOLK_CONJ_FUNCTION
int i;