mirror of https://github.com/PentHertz/srsLTE.git
Merge branch 'add_tx_zeros' into working_mac
Conflicts: srslte/lib/cuhd/src/cuhd_imp.cpp
This commit is contained in:
commit
e3dd3c3f88
|
@ -27,8 +27,8 @@ for n_rb=1:length(NULRB)
|
||||||
lib=srslte_prach(ueConfig,prachConfig);
|
lib=srslte_prach(ueConfig,prachConfig);
|
||||||
|
|
||||||
[mat, info]=ltePRACH(ueConfig,prachConfig);
|
[mat, info]=ltePRACH(ueConfig,prachConfig);
|
||||||
err=mean(abs(mat-lib));
|
err=max(abs(mat-lib));
|
||||||
if (err > 10^-3)
|
if (err > 2*10^-3)
|
||||||
disp(err)
|
disp(err)
|
||||||
a=1:100;
|
a=1:100;
|
||||||
plot(a,real(lib(a)),a,real(mat(a)))
|
plot(a,real(lib(a)),a,real(mat(a)))
|
||||||
|
|
|
@ -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);
|
puschConfig=struct('NTurboDecIts',5,'NLayers',1,'OrthCover','Off','PRBSet',22,'Modulation','16QAM','RV',0);
|
||||||
|
|
||||||
TBS=336;
|
TBS=336;
|
||||||
cfo=3400;
|
cfo=0;
|
||||||
t0=128;
|
t0=68;
|
||||||
x=[rx(t0:end); zeros(t0-1,1)];
|
x=[rx(t0:end); zeros(t0-1,1)];
|
||||||
|
|
||||||
subframe_rx=lteSCFDMADemodulate(ueConfig,x.*exp(-1i*2*pi*cfo/15000*transpose(1:length(x))/512));
|
subframe_rx=lteSCFDMADemodulate(ueConfig,x.*exp(-1i*2*pi*cfo/15000*transpose(1:length(x))/512));
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
ueConfig=struct('NCellID',1,'NULRB',25,'RNTI',77,'CyclicPrefixUL','Normal','NTxAnts',1,'Shortened',1);
|
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')
|
addpath('../../build/srslte/lib/phch/test')
|
||||||
|
|
||||||
|
@ -41,14 +41,17 @@ for i=1:length(TBs)
|
||||||
if (cqilen(c)>0 || TBs(i)>0)
|
if (cqilen(c)>0 || TBs(i)>0)
|
||||||
[cw, info]=lteULSCH(ueConfig,puschConfig,trblkin);
|
[cw, info]=lteULSCH(ueConfig,puschConfig,trblkin);
|
||||||
cw_mat=ltePUSCH(ueConfig,puschConfig,cw);
|
cw_mat=ltePUSCH(ueConfig,puschConfig,cw);
|
||||||
|
drs=ltePUSCHDRS(ueConfig,puschConfig);
|
||||||
idx=ltePUSCHIndices(ueConfig,puschConfig);
|
idx=ltePUSCHIndices(ueConfig,puschConfig);
|
||||||
|
drs_idx=ltePUSCHDRSIndices(ueConfig,puschConfig);
|
||||||
subframe_mat = lteULResourceGrid(ueConfig);
|
subframe_mat = lteULResourceGrid(ueConfig);
|
||||||
subframe_mat(idx)=cw_mat;
|
subframe_mat(idx)=cw_mat;
|
||||||
|
subframe_mat(drs_idx)=drs;
|
||||||
waveform = lteSCFDMAModulate(ueConfig,subframe_mat,0);
|
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);
|
[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));
|
err=mean(abs(waveform-waveform_lib));
|
||||||
if (err > 10^-3)
|
if (err > 10^-8)
|
||||||
disp(err)
|
disp(err)
|
||||||
error('Error!');
|
error('Error!');
|
||||||
end
|
end
|
||||||
|
|
|
@ -42,6 +42,7 @@ namespace srslte {
|
||||||
public:
|
public:
|
||||||
virtual void get_time(srslte_timestamp_t *now) = 0;
|
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(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_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;
|
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);
|
void get_time(srslte_timestamp_t *now);
|
||||||
bool tx(void *buffer, uint32_t nof_samples, srslte_timestamp_t tx_time);
|
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_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);
|
bool rx_at(void *buffer, uint32_t nof_samples, srslte_timestamp_t rx_time);
|
||||||
|
|
||||||
|
@ -72,6 +73,17 @@ namespace srslte {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void *uhd;
|
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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
#include "srslte/srslte.h"
|
#include "srslte/srslte.h"
|
||||||
#include "srsapps/radio/radio_uhd.h"
|
#include "srsapps/radio/radio_uhd.h"
|
||||||
|
|
||||||
|
|
||||||
namespace srslte {
|
namespace srslte {
|
||||||
|
|
||||||
bool radio_uhd::init()
|
bool radio_uhd::init()
|
||||||
|
@ -64,6 +63,11 @@ bool radio_uhd::init_agc(char *args)
|
||||||
}
|
}
|
||||||
cuhd_set_rx_gain(uhd, 40);
|
cuhd_set_rx_gain(uhd, 40);
|
||||||
cuhd_set_tx_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;
|
return true;
|
||||||
}
|
}
|
||||||
bool radio_uhd::rx_at(void* buffer, uint32_t nof_samples, srslte_timestamp_t rx_time)
|
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)
|
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;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
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)
|
void radio_uhd::set_rx_freq(float freq)
|
||||||
{
|
{
|
||||||
cuhd_set_rx_freq(uhd, 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)
|
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)
|
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)
|
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()
|
void radio_uhd::start_rx()
|
||||||
|
|
|
@ -239,7 +239,6 @@ bool mux::assemble_pdu(uint32_t pdu_sz_nbits) {
|
||||||
}
|
}
|
||||||
// MAC control element for PHR
|
// MAC control element for PHR
|
||||||
// TODO
|
// 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;
|
// data from any Logical Channel, except data from UL-CCCH;
|
||||||
// first only those with positive Bj
|
// 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
|
// If resources remain, allocate regardless of their Bj value
|
||||||
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
|
for (int i=0;i<mac_io::NOF_UL_LCH;i++) {
|
||||||
while (allocate_sdu(lchid_sorted[i], &pdu_msg));
|
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);
|
bool send_bsr = bsr_procedure->generate_bsr_on_ul_grant(pdu_msg.rem_size(), &bsr);
|
||||||
// Insert Padding BSR if not inserted Regular/Periodic BSR
|
// Insert Padding BSR if not inserted Regular/Periodic BSR
|
||||||
if (!bsr_payload_sz && send_bsr) {
|
if (!bsr_payload_sz && send_bsr) {
|
||||||
|
|
|
@ -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:
|
// 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);
|
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_pucch_resource_idx);
|
||||||
phy->set_param(srslte::ue::phy_params::SR_CONFIG_INDEX,
|
phy->set_param(srslte::ue::phy_params::SR_CONFIG_INDEX,
|
||||||
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_cnfg_idx);
|
msg->rr_cnfg.phy_cnfg_ded.sched_request_cnfg.sr_cnfg_idx);
|
||||||
|
|
|
@ -152,10 +152,7 @@ private:
|
||||||
bool do_agc;
|
bool do_agc;
|
||||||
double last_gain;
|
double last_gain;
|
||||||
|
|
||||||
uint32_t sr_N_offset;
|
|
||||||
uint32_t sr_periodicity;
|
|
||||||
bool sr_enabled;
|
bool sr_enabled;
|
||||||
uint32_t sr_n_pucch;
|
|
||||||
bool sr_is_ready_to_send(uint32_t tti);
|
bool sr_is_ready_to_send(uint32_t tti);
|
||||||
|
|
||||||
bool init_(radio *radio_handler, tti_sync *ttisync, log *log_h, bool do_agc);
|
bool init_(radio *radio_handler, tti_sync *ttisync, log *log_h, bool do_agc);
|
||||||
|
@ -167,6 +164,8 @@ private:
|
||||||
float old_gain;
|
float old_gain;
|
||||||
uint32_t sr_tx_tti;
|
uint32_t sr_tx_tti;
|
||||||
|
|
||||||
|
bool is_first_of_burst;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,6 @@ namespace ue {
|
||||||
PUCCH_N_PUCCH_2,
|
PUCCH_N_PUCCH_2,
|
||||||
PUCCH_N_PUCCH_SR,
|
PUCCH_N_PUCCH_SR,
|
||||||
|
|
||||||
SR_PUCCH_RESINDEX,
|
|
||||||
SR_CONFIG_INDEX,
|
SR_CONFIG_INDEX,
|
||||||
|
|
||||||
UCI_I_OFFSET_ACK,
|
UCI_I_OFFSET_ACK,
|
||||||
|
|
|
@ -61,7 +61,7 @@ namespace ue {
|
||||||
bool generate_data(ul_sched_grant *pusch_grant, srslte_softbuffer_tx_t *softbuffer, 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 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 uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission
|
||||||
|
static const bool normalize_amp = true;
|
||||||
private:
|
private:
|
||||||
log *log_h;
|
log *log_h;
|
||||||
phy_params *params_db;
|
phy_params *params_db;
|
||||||
|
|
|
@ -40,8 +40,12 @@ namespace ue {
|
||||||
class ul_sched_grant : public sched_grant {
|
class ul_sched_grant : public sched_grant {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ul_sched_grant(rnti_type_t type, uint16_t rnti) : sched_grant(type, rnti) {}
|
ul_sched_grant(rnti_type_t type, uint16_t rnti) : sched_grant(type, rnti) {
|
||||||
ul_sched_grant(uint16_t rnti) : sched_grant(rnti) {}
|
N_srs = 0;
|
||||||
|
}
|
||||||
|
ul_sched_grant(uint16_t rnti) : sched_grant(rnti) {
|
||||||
|
N_srs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t get_rv() {
|
uint32_t get_rv() {
|
||||||
return ul_dci.rv_idx;
|
return ul_dci.rv_idx;
|
||||||
|
@ -55,6 +59,13 @@ namespace ue {
|
||||||
void set_ndi(bool value) {
|
void set_ndi(bool value) {
|
||||||
ul_dci.ndi = value;
|
ul_dci.ndi = value;
|
||||||
}
|
}
|
||||||
|
void set_shortened(bool enabled) {
|
||||||
|
if (enabled) {
|
||||||
|
N_srs = 1;
|
||||||
|
} else {
|
||||||
|
N_srs = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
bool get_cqi_request() {
|
bool get_cqi_request() {
|
||||||
return ul_dci.cqi_request;
|
return ul_dci.cqi_request;
|
||||||
}
|
}
|
||||||
|
@ -85,7 +96,7 @@ namespace ue {
|
||||||
bool is_from_rar() {
|
bool is_from_rar() {
|
||||||
return grant_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;
|
grant_is_from_rar = false;
|
||||||
if (srslte_dci_msg_to_ul_grant(msg, cell, N_srs, n_rb_ho, &ul_dci, &grant)) {
|
if (srslte_dci_msg_to_ul_grant(msg, cell, N_srs, n_rb_ho, &ul_dci, &grant)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -120,6 +131,7 @@ namespace ue {
|
||||||
uint32_t current_tx_nb;
|
uint32_t current_tx_nb;
|
||||||
uint16_t rnti;
|
uint16_t rnti;
|
||||||
bool grant_is_from_rar;
|
bool grant_is_from_rar;
|
||||||
|
uint32_t N_srs;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
if (srslte_ue_dl_find_ul_dci(&ue_dl, &dci_msg, cfi, tti%10, grant->get_rnti()) != 1) {
|
||||||
return false;
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
dl_buffer_queue = new queue(6, sizeof(dl_buffer));
|
||||||
do_agc = do_agc_;
|
do_agc = do_agc_;
|
||||||
last_gain = 1e4;
|
last_gain = 1e4;
|
||||||
|
time_adv_sec = 0;
|
||||||
|
sr_tx_tti = 0;
|
||||||
|
|
||||||
// Set default params
|
// Set default params
|
||||||
params_db.set_param(phy_params::CELLSEARCH_TIMEOUT_PSS_NFRAMES, 100);
|
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) {
|
void phy::set_timeadv_rar(uint32_t ta_cmd) {
|
||||||
ta_cmd=7;
|
|
||||||
n_ta = srslte_N_ta_new_rar(ta_cmd);
|
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);
|
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) {
|
void phy::set_timeadv(uint32_t ta_cmd) {
|
||||||
n_ta = srslte_N_ta_new(n_ta, 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);
|
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);
|
params_db.set_param((uint32_t) param, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// FIXME: Add PRACH power control
|
// FIXME: Add PRACH power control
|
||||||
bool phy::send_prach(uint32_t preamble_idx) {
|
bool phy::send_prach(uint32_t preamble_idx) {
|
||||||
return send_prach(preamble_idx, -1, 0);
|
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) {
|
if (phy_state == RXTX) {
|
||||||
srslte_agc_lock(&ue_sync.agc, true);
|
srslte_agc_lock(&ue_sync.agc, true);
|
||||||
old_gain = radio_handler->get_tx_gain();
|
old_gain = radio_handler->get_tx_gain();
|
||||||
radio_handler->set_tx_gain(0);
|
radio_handler->set_tx_gain(10);
|
||||||
Info("Stopped AGC. Set TX gain to %.1f dB\n", 0);
|
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 prach_buffer.prepare_to_send(preamble_idx, allowed_subframe, target_power_dbm);
|
||||||
}
|
}
|
||||||
return false;
|
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)
|
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;
|
sr_enabled = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,10 +166,12 @@ int phy::sr_last_tx_tti() {
|
||||||
|
|
||||||
bool phy::sr_is_ready_to_send(uint32_t tti_) {
|
bool phy::sr_is_ready_to_send(uint32_t tti_) {
|
||||||
if (sr_enabled) {
|
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_enabled = false;
|
||||||
sr_tx_tti = tti_;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -508,7 +477,8 @@ void phy::run_rx_tx_state()
|
||||||
phy_state = IDLE;
|
phy_state = IDLE;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
is_sfn_synched = true;
|
is_sfn_synched = true;
|
||||||
|
is_first_of_burst = true;
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
|
@ -518,28 +488,40 @@ void phy::run_rx_tx_state()
|
||||||
log_h->step(current_tti);
|
log_h->step(current_tti);
|
||||||
float cfo = srslte_ue_sync_get_cfo(&ue_sync)/15000;
|
float cfo = srslte_ue_sync_get_cfo(&ue_sync)/15000;
|
||||||
|
|
||||||
// Prepare transmission for the next tti
|
bool tx_zeros = true;
|
||||||
srslte_timestamp_add(&last_rx_time, 0, 1e-3);
|
|
||||||
|
|
||||||
// send prach if we have to
|
// Advance transmission time for the next tti
|
||||||
if (prach_buffer.is_ready_to_send(current_tti)) {
|
srslte_timestamp_add(&last_rx_time, 0, 1e-3);
|
||||||
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);
|
|
||||||
}
|
|
||||||
// Generate scheduling request if we have to
|
// Generate scheduling request if we have to
|
||||||
if (sr_is_ready_to_send(current_tti+ul_buffer::tx_advance_sf)) {
|
if (sr_is_ready_to_send(current_tti+ul_buffer::tx_advance_sf)) {
|
||||||
get_ul_buffer_adv(current_tti)->generate_sr();
|
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()) {
|
// Every subframe, TX a PRACH or a PUSCH/PUCCH
|
||||||
// Generate PUCCH if no UL grant
|
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()) {
|
if (!get_ul_buffer_adv(current_tti)->is_released()) {
|
||||||
get_ul_buffer_adv(current_tti)->generate_data();
|
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
|
// Receive alligned buffer for the current tti
|
||||||
get_dl_buffer(current_tti)->recv_ue_sync(&ue_sync, &last_rx_time);
|
get_dl_buffer(current_tti)->recv_ue_sync(&ue_sync, &last_rx_time);
|
||||||
|
|
|
@ -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) {
|
if (initiated && preamble_idx >= 0 && preamble_idx < 64 && params_db != NULL) {
|
||||||
// consider the number of subframes the transmission must be anticipated
|
// consider the number of subframes the transmission must be anticipated
|
||||||
uint32_t current_tti = (current_tti_ + tx_advance_sf)%10240;
|
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);
|
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 (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_);
|
||||||
if (prach_sfn == SRSLTE_PRACH_SFN_EVEN && ((current_tti/10)%2)==0 ||
|
transmitted_tti = current_tti;
|
||||||
prach_sfn == SRSLTE_PRACH_SFN_ANY)
|
return true;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
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);
|
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",
|
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);
|
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)) {
|
if (!srslte_ue_ul_init(&ue_ul, cell)) {
|
||||||
srslte_ue_ul_set_normalization(&ue_ul, false);
|
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));
|
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);
|
srslte_ue_ul_set_cfo_enable(&ue_ul, false);
|
||||||
bzero(&uci_data, sizeof(srslte_uci_data_t));
|
bzero(&uci_data, sizeof(srslte_uci_data_t));
|
||||||
uci_pending = false;
|
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;
|
int nof_tx = 0;
|
||||||
|
|
||||||
bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time)
|
bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time)
|
||||||
{
|
{
|
||||||
|
// send packet next timeslot minus time advance
|
||||||
// send packet through usrp
|
|
||||||
srslte_timestamp_t tx_time;
|
srslte_timestamp_t tx_time;
|
||||||
srslte_timestamp_copy(&tx_time, &rx_time);
|
srslte_timestamp_copy(&tx_time, &rx_time);
|
||||||
srslte_timestamp_add(&tx_time, 0, tx_advance_sf*1e-3 - time_adv_sec);
|
srslte_timestamp_add(&tx_time, 0, tx_advance_sf*1e-3 - time_adv_sec);
|
||||||
|
|
||||||
// Correct CFO before transmission
|
// 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
|
// Compute peak
|
||||||
float max = 0;
|
float max = 0;
|
||||||
float *t = (float*) signal_buffer;
|
if (normalize_amp) {
|
||||||
for (int i=0;i<2*SRSLTE_SF_LEN_PRB(cell.nof_prb);i++) {
|
float *t = (float*) signal_buffer;
|
||||||
if (fabsf(t[i]) > max) {
|
for (int i=0;i<2*SRSLTE_SF_LEN_PRB(cell.nof_prb);i++) {
|
||||||
max = fabsf(t[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
|
Info("TX CFO: %f, len=%d, rx_time= %.6f tx_time = %.6f TA: %.1f PeakAmplitude=%.2f PKT#%d\n",
|
||||||
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",
|
|
||||||
cfo*15000, SRSLTE_SF_LEN_PRB(cell.nof_prb),
|
cfo*15000, SRSLTE_SF_LEN_PRB(cell.nof_prb),
|
||||||
srslte_timestamp_real(&rx_time),
|
srslte_timestamp_real(&rx_time),
|
||||||
srslte_timestamp_real(&tx_time), time_adv_sec*1000000, max, nof_tx);
|
srslte_timestamp_real(&tx_time), time_adv_sec*1000000, max, nof_tx);
|
||||||
|
|
|
@ -87,6 +87,9 @@ IF(UHD_FOUND)
|
||||||
add_executable(usrp_capture_sync usrp_capture_sync.c)
|
add_executable(usrp_capture_sync usrp_capture_sync.c)
|
||||||
target_link_libraries(usrp_capture_sync srslte srslte_uhd)
|
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.")
|
MESSAGE(STATUS " UHD examples will be installed.")
|
||||||
|
|
||||||
ELSE(UHD_FOUND)
|
ELSE(UHD_FOUND)
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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 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_API void srslte_prach_sf_config(uint32_t config_idx,
|
||||||
srslte_prach_sf_config_t *sf_config);
|
srslte_prach_sf_config_t *sf_config);
|
||||||
|
|
||||||
|
|
|
@ -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,
|
SRSLTE_API void srslte_ue_ul_set_rnti(srslte_ue_ul_t *q,
|
||||||
uint16_t rnti);
|
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
|
#endif
|
||||||
|
|
|
@ -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_i(FILE *stream, int *x, uint32_t len);
|
||||||
SRSLTE_API void srslte_vec_fprint_hex(FILE *stream, uint8_t *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_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 */
|
/* sum two vectors */
|
||||||
SRSLTE_API void srslte_vec_sum_ch(uint8_t *x, uint8_t *y, char *z, uint32_t len);
|
SRSLTE_API void srslte_vec_sum_ch(uint8_t *x, uint8_t *y, char *z, uint32_t len);
|
||||||
|
|
|
@ -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) {
|
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));
|
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->rsi = root_seq_index;
|
||||||
p->hs = high_speed_flag;
|
p->hs = high_speed_flag;
|
||||||
p->zczc = zero_corr_zone_config;
|
p->zczc = zero_corr_zone_config;
|
||||||
|
|
||||||
// Determine N_zc and N_cs
|
// Determine N_zc and N_cs
|
||||||
if(4 == preamble_format){
|
if(4 == preamble_format){
|
||||||
p->N_zc = 139;
|
p->N_zc = 139;
|
||||||
|
@ -346,6 +370,8 @@ int srslte_prach_init(srslte_prach_t *p,
|
||||||
p->N_cs = prach_Ncs_unrestricted[p->zczc];
|
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
|
// Set up containers
|
||||||
p->prach_bins = srslte_vec_malloc(sizeof(cf_t)*p->N_zc);
|
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 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_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 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++){
|
for(int i=0;i<p->N_zc;i++){
|
||||||
p->prach_bins[i] = signal[begin+i];
|
p->prach_bins[i] = signal[begin+i];
|
||||||
|
|
|
@ -149,12 +149,12 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
printf("Subframe len: %d samples\n", flen);
|
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 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);
|
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_srate(uhd, srslte_sampling_freq_hz(nof_prb));
|
||||||
cuhd_set_tx_gain(uhd, uhd_gain);
|
cuhd_set_tx_freq_offset(uhd, uhd_freq, 8e6);
|
||||||
cuhd_set_tx_freq(uhd, uhd_freq);
|
sleep(1);
|
||||||
cuhd_rx_wait_lo_locked(uhd);
|
|
||||||
|
|
||||||
cf_t *zeros = calloc(sizeof(cf_t),flen);
|
cf_t *zeros = calloc(sizeof(cf_t),flen);
|
||||||
|
|
||||||
|
@ -167,8 +167,9 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
cuhd_start_rx_stream(uhd);
|
cuhd_start_rx_stream(uhd);
|
||||||
uint32_t nframe=0;
|
uint32_t nframe=0;
|
||||||
|
|
||||||
while(nframe<nof_frames) {
|
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);
|
cuhd_recv_with_time(uhd, &buffer[flen*nframe], flen, true, &tstamp.full_secs, &tstamp.frac_secs);
|
||||||
nframe++;
|
nframe++;
|
||||||
if (nframe==9 || nframe==8) {
|
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);
|
cuhd_send_timed2(uhd, zeros, flen, tstamp.full_secs, tstamp.frac_secs, true, false);
|
||||||
printf("Transmitting zeros\n");
|
printf("Transmitting zeros\n");
|
||||||
} else {
|
} else {
|
||||||
cuhd_send_timed2(uhd, preamble, flen, tstamp.full_secs, tstamp.frac_secs, false, true);
|
cuhd_send_timed2(uhd, preamble, flen, tstamp.full_secs, tstamp.frac_secs, true, true);
|
||||||
printf("Transmitting PRACH\n");
|
printf("Transmitting PRACH\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("Rx subframe %d\n", nframe);
|
|
||||||
}
|
}
|
||||||
if (f) {
|
if (f) {
|
||||||
fwrite(&buffer[10*flen], flen*sizeof(cf_t), 1, f);
|
fwrite(&buffer[10*flen], flen*sizeof(cf_t), 1, f);
|
||||||
|
|
|
@ -374,6 +374,45 @@ int srslte_ue_ul_pusch_encode_cfg(srslte_ue_ul_t *q, srslte_pusch_cfg_t *cfg,
|
||||||
ret = SRSLTE_SUCCESS;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
void srslte_vec_conj_cc(cf_t *x, cf_t *y, uint32_t len) {
|
||||||
#ifndef HAVE_VOLK_CONJ_FUNCTION
|
#ifndef HAVE_VOLK_CONJ_FUNCTION
|
||||||
int i;
|
int i;
|
||||||
|
|
Loading…
Reference in New Issue