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);
|
||||
|
||||
[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)))
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -77,7 +77,6 @@ namespace ue {
|
|||
PUCCH_N_PUCCH_2,
|
||||
PUCCH_N_PUCCH_SR,
|
||||
|
||||
SR_PUCCH_RESINDEX,
|
||||
SR_CONFIG_INDEX,
|
||||
|
||||
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 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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -509,6 +478,7 @@ void phy::run_rx_tx_state()
|
|||
break;
|
||||
case 1:
|
||||
is_sfn_synched = true;
|
||||
is_first_of_burst = true;
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
|
@ -518,27 +488,39 @@ 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
|
||||
bool tx_zeros = true;
|
||||
|
||||
// Advance transmission time for the next tti
|
||||
srslte_timestamp_add(&last_rx_time, 0, 1e-3);
|
||||
|
||||
// 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);
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
// 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
|
||||
|
|
|
@ -109,27 +109,13 @@ 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))
|
||||
{
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
@ -220,17 +220,19 @@ 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
|
||||
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;
|
||||
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) {
|
||||
|
@ -240,8 +242,9 @@ bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo
|
|||
|
||||
// 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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
@ -347,6 +371,8 @@ int srslte_prach_init(srslte_prach_t *p,
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
p->corr_spec = 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];
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
@ -169,6 +169,7 @@ int main(int argc, char **argv) {
|
|||
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);
|
||||
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);
|
||||
|
|
|
@ -375,5 +375,44 @@ int srslte_ue_ul_pusch_encode_cfg(srslte_ue_ul_t *q, srslte_pusch_cfg_t *cfg,
|
|||
}
|
||||
|
||||
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) {
|
||||
#ifndef HAVE_VOLK_CONJ_FUNCTION
|
||||
int i;
|
||||
|
|
Loading…
Reference in New Issue