Merge branch 'mobility' into next

master
Ismael Gomez 7 years ago
commit d0fb17c088

@ -120,7 +120,7 @@ else(POLARSSL_FOUND)
endif(BUILD_STATIC)
add_definitions(-DHAVE_MBEDTLS)
else(MBEDTLS_FOUND)
message(FATAL_ERROR "Either polarssl or mbedtls is required to compile srsLTE")
message(FATAL_ERROR "Either PolarSSL or mbedTLS are required to build srsLTE")
endif (MBEDTLS_FOUND)
endif(POLARSSL_FOUND)

@ -241,15 +241,27 @@ int main(int argc, char **argv) {
srslte_rf_stop_rx_stream(&rf);
srslte_rf_flush_buffer(&rf);
if (srslte_ue_sync_init_multi(&ue_sync, cell, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
if (srslte_ue_sync_init_multi(&ue_sync, cell.nof_prb, cell.id==1000, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
fprintf(stderr, "Error initiating ue_sync\n");
return -1;
}
if (srslte_ue_dl_init(&ue_dl, cell, 1)) {
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n");
return -1;
}
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
return -1;
}
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
return -1;
}
if (srslte_ue_mib_init(&ue_mib, cell)) {
if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
return -1;
}
if (srslte_ue_mib_set_cell(&ue_mib, cell)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
return -1;
}
@ -264,7 +276,11 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error initiating FFT\n");
return -1;
}
if (srslte_chest_dl_init(&chest, cell)) {
if (srslte_chest_dl_init(&chest, cell.nof_prb)) {
fprintf(stderr, "Error initiating channel estimator\n");
return -1;
}
if (srslte_chest_dl_set_cell(&chest, cell)) {
fprintf(stderr, "Error initiating channel estimator\n");
return -1;
}

@ -188,6 +188,18 @@ int main(int argc, char **argv) {
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
signal(SIGINT, sig_int_handler);
if (srslte_ue_cellsearch_init_multi(&cs, cell_detect_config.max_frames_pss, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
fprintf(stderr, "Error initiating UE cell detect\n");
exit(-1);
}
if (cell_detect_config.max_frames_pss) {
srslte_ue_cellsearch_set_nof_valid_frames(&cs, cell_detect_config.nof_valid_pss_frames);
}
if (cell_detect_config.init_agc) {
srslte_ue_sync_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_wrapper, cell_detect_config.init_agc);
}
for (freq=0;freq<nof_freqs && !go_exit;freq++) {
/* set rf_freq */
@ -204,25 +216,12 @@ int main(int argc, char **argv) {
bzero(found_cells, 3*sizeof(srslte_ue_cellsearch_result_t));
if (srslte_ue_cellsearch_init_multi(&cs, cell_detect_config.max_frames_pss, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
fprintf(stderr, "Error initiating UE cell detect\n");
exit(-1);
}
if (cell_detect_config.max_frames_pss) {
srslte_ue_cellsearch_set_nof_valid_frames(&cs, cell_detect_config.nof_valid_pss_frames);
}
if (cell_detect_config.init_agc) {
srslte_ue_sync_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_wrapper, cell_detect_config.init_agc);
}
INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ/1000000);
srslte_rf_set_rx_srate(&rf, SRSLTE_CS_SAMP_FREQ);
INFO("Starting receiver...\n", 0);
srslte_rf_start_rx_stream(&rf);
n = srslte_ue_cellsearch_scan(&cs, found_cells, NULL);
srslte_ue_cellsearch_free(&cs);
if (n < 0) {
fprintf(stderr, "Error searching cell\n");
exit(-1);
@ -269,6 +268,7 @@ int main(int argc, char **argv) {
printf("\nBye\n");
srslte_ue_cellsearch_free(&cs);
srslte_rf_close(&rf);
exit(0);
}

@ -292,7 +292,11 @@ void base_init() {
exit(-1);
}
srslte_ofdm_set_normalize(&ifft, true);
if (srslte_pbch_init(&pbch, cell)) {
if (srslte_pbch_init(&pbch)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
if (srslte_pbch_set_cell(&pbch, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
@ -302,7 +306,11 @@ void base_init() {
exit(-1);
}
if (srslte_pcfich_init(&pcfich, &regs, cell)) {
if (srslte_pcfich_init(&pcfich, 1)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
if (srslte_pcfich_set_cell(&pcfich, &regs, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
@ -312,13 +320,20 @@ void base_init() {
exit(-1);
}
if (srslte_pdcch_init_tx(&pdcch, &regs, cell)) {
if (srslte_pdcch_init_enb(&pdcch, cell.nof_prb)) {
fprintf(stderr, "Error creating PDCCH object\n");
exit(-1);
}
if (srslte_pdcch_set_cell(&pdcch, &regs, cell)) {
fprintf(stderr, "Error creating PDCCH object\n");
exit(-1);
}
bzero(&pdsch, sizeof(srslte_pdsch_t));
if (srslte_pdsch_init_tx(&pdsch, cell)) {
if (srslte_pdsch_init_enb(&pdsch, cell.nof_prb)) {
fprintf(stderr, "Error creating PDSCH object\n");
exit(-1);
}
if (srslte_pdsch_set_cell(&pdsch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
exit(-1);
}
@ -660,7 +675,11 @@ int main(int argc, char **argv) {
srslte_sss_generate(sss_signal0, sss_signal5, cell.id);
/* Generate CRS signals */
if (srslte_chest_dl_init(&est, cell)) {
if (srslte_chest_dl_init(&est, cell.nof_prb)) {
fprintf(stderr, "Error initializing equalizer\n");
exit(-1);
}
if (srslte_chest_dl_set_cell(&est, cell)) {
fprintf(stderr, "Error initializing equalizer\n");
exit(-1);
}

@ -475,19 +475,38 @@ int main(int argc, char **argv) {
//ue_sync.decimate = prog_args.decimate;
}
}
if (srslte_ue_sync_init_multi_decim(&ue_sync, cell, srslte_rf_recv_wrapper, prog_args.rf_nof_rx_ant, (void*) &rf,decimate)) {
if (srslte_ue_sync_init_multi_decim(&ue_sync,
cell.nof_prb,
cell.id==1000,
srslte_rf_recv_wrapper,
prog_args.rf_nof_rx_ant,
(void*) &rf,decimate))
{
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
if (srslte_ue_sync_set_cell(&ue_sync, cell))
{
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
#endif
}
if (srslte_ue_mib_init(&ue_mib, cell)) {
if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1);
}
if (srslte_ue_mib_set_cell(&ue_mib, cell)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1);
}
if (srslte_ue_dl_init(&ue_dl, cell, prog_args.rf_nof_rx_ant)) { // This is the User RNTI
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, prog_args.rf_nof_rx_ant)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1);
}
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1);
}
@ -566,6 +585,10 @@ int main(int argc, char **argv) {
/* If a new line is detected set verbose level to Debug */
if (fgets(input, sizeof(input), stdin)) {
srslte_verbose = SRSLTE_VERBOSE_DEBUG;
ue_dl.pkt_errors = 0;
ue_dl.pkts_total = 0;
ue_dl.nof_detected = 0;
nof_trials = 0;
}
}
@ -760,10 +783,12 @@ int main(int argc, char **argv) {
if (sfn == 1024) {
sfn = 0;
PRINT_LINE_ADVANCE_CURSOR();
/*
ue_dl.pkt_errors = 0;
ue_dl.pkts_total = 0;
ue_dl.nof_detected = 0;
nof_trials = 0;
*/
}
}

@ -165,7 +165,11 @@ int main(int argc, char **argv) {
cell.nof_prb = nof_prb;
cell.nof_ports = 1;
if (srslte_ue_sync_init_multi(&ue_sync, cell, srslte_rf_recv_wrapper, nof_rx_antennas, (void*) &rf)) {
if (srslte_ue_sync_init_multi(&ue_sync, cell.nof_prb, cell.id==1000, srslte_rf_recv_wrapper, nof_rx_antennas, (void*) &rf)) {
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}

@ -30,6 +30,7 @@
#include <ctype.h>
#include <stdint.h>
#include <string>
#include <srslte/asn1/liblte_rrc.h>
namespace srslte {
@ -112,6 +113,12 @@ inline bool mnc_to_string(uint16_t mnc, std::string *str)
*str += (mnc & 0x000F) + '0';
return true;
}
inline std::string plmn_id_to_c_str(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
std::string mcc_str, mnc_str;
mnc_to_string(plmn_id.mnc, &mnc_str);
mcc_to_string(plmn_id.mcc, &mcc_str);
return mcc_str + mnc_str;
}
} // namespace srslte

@ -102,6 +102,15 @@ public:
virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0;
virtual uint32_t get_ul_count() = 0;
virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 0;
virtual void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) = 0;
};
// NAS interface for UE
class nas_interface_ue
{
public:
virtual void attach_request() = 0;
virtual void deattach_request() = 0;
};
// RRC interface for MAC
@ -123,6 +132,7 @@ class rrc_interface_phy
public:
virtual void in_sync() = 0;
virtual void out_of_sync() = 0;
virtual void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) = 0;
};
// RRC interface for NAS
@ -133,18 +143,11 @@ public:
virtual uint16_t get_mcc() = 0;
virtual uint16_t get_mnc() = 0;
virtual void enable_capabilities() = 0;
virtual void plmn_search() = 0;
virtual void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) = 0;
virtual std::string get_rb_name(uint32_t lcid) = 0;
};
// RRC interface for GW
class rrc_interface_gw
{
public:
virtual bool rrc_connected() = 0;
virtual void rrc_connect() = 0;
virtual bool have_drb() = 0;
};
// RRC interface for PDCP
class rrc_interface_pdcp
{
@ -444,8 +447,7 @@ class phy_interface_mac_common
{
public:
/* Start synchronization with strongest cell in the current carrier frequency */
virtual void sync_start() = 0;
virtual void sync_stop() = 0;
virtual bool sync_status() = 0;
/* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */
virtual void set_crnti(uint16_t rnti) = 0;
@ -514,8 +516,14 @@ public:
virtual void set_config_tdd(LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd) = 0;
virtual void set_config_64qam_en(bool enable) = 0;
/* Cell search and selection procedures */
virtual void cell_search_start() = 0;
virtual void cell_search_next() = 0;
virtual bool cell_select(uint32_t earfcn, srslte_cell_t cell) = 0;
virtual bool sync_stop() = 0;
/* Is the PHY downlink synchronized? */
virtual bool status_is_sync() = 0;
virtual bool sync_status() = 0;
/* Configure UL using parameters written with set_param() */
virtual void configure_ul_params(bool pregen_disabled = false) = 0;

@ -92,10 +92,13 @@ typedef struct {
SRSLTE_API int srslte_chest_dl_init(srslte_chest_dl_t *q,
srslte_cell_t cell);
uint32_t max_prb);
SRSLTE_API void srslte_chest_dl_free(srslte_chest_dl_t *q);
SRSLTE_API int srslte_chest_dl_set_cell(srslte_chest_dl_t *q,
srslte_cell_t cell);
SRSLTE_API void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q,
float *filter,
uint32_t filter_len);

@ -77,10 +77,14 @@ typedef struct {
SRSLTE_API int srslte_chest_ul_init(srslte_chest_ul_t *q,
srslte_cell_t cell);
uint32_t max_prb);
SRSLTE_API void srslte_chest_ul_free(srslte_chest_ul_t *q);
SRSLTE_API int srslte_chest_ul_set_cell(srslte_chest_ul_t *q,
srslte_cell_t cell);
SRSLTE_API void srslte_chest_ul_set_cfg(srslte_chest_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pucch_cfg_t *pucch_cfg,

@ -53,6 +53,9 @@ typedef struct SRSLTE_API {
SRSLTE_API int srslte_refsignal_cs_init(srslte_refsignal_cs_t *q,
uint32_t max_prb);
SRSLTE_API int srslte_refsignal_cs_set_cell(srslte_refsignal_cs_t * q,
srslte_cell_t cell);
SRSLTE_API void srslte_refsignal_cs_free(srslte_refsignal_cs_t *q);

@ -94,6 +94,9 @@ typedef struct {
} srslte_refsignal_srs_pregen_t;
SRSLTE_API int srslte_refsignal_ul_init(srslte_refsignal_ul_t *q,
uint32_t max_prb);
SRSLTE_API int srslte_refsignal_ul_set_cell(srslte_refsignal_ul_t *q,
srslte_cell_t cell);
SRSLTE_API void srslte_refsignal_ul_free(srslte_refsignal_ul_t *q);
@ -117,6 +120,10 @@ SRSLTE_API bool srslte_refsignal_dmrs_pusch_cfg_isvalid(srslte_refsignal_ul_t *q
srslte_refsignal_dmrs_pusch_cfg_t *cfg,
uint32_t nof_prb);
SRSLTE_API int srslte_refsignal_dmrs_pusch_pregen_init(srslte_refsignal_ul_t *q,
srslte_refsignal_ul_dmrs_pregen_t *pregen,
uint32_t max_prb);
SRSLTE_API int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q,
srslte_refsignal_ul_dmrs_pregen_t *pregen);

@ -44,7 +44,8 @@ typedef struct SRSLTE_API {
uint8_t *c_bytes;
float *c_float;
short *c_short;
uint32_t len;
uint32_t cur_len;
uint32_t max_len;
} srslte_sequence_t;
SRSLTE_API int srslte_sequence_init(srslte_sequence_t *q, uint32_t len);
@ -55,7 +56,8 @@ SRSLTE_API int srslte_sequence_LTE_pr(srslte_sequence_t *q,
uint32_t len,
uint32_t seed);
SRSLTE_API void srslte_sequence_set_LTE_pr(srslte_sequence_t *q,
SRSLTE_API int srslte_sequence_set_LTE_pr(srslte_sequence_t *q,
uint32_t len,
uint32_t seed);
SRSLTE_API int srslte_sequence_pbch(srslte_sequence_t *seq,

@ -58,6 +58,7 @@ typedef enum {
}srslte_dft_dir_t;
typedef struct SRSLTE_API {
int init_size; // DFT length used in the first initialization
int size; // DFT length
void *in; // Input buffer
void *out; // Output buffer
@ -88,6 +89,16 @@ SRSLTE_API int srslte_dft_plan_r(srslte_dft_plan_t *plan,
int dft_points,
srslte_dft_dir_t dir);
SRSLTE_API int srslte_dft_replan(srslte_dft_plan_t *plan,
const int new_dft_points);
SRSLTE_API int srslte_dft_replan_c(srslte_dft_plan_t *plan,
int new_dft_points);
SRSLTE_API int srslte_dft_replan_r(srslte_dft_plan_t *plan,
int new_dft_points);
SRSLTE_API void srslte_dft_plan_free(srslte_dft_plan_t *plan);
/* Set options */

@ -45,11 +45,17 @@ typedef struct SRSLTE_API {
uint32_t max_prb;
srslte_dft_plan_t dft_plan[SRSLTE_MAX_PRB+1];
srslte_dft_plan_t idft_plan[SRSLTE_MAX_PRB+1];
}srslte_dft_precoding_t;
SRSLTE_API int srslte_dft_precoding_init(srslte_dft_precoding_t *q,
uint32_t max_prb,
bool is_tx);
SRSLTE_API int srslte_dft_precoding_init_tx(srslte_dft_precoding_t *q,
uint32_t max_prb);
SRSLTE_API int srslte_dft_precoding_init_rx(srslte_dft_precoding_t *q,
uint32_t max_prb);
SRSLTE_API void srslte_dft_precoding_free(srslte_dft_precoding_t *q);
@ -62,10 +68,4 @@ SRSLTE_API int srslte_dft_precoding(srslte_dft_precoding_t *q,
uint32_t nof_prb,
uint32_t nof_symbols);
SRSLTE_API int srslte_dft_predecoding(srslte_dft_precoding_t *q,
cf_t *input,
cf_t *output,
uint32_t nof_prb,
uint32_t nof_symbols);
#endif

@ -47,6 +47,7 @@
/* This is common for both directions */
typedef struct SRSLTE_API{
srslte_dft_plan_t fft_plan;
uint32_t max_prb;
uint32_t nof_symbols;
uint32_t symbol_sz;
uint32_t nof_guards;
@ -56,17 +57,26 @@ typedef struct SRSLTE_API{
cf_t *tmp; // for removing zero padding
bool freq_shift;
float freq_shift_f;
cf_t *shift_buffer;
}srslte_ofdm_t;
SRSLTE_API int srslte_ofdm_init_(srslte_ofdm_t *q,
srslte_cp_t cp,
int symbol_sz,
int nof_prb,
int max_prb,
srslte_dft_dir_t dir);
SRSLTE_API int srslte_ofdm_rx_init(srslte_ofdm_t *q,
srslte_cp_t cp_type,
uint32_t max_prb);
SRSLTE_API int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q,
srslte_cp_t cp,
uint32_t nof_prb);
SRSLTE_API int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q,
srslte_cp_t cp,
uint32_t nof_prb);
SRSLTE_API void srslte_ofdm_rx_free(srslte_ofdm_t *q);

@ -108,10 +108,13 @@ typedef struct {
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_enb_dl_init(srslte_enb_dl_t *q,
srslte_cell_t cell);
uint32_t max_prb);
SRSLTE_API void srslte_enb_dl_free(srslte_enb_dl_t *q);
SRSLTE_API int srslte_enb_dl_set_cell(srslte_enb_dl_t *q,
srslte_cell_t cell);
SRSLTE_API void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q,
uint32_t cfi);
@ -154,9 +157,11 @@ SRSLTE_API int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q,
srslte_ra_dl_grant_t *grant,
srslte_softbuffer_tx_t *softbuffer[SRSLTE_MAX_CODEWORDS],
uint16_t rnti,
uint32_t rv_idx,
int rv_idx[SRSLTE_MAX_CODEWORDS],
uint32_t sf_idx,
uint8_t *data[SRSLTE_MAX_CODEWORDS]);
uint8_t *data[SRSLTE_MAX_CODEWORDS],
srslte_mimo_type_t mimo_type,
uint32_t pmi);
SRSLTE_API int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q,
srslte_ra_dl_dci_t *grant,

@ -101,14 +101,17 @@ typedef struct {
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_enb_ul_init(srslte_enb_ul_t *q,
uint32_t max_prb);
SRSLTE_API void srslte_enb_ul_free(srslte_enb_ul_t *q);
SRSLTE_API int srslte_enb_ul_set_cell(srslte_enb_ul_t *q,
srslte_cell_t cell,
srslte_prach_cfg_t* prach_cfg,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pusch_hopping_cfg_t *hopping_cfg,
srslte_pucch_cfg_t *pucch_cfg);
SRSLTE_API void srslte_enb_ul_free(srslte_enb_ul_t *q);
SRSLTE_API int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q,
uint16_t rnti);

@ -53,6 +53,8 @@
#define SRSLTE_BCH_PAYLOADCRC_LEN (SRSLTE_BCH_PAYLOAD_LEN+16)
#define SRSLTE_BCH_ENCODED_LEN 3*(SRSLTE_BCH_PAYLOADCRC_LEN)
#define SRSLTE_PBCH_MAX_RE 256 // make it avx2-aligned
/* PBCH object */
typedef struct SRSLTE_API {
srslte_cell_t cell;
@ -83,11 +85,13 @@ typedef struct SRSLTE_API {
} srslte_pbch_t;
SRSLTE_API int srslte_pbch_init(srslte_pbch_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_pbch_init(srslte_pbch_t *q);
SRSLTE_API void srslte_pbch_free(srslte_pbch_t *q);
SRSLTE_API int srslte_pbch_set_cell(srslte_pbch_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_pbch_decode(srslte_pbch_t *q,
cf_t *slot1_symbols,
cf_t *ce_slot1[SRSLTE_MAX_PORTS],

@ -79,13 +79,11 @@ typedef struct SRSLTE_API {
} srslte_pcfich_t;
SRSLTE_API int srslte_pcfich_init(srslte_pcfich_t *q,
srslte_regs_t *regs,
srslte_cell_t cell);
uint32_t nof_rx_antennas);
SRSLTE_API int srslte_pcfich_init_multi(srslte_pcfich_t *q,
SRSLTE_API int srslte_pcfich_set_cell(srslte_pcfich_t *q,
srslte_regs_t *regs,
srslte_cell_t cell,
uint32_t nof_rx_antennas);
srslte_cell_t cell);
SRSLTE_API void srslte_pcfich_free(srslte_pcfich_t *q);

@ -64,6 +64,7 @@ typedef struct SRSLTE_API {
uint32_t nof_cce;
uint32_t max_bits;
uint32_t nof_rx_antennas;
bool is_ue;
srslte_regs_t *regs;
@ -84,29 +85,16 @@ typedef struct SRSLTE_API {
} srslte_pdcch_t;
SRSLTE_API int srslte_pdcch_init(srslte_pdcch_t *q,
srslte_regs_t *regs,
srslte_cell_t cell);
SRSLTE_API int srslte_pdcch_init_tx(srslte_pdcch_t *q,
srslte_regs_t *regs,
srslte_cell_t cell);
SRSLTE_API int srslte_pdcch_init_rx(srslte_pdcch_t *q,
srslte_regs_t *regs,
srslte_cell_t cell,
SRSLTE_API int srslte_pdcch_init_ue(srslte_pdcch_t *q,
uint32_t max_prb,
uint32_t nof_rx_antennas);
SRSLTE_API int srslte_pdcch_init_multi(srslte_pdcch_t *q,
srslte_regs_t *regs,
srslte_cell_t cell,
uint32_t nof_rx_antennas);
SRSLTE_API int srslte_pdcch_init_enb(srslte_pdcch_t *q,
uint32_t max_prb);
SRSLTE_API int srslte_pdcch_init_txrx(srslte_pdcch_t *q,
SRSLTE_API int srslte_pdcch_set_cell(srslte_pdcch_t *q,
srslte_regs_t *regs,
srslte_cell_t cell,
uint32_t nof_rx_antennas,
bool isReceiver);
srslte_cell_t cell);
SRSLTE_API void srslte_pdcch_free(srslte_pdcch_t *q);

@ -49,6 +49,7 @@
typedef struct {
srslte_sequence_t seq[SRSLTE_MAX_CODEWORDS][SRSLTE_NSUBFRAMES_X_FRAME];
uint32_t cell_id;
bool sequence_generated;
} srslte_pdsch_user_t;
@ -60,6 +61,9 @@ typedef struct SRSLTE_API {
uint32_t max_re;
uint16_t ue_rnti;
bool is_ue;
/* buffers */
// void buffers are shared for tx and rx
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; /* Channel estimation (Rx only) */
@ -74,19 +78,25 @@ typedef struct SRSLTE_API {
// This is to generate the scrambling seq for multiple CRNTIs
srslte_pdsch_user_t **users;
srslte_sequence_t tmp_seq;
srslte_sch_t dl_sch;
} srslte_pdsch_t;
SRSLTE_API int srslte_pdsch_init_tx(srslte_pdsch_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_pdsch_init_rx(srslte_pdsch_t *q,
srslte_cell_t cell,
uint32_t nof_antennas);
SRSLTE_API int srslte_pdsch_init_ue(srslte_pdsch_t *q,
uint32_t max_prb,
uint32_t nof_rx_antennas);
SRSLTE_API int srslte_pdsch_init_enb(srslte_pdsch_t *q,
uint32_t max_prb);
SRSLTE_API void srslte_pdsch_free(srslte_pdsch_t *q);
SRSLTE_API int srslte_pdsch_set_cell(srslte_pdsch_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q,
uint16_t rnti);

@ -86,16 +86,14 @@ typedef struct SRSLTE_API {
} srslte_phich_t;
SRSLTE_API int srslte_phich_init(srslte_phich_t *q,
srslte_regs_t *regs,
srslte_cell_t cell);
SRSLTE_API int srslte_phich_init_multi(srslte_phich_t *q,
srslte_regs_t *regs,
srslte_cell_t cell,
uint32_t nof_rx_antennas);
SRSLTE_API void srslte_phich_free(srslte_phich_t *q);
SRSLTE_API int srslte_phich_set_cell(srslte_phich_t *q,
srslte_regs_t *regs,
srslte_cell_t cell);
SRSLTE_API void srslte_phich_calc(srslte_phich_t *q,
uint32_t n_prb_lowest,
uint32_t n_dmrs,

@ -44,6 +44,8 @@
#include "srslte/phy/common/phy_common.h"
#define SRSLTE_PRACH_MAX_LEN (2*24576+21024) // Maximum Tcp + Tseq
/** Generation and detection of RACH signals for uplink.
* Currently only supports preamble formats 0-3.
* Does not currently support high speed flag.
@ -60,6 +62,8 @@ typedef struct SRSLTE_API {
uint32_t N_ifft_ul; // IFFT size for uplink
uint32_t N_ifft_prach; // IFFT size for PRACH generation
uint32_t max_N_ifft_ul;
// Working parameters
uint32_t N_zc; // PRACH sequence length
uint32_t N_cs; // Cyclic shift size
@ -82,12 +86,12 @@ typedef struct SRSLTE_API {
float *corr;
// PRACH IFFT
srslte_dft_plan_t *fft;
srslte_dft_plan_t *ifft;
srslte_dft_plan_t fft;
srslte_dft_plan_t ifft;
// ZC-sequence FFT and IFFT
srslte_dft_plan_t *zc_fft;
srslte_dft_plan_t *zc_ifft;
srslte_dft_plan_t zc_fft;
srslte_dft_plan_t zc_ifft;
cf_t *signal_fft;
float detect_factor;
@ -129,6 +133,9 @@ SRSLTE_API void srslte_prach_sf_config(uint32_t config_idx,
srslte_prach_sf_config_t *sf_config);
SRSLTE_API int srslte_prach_init(srslte_prach_t *p,
uint32_t max_N_ifft_ul);
SRSLTE_API int srslte_prach_set_cell(srslte_prach_t *p,
uint32_t N_ifft_ul,
uint32_t config_idx,
uint32_t root_seq_index,

@ -45,7 +45,7 @@
#define SRSLTE_PUCCH_N_SEQ 12
#define SRSLTE_PUCCH2_NOF_BITS SRSLTE_UCI_CQI_CODED_PUCCH_B
#define SRSLTE_PUCCH_MAX_BITS SRSLTE_CQI_MAX_BITS
#define SRSLTE_PUCCH_MAX_SYMBOLS 120
#define SRSLTE_PUCCH_MAX_SYMBOLS 128
typedef enum SRSLTE_API {
SRSLTE_PUCCH_FORMAT_1 = 0,
@ -115,11 +115,13 @@ typedef struct SRSLTE_API {
}srslte_pucch_t;
SRSLTE_API int srslte_pucch_init(srslte_pucch_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_pucch_init(srslte_pucch_t *q);
SRSLTE_API void srslte_pucch_free(srslte_pucch_t *q);
SRSLTE_API int srslte_pucch_set_cell(srslte_pucch_t *q,
srslte_cell_t cell);
SRSLTE_API bool srslte_pucch_set_cfg(srslte_pucch_t* q,
srslte_pucch_cfg_t* cfg,
bool group_hopping_en);

@ -62,13 +62,16 @@ typedef struct {
typedef struct {
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
bool sequences_generated;
uint32_t cell_id;
bool sequence_generated;
} srslte_pusch_user_t;
/* PUSCH object */
typedef struct SRSLTE_API {
srslte_cell_t cell;
bool is_ue;
uint16_t ue_rnti;
uint32_t max_re;
srslte_dft_precoding_t dft_precoding;
@ -96,11 +99,17 @@ typedef struct SRSLTE_API {
}srslte_pusch_t;
SRSLTE_API int srslte_pusch_init(srslte_pusch_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_pusch_init_ue(srslte_pusch_t *q,
uint32_t max_prb);
SRSLTE_API int srslte_pusch_init_enb(srslte_pusch_t *q,
uint32_t max_prb);
SRSLTE_API void srslte_pusch_free(srslte_pusch_t *q);
SRSLTE_API int srslte_pusch_set_cell(srslte_pusch_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_pusch_cfg(srslte_pusch_t *q,
srslte_pusch_cfg_t *cfg,
srslte_ra_ul_grant_t *grant,
@ -114,7 +123,7 @@ SRSLTE_API int srslte_pusch_cfg(srslte_pusch_t *q,
SRSLTE_API int srslte_pusch_set_rnti(srslte_pusch_t *q,
uint16_t rnti);
SRSLTE_API void srslte_pusch_clear_rnti(srslte_pusch_t *q,
SRSLTE_API void srslte_pusch_free_rnti(srslte_pusch_t *q,
uint16_t rnti);
SRSLTE_API int srslte_pusch_encode(srslte_pusch_t *q,

@ -68,6 +68,7 @@ SRSLTE_API void srslte_interp_linear_f(float *input,
typedef struct {
cf_t *diff_vec;
uint32_t vector_len;
uint32_t max_vector_len;
} srslte_interp_linsrslte_vec_t;
SRSLTE_API int srslte_interp_linear_vector_init(srslte_interp_linsrslte_vec_t *q,
@ -75,6 +76,9 @@ SRSLTE_API int srslte_interp_linear_vector_init(srslte_interp_linsrslte_vec_t *q
SRSLTE_API void srslte_interp_linear_vector_free(srslte_interp_linsrslte_vec_t *q);
SRSLTE_API int srslte_interp_linear_vector_resize(srslte_interp_linsrslte_vec_t *q,
uint32_t vector_len);
SRSLTE_API void srslte_interp_linear_vector(srslte_interp_linsrslte_vec_t *q,
cf_t *in0,
cf_t *in1,
@ -108,6 +112,8 @@ typedef struct {
float *ramp;
uint32_t vector_len;
uint32_t M;
uint32_t max_vector_len;
uint32_t max_M;
} srslte_interp_lin_t;
SRSLTE_API int srslte_interp_linear_init(srslte_interp_lin_t *q,
@ -116,6 +122,10 @@ SRSLTE_API int srslte_interp_linear_init(srslte_interp_lin_t *q,
SRSLTE_API void srslte_interp_linear_free(srslte_interp_lin_t *q);
SRSLTE_API int srslte_interp_linear_resize(srslte_interp_lin_t *q,
uint32_t vector_len,
uint32_t M);
SRSLTE_API void srslte_interp_linear_offset(srslte_interp_lin_t *q,
cf_t *input,
cf_t *output,

@ -49,6 +49,7 @@ typedef struct SRSLTE_API {
float last_freq;
float tol;
int nsamples;
int max_samples;
srslte_cexptab_t tab;
cf_t *cur_cexp;
}srslte_cfo_t;
@ -58,7 +59,7 @@ SRSLTE_API int srslte_cfo_init(srslte_cfo_t *h,
SRSLTE_API void srslte_cfo_free(srslte_cfo_t *h);
SRSLTE_API int srslte_cfo_realloc(srslte_cfo_t *h,
SRSLTE_API int srslte_cfo_resize(srslte_cfo_t *h,
uint32_t samples);
SRSLTE_API void srslte_cfo_set_tol(srslte_cfo_t *h,

@ -35,6 +35,7 @@
typedef struct {
cf_t *corr;
uint32_t symbol_sz;
uint32_t max_symbol_sz;
} srslte_cp_synch_t;
SRSLTE_API int srslte_cp_synch_init(srslte_cp_synch_t *q,
@ -42,6 +43,9 @@ SRSLTE_API int srslte_cp_synch_init(srslte_cp_synch_t *q,
SRSLTE_API void srslte_cp_synch_free(srslte_cp_synch_t *q);
SRSLTE_API int srslte_cp_synch_resize(srslte_cp_synch_t *q,
uint32_t symbol_sz);
SRSLTE_API uint32_t srslte_cp_synch(srslte_cp_synch_t *q,
cf_t *input,
uint32_t max_offset,

@ -79,6 +79,10 @@ typedef struct SRSLTE_API {
#endif
int decimate;
uint32_t max_frame_size;
uint32_t max_fft_size;
uint32_t frame_size;
uint32_t N_id_2;
uint32_t fft_size;
@ -113,6 +117,10 @@ SRSLTE_API int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q,
int cfo_i,
int decimate);
SRSLTE_API int srslte_pss_synch_resize(srslte_pss_synch_t *q, uint32_t frame_size,
uint32_t fft_size,
int offset);
SRSLTE_API int srslte_pss_synch_init(srslte_pss_synch_t *q,
uint32_t frame_size);

@ -70,6 +70,7 @@ typedef struct SRSLTE_API {
srslte_dft_plan_t dftp_input;
uint32_t fft_size;
uint32_t max_fft_size;
float corr_peak_threshold;
uint32_t symbol_sz;
@ -89,7 +90,7 @@ typedef struct SRSLTE_API {
SRSLTE_API int srslte_sss_synch_init(srslte_sss_synch_t *q,
uint32_t fft_size);
SRSLTE_API int srslte_sss_synch_realloc(srslte_sss_synch_t *q,
SRSLTE_API int srslte_sss_synch_resize(srslte_sss_synch_t *q,
uint32_t fft_size);
SRSLTE_API void srslte_sss_synch_free(srslte_sss_synch_t *q);

@ -75,6 +75,8 @@ typedef struct SRSLTE_API {
uint32_t frame_size;
uint32_t max_offset;
bool enable_cfo_corr;
bool mean_cfo2_isunset;
bool mean_cfo_isunset;
float mean_cfo;
float mean_cfo2;
int cfo_i;
@ -85,6 +87,7 @@ typedef struct SRSLTE_API {
uint32_t cp_len;
srslte_cfo_t cfocorr;
srslte_cfo_t cfocorr2;
float current_cfo_tol;
sss_alg_t sss_alg;
bool detect_cp;
bool sss_en;
@ -97,6 +100,8 @@ typedef struct SRSLTE_API {
float M_ext_avg;
cf_t *temp;
uint32_t max_frame_size;
}srslte_sync_t;
typedef enum {
@ -121,6 +126,11 @@ SRSLTE_API int srslte_sync_init_decim(srslte_sync_t *q,
SRSLTE_API void srslte_sync_free(srslte_sync_t *q);
SRSLTE_API int srslte_sync_resize(srslte_sync_t *q,
uint32_t frame_size,
uint32_t max_offset,
uint32_t fft_size);
SRSLTE_API void srslte_sync_reset(srslte_sync_t *q);
/* Finds a correlation peak in the input signal around position find_offset */
@ -138,6 +148,9 @@ SRSLTE_API srslte_cp_t srslte_sync_detect_cp(srslte_sync_t *q,
SRSLTE_API void srslte_sync_set_threshold(srslte_sync_t *q,
float threshold);
SRSLTE_API void srslte_sync_set_cfo_tol(srslte_sync_t *q,
float tol);
/* Gets the subframe idx (0 or 5) */
SRSLTE_API uint32_t srslte_sync_get_sf_idx(srslte_sync_t *q);

@ -119,11 +119,14 @@ typedef struct SRSLTE_API {
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_dl_init(srslte_ue_dl_t *q,
srslte_cell_t cell,
uint32_t max_prb,
uint32_t nof_rx_antennas);
SRSLTE_API void srslte_ue_dl_free(srslte_ue_dl_t *q);
SRSLTE_API int srslte_ue_dl_set_cell(srslte_ue_dl_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q,
cf_t *input[SRSLTE_MAX_PORTS],
uint32_t sf_idx,

@ -79,10 +79,13 @@ typedef struct SRSLTE_API {
} srslte_ue_mib_t;
SRSLTE_API int srslte_ue_mib_init(srslte_ue_mib_t *q,
srslte_cell_t cell);
uint32_t max_prb);
SRSLTE_API void srslte_ue_mib_free(srslte_ue_mib_t *q);
SRSLTE_API int srslte_ue_mib_set_cell(srslte_ue_mib_t * q,
srslte_cell_t cell);
SRSLTE_API void srslte_ue_mib_reset(srslte_ue_mib_t * q);
SRSLTE_API int srslte_ue_mib_decode(srslte_ue_mib_t * q,
@ -104,21 +107,17 @@ typedef struct {
uint32_t nof_rx_antennas;
} srslte_ue_mib_sync_t;
SRSLTE_API int srslte_ue_mib_sync_init(srslte_ue_mib_sync_t *q,
uint32_t cell_id,
srslte_cp_t cp,
int (recv_callback)(void*, void*, uint32_t, srslte_timestamp_t *),
void *stream_handler);
SRSLTE_API int srslte_ue_mib_sync_init_multi(srslte_ue_mib_sync_t *q,
uint32_t cell_id,
srslte_cp_t cp,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t *),
uint32_t nof_rx_antennas,
void *stream_handler);
SRSLTE_API void srslte_ue_mib_sync_free(srslte_ue_mib_sync_t *q);
SRSLTE_API int srslte_ue_mib_sync_set_cell(srslte_ue_mib_sync_t *q,
uint32_t cell_id,
srslte_cp_t cp);
SRSLTE_API void srslte_ue_mib_sync_reset(srslte_ue_mib_sync_t * q);
SRSLTE_API int srslte_ue_mib_sync_decode(srslte_ue_mib_sync_t * q,

@ -70,6 +70,8 @@ typedef struct SRSLTE_API {
srslte_sync_t sfind;
srslte_sync_t strack;
uint32_t max_prb;
srslte_agc_t agc;
bool do_agc;
uint32_t agc_period;
@ -125,18 +127,21 @@ typedef struct SRSLTE_API {
} srslte_ue_sync_t;
SRSLTE_API int srslte_ue_sync_init(srslte_ue_sync_t *q,
srslte_cell_t cell,
uint32_t max_prb,
bool search_cell,
int (recv_callback)(void*, void*, uint32_t, srslte_timestamp_t*),
void *stream_handler);
SRSLTE_API int srslte_ue_sync_init_multi(srslte_ue_sync_t *q,
srslte_cell_t cell,
uint32_t max_prb,
bool search_cell,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*),
uint32_t nof_rx_antennas,
void *stream_handler);
SRSLTE_API int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
srslte_cell_t cell,
uint32_t max_prb,
bool search_cell,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*),
uint32_t nof_rx_antennas,
void *stream_handler,
@ -157,6 +162,9 @@ SRSLTE_API int srslte_ue_sync_init_file_multi(srslte_ue_sync_t *q,
SRSLTE_API void srslte_ue_sync_free(srslte_ue_sync_t *q);
SRSLTE_API int srslte_ue_sync_set_cell(srslte_ue_sync_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_ue_sync_start_agc(srslte_ue_sync_t *q,
double (set_gain_callback)(void*, double),
float init_gain_value);
@ -173,6 +181,9 @@ SRSLTE_API int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q,
SRSLTE_API int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q,
cf_t *input_buffer[SRSLTE_MAX_PORTS]);
SRSLTE_API void srslte_ue_sync_set_cfo_tol(srslte_ue_sync_t *q,
float tol);
SRSLTE_API void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q,
float cfo);

@ -76,6 +76,7 @@ typedef struct SRSLTE_API {
bool normalize_en;
bool cfo_en;
float current_cfo_tol;
float current_cfo;
srslte_pucch_format_t last_pucch_format;
@ -107,10 +108,16 @@ typedef struct SRSLTE_API {
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_ul_init(srslte_ue_ul_t *q,
srslte_cell_t cell);
uint32_t max_prb);
SRSLTE_API void srslte_ue_ul_free(srslte_ue_ul_t *q);
SRSLTE_API int srslte_ue_ul_set_cell(srslte_ue_ul_t *q,
srslte_cell_t cell);
SRSLTE_API void srslte_ue_ul_set_cfo_tol(srslte_ue_ul_t *q,
float tol);
SRSLTE_API void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q,
float cur_cfo);

@ -46,6 +46,8 @@ typedef struct SRSLTE_API {
uint32_t input_len;
uint32_t filter_len;
uint32_t output_len;
uint32_t max_input_len;
uint32_t max_filter_len;
srslte_dft_plan_t input_plan;
srslte_dft_plan_t filter_plan;
srslte_dft_plan_t output_plan;
@ -58,6 +60,9 @@ SRSLTE_API int srslte_conv_fft_cc_init(srslte_conv_fft_cc_t *q,
uint32_t input_len,
uint32_t filter_len);
SRSLTE_API int srslte_conv_fft_cc_replan(srslte_conv_fft_cc_t *q,
uint32_t input_len,
uint32_t filter_len);
SRSLTE_API void srslte_conv_fft_cc_free(srslte_conv_fft_cc_t *q);

@ -98,15 +98,16 @@ namespace srslte {
void set_tx_rx_gain_offset(float offset);
double set_rx_gain_th(float gain);
void set_tx_freq(float freq);
void set_rx_freq(float freq);
void set_freq_offset(double freq);
void set_tx_freq(double freq);
void set_rx_freq(double freq);
float get_tx_freq();
float get_rx_freq();
double get_tx_freq();
double get_rx_freq();
void set_master_clock_rate(float rate);
void set_tx_srate(float srate);
void set_rx_srate(float srate);
void set_master_clock_rate(double rate);
void set_tx_srate(double srate);
void set_rx_srate(double srate);
float get_tx_gain();
float get_rx_gain();
@ -158,7 +159,7 @@ namespace srslte {
const static double blade_default_tx_adv_samples = 27;
const static double blade_default_tx_adv_offset_sec = 1e-6;
float tx_freq, rx_freq;
double tx_freq, rx_freq, freq_offset;
trace<uint32_t> tr_local_time;
trace<uint32_t> tr_usrp_time;

@ -46,7 +46,7 @@ class gw
{
public:
gw();
void init(srsue::pdcp_interface_gw *pdcp_, srsue::rrc_interface_gw *rrc_, srsue::ue_interface *ue_, log *gw_log_, uint32_t lcid_);
void init(srsue::pdcp_interface_gw *pdcp_, srsue::ue_interface *ue_, log *gw_log_, uint32_t lcid_);
void stop();
void get_metrics(gw_metrics_t &m);
@ -62,7 +62,6 @@ private:
static const int GW_THREAD_PRIO = 7;
srsue::pdcp_interface_gw *pdcp;
srsue::rrc_interface_gw *rrc;
srsue::ue_interface *ue;
byte_buffer_pool *pool;
@ -75,6 +74,8 @@ private:
bool if_up;
uint32_t lcid;
uint32_t current_ip_addr;
long ul_tput_bytes;
long dl_tput_bytes;
struct timeval metrics_time[3];

@ -32,6 +32,8 @@
#include <string.h>
#include <complex.h>
#include <math.h>
#include <srslte/phy/common/phy_common.h>
#include <srslte/srslte.h>
#include "srslte/config.h"
@ -72,63 +74,56 @@ static void set_default_filter(srslte_chest_dl_t *q, int filter_len) {
*
* This object depends on the srslte_refsignal_t object for creating the LTE CSR signal.
*/
int srslte_chest_dl_init(srslte_chest_dl_t *q, srslte_cell_t cell)
int srslte_chest_dl_init(srslte_chest_dl_t *q, uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
if (q != NULL)
{
bzero(q, sizeof(srslte_chest_dl_t));
ret = srslte_refsignal_cs_init(&q->csr_signal, cell);
ret = srslte_refsignal_cs_init(&q->csr_signal, max_prb);
if (ret != SRSLTE_SUCCESS) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
goto clean_exit;
}
q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(max_prb));
if (!q->tmp_noise) {
perror("malloc");
goto clean_exit;
}
q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(max_prb));
if (!q->pilot_estimates) {
perror("malloc");
goto clean_exit;
}
q->pilot_estimates_average = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
q->pilot_estimates_average = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(max_prb));
if (!q->pilot_estimates_average) {
perror("malloc");
goto clean_exit;
}
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(max_prb));
if (!q->pilot_recv_signal) {
perror("malloc");
goto clean_exit;
}
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, SRSLTE_NRE*cell.nof_prb)) {
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, SRSLTE_NRE*max_prb)) {
fprintf(stderr, "Error initializing vector interpolator\n");
goto clean_exit;
}
if (srslte_interp_linear_init(&q->srslte_interp_lin, 2*cell.nof_prb, SRSLTE_NRE/2)) {
if (srslte_interp_linear_init(&q->srslte_interp_lin, 2*max_prb, SRSLTE_NRE/2)) {
fprintf(stderr, "Error initializing interpolator\n");
goto clean_exit;
}
if (srslte_pss_generate(q->pss_signal, cell.id%3)) {
fprintf(stderr, "Error initializing PSS signal for noise estimation\n");
goto clean_exit;
}
q->noise_alg = SRSLTE_NOISE_ALG_REFS;
q->smooth_filter_len = 3;
srslte_chest_dl_set_smooth_filter3_coeff(q, 0.1);
q->cell = cell;
}
ret = SRSLTE_SUCCESS;
@ -162,10 +157,45 @@ void srslte_chest_dl_free(srslte_chest_dl_t *q)
bzero(q, sizeof(srslte_chest_dl_t));
}
int srslte_chest_dl_set_cell(srslte_chest_dl_t *q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
ret = srslte_refsignal_cs_set_cell(&q->csr_signal, cell);
if (ret != SRSLTE_SUCCESS) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
return SRSLTE_ERROR;
}
if (srslte_pss_generate(q->pss_signal, cell.id%3)) {
fprintf(stderr, "Error initializing PSS signal for noise estimation\n");
return SRSLTE_ERROR;
}
if (srslte_interp_linear_vector_resize(&q->srslte_interp_linvec, SRSLTE_NRE*q->cell.nof_prb)) {
fprintf(stderr, "Error initializing vector interpolator\n");
return SRSLTE_ERROR;
}
if (srslte_interp_linear_resize(&q->srslte_interp_lin, 2*q->cell.nof_prb, SRSLTE_NRE/2)) {
fprintf(stderr, "Error initializing interpolator\n");
return SRSLTE_ERROR;
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
/* Uses the difference between the averaged and non-averaged pilot estimates */
static float estimate_noise_pilots(srslte_chest_dl_t *q, uint32_t port_id)
{
int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id);
/* Substract noisy pilot estimates */
srslte_vec_sub_ccc(q->pilot_estimates_average, q->pilot_estimates, q->tmp_noise, nref);
@ -319,6 +349,7 @@ int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, u
/* Use the known CSR signal to compute Least-squares estimates */
srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_signal.pilots[port_id/2][sf_idx],
q->pilot_estimates, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
if (ce != NULL) {
/* Smooth estimates (if applicable) and interpolate */

@ -32,6 +32,8 @@
#include <string.h>
#include <complex.h>
#include <math.h>
#include <srslte/srslte.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/config.h"
@ -43,6 +45,9 @@
#define NOF_REFS_SYM (q->cell.nof_prb*SRSLTE_NRE)
#define NOF_REFS_SF (NOF_REFS_SYM*2) // 2 reference symbols per subframe
#define MAX_REFS_SYM (max_prb*SRSLTE_NRE)
#define MAX_REFS_SF (max_prb*SRSLTE_NRE*2) // 2 reference symbols per subframe
/** 3GPP LTE Downlink channel estimator and equalizer.
* Estimates the channel in the resource elements transmitting references and interpolates for the rest
* of the resource grid.
@ -52,52 +57,49 @@
* This object depends on the srslte_refsignal_t object for creating the LTE CSR signal.
*/
int srslte_chest_ul_init(srslte_chest_ul_t *q, srslte_cell_t cell)
int srslte_chest_ul_init(srslte_chest_ul_t *q, uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
if (q != NULL)
{
bzero(q, sizeof(srslte_chest_ul_t));
q->cell = cell;
ret = srslte_refsignal_ul_init(&q->dmrs_signal, cell);
ret = srslte_refsignal_ul_init(&q->dmrs_signal, max_prb);
if (ret != SRSLTE_SUCCESS) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
goto clean_exit;
}
q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * NOF_REFS_SF);
q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * MAX_REFS_SF);
if (!q->tmp_noise) {
perror("malloc");
goto clean_exit;
}
q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * NOF_REFS_SF);
q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * MAX_REFS_SF);
if (!q->pilot_estimates) {
perror("malloc");
goto clean_exit;
}
for (int i=0;i<4;i++) {
q->pilot_estimates_tmp[i] = srslte_vec_malloc(sizeof(cf_t) * NOF_REFS_SF);
q->pilot_estimates_tmp[i] = srslte_vec_malloc(sizeof(cf_t) * MAX_REFS_SF);
if (!q->pilot_estimates_tmp[i]) {
perror("malloc");
goto clean_exit;
}
}
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * (NOF_REFS_SF+1));
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * (MAX_REFS_SF+1));
if (!q->pilot_recv_signal) {
perror("malloc");
goto clean_exit;
}
q->pilot_known_signal = srslte_vec_malloc(sizeof(cf_t) * (NOF_REFS_SF+1));
q->pilot_known_signal = srslte_vec_malloc(sizeof(cf_t) * (MAX_REFS_SF+1));
if (!q->pilot_known_signal) {
perror("malloc");
goto clean_exit;
}
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, NOF_REFS_SYM)) {
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, MAX_REFS_SYM)) {
fprintf(stderr, "Error initializing vector interpolator\n");
goto clean_exit;
}
@ -107,6 +109,11 @@ int srslte_chest_ul_init(srslte_chest_ul_t *q, srslte_cell_t cell)
q->dmrs_signal_configured = false;
if (srslte_refsignal_dmrs_pusch_pregen_init(&q->dmrs_signal, &q->dmrs_pregen, max_prb)) {
fprintf(stderr, "Error allocating memory for pregenerated signals\n");
goto clean_exit;
}
}
ret = SRSLTE_SUCCESS;
@ -120,9 +127,8 @@ clean_exit:
void srslte_chest_ul_free(srslte_chest_ul_t *q)
{
if (q->dmrs_signal_configured) {
srslte_refsignal_dmrs_pusch_pregen_free(&q->dmrs_signal, &q->dmrs_pregen);
}
srslte_refsignal_ul_free(&q->dmrs_signal);
if (q->tmp_noise) {
free(q->tmp_noise);
@ -146,6 +152,30 @@ void srslte_chest_ul_free(srslte_chest_ul_t *q)
bzero(q, sizeof(srslte_chest_ul_t));
}
int srslte_chest_ul_set_cell(srslte_chest_ul_t *q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
ret = srslte_refsignal_ul_set_cell(&q->dmrs_signal, cell);
if (ret != SRSLTE_SUCCESS) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
return SRSLTE_ERROR;
}
if (srslte_interp_linear_vector_resize(&q->srslte_interp_linvec, NOF_REFS_SYM)) {
fprintf(stderr, "Error initializing vector interpolator\n");
return SRSLTE_ERROR;
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
void srslte_chest_ul_set_cfg(srslte_chest_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pucch_cfg_t *pucch_cfg,

@ -99,10 +99,39 @@ inline uint32_t srslte_refsignal_cs_nsymbol(uint32_t l, srslte_cp_t cp, uint32_t
}
/** Allocates memory for the 20 slots in a subframe
*/
int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL)
{
ret = SRSLTE_ERROR;
for (int p=0;p<2;p++) {
for (int i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
q->pilots[p][i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(max_prb, 2*p));
if (!q->pilots[p][i]) {
perror("malloc");
goto free_and_exit;
}
}
}
ret = SRSLTE_SUCCESS;
}
free_and_exit:
if (ret == SRSLTE_ERROR) {
srslte_refsignal_cs_free(q);
}
return ret;
}
/** Allocates and precomputes the Cell-Specific Reference (CSR) signal for
* the 20 slots in a subframe
*/
int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell)
int srslte_refsignal_cs_set_cell(srslte_refsignal_cs_t * q, srslte_cell_t cell)
{
uint32_t c_init;
@ -114,12 +143,12 @@ int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell)
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
ret = SRSLTE_ERROR;
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
bzero(q, sizeof(srslte_refsignal_cs_t));
bzero(&seq, sizeof(srslte_sequence_t));
if (srslte_sequence_init(&seq, 2*2*SRSLTE_MAX_PRB)) {
goto free_and_exit;
return SRSLTE_ERROR;
}
if (SRSLTE_CP_ISNORM(cell.cp)) {
@ -128,18 +157,6 @@ int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell)
N_cp = 0;
}
q->cell = cell;
for (p=0;p<2;p++) {
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
q->pilots[p][i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, 2*p));
if (!q->pilots[p][i]) {
perror("malloc");
goto free_and_exit;
}
}
}
for (ns=0;ns<SRSLTE_NSLOTS_X_FRAME;ns++) {
for (p=0;p<2;p++) {
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(2*p)/2;
@ -150,7 +167,7 @@ int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell)
+ 2 * cell.id + N_cp;
/* generate sequence for this symbol and slot */
srslte_sequence_set_LTE_pr(&seq, c_init);
srslte_sequence_set_LTE_pr(&seq, 2*2*SRSLTE_MAX_PRB, c_init);
/* Compute signal */
for (i = 0; i < 2*q->cell.nof_prb; i++) {
@ -161,16 +178,11 @@ int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell)
_Complex_I * (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2);
}
}
}
}
srslte_sequence_free(&seq);
ret = SRSLTE_SUCCESS;
}
free_and_exit:
if (ret == SRSLTE_ERROR) {
srslte_sequence_free(&seq);
srslte_refsignal_cs_free(q);
ret = SRSLTE_SUCCESS;
}
return ret;
}
@ -178,10 +190,8 @@ free_and_exit:
/** Deallocates a srslte_refsignal_cs_t object allocated with srslte_refsignal_cs_init */
void srslte_refsignal_cs_free(srslte_refsignal_cs_t * q)
{
int i, p;
for (p=0;p<2;p++) {
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
for (int p=0;p<2;p++) {
for (int i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
if (q->pilots[p][i]) {
free(q->pilots[p][i]);
}

@ -29,6 +29,7 @@
#include <strings.h>
#include <stdlib.h>
#include <complex.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/ch_estimation/refsignal_ul.h"
@ -138,8 +139,8 @@ static int generate_n_prs(srslte_refsignal_ul_t * q) {
}
q->n_prs_pusch[delta_ss][ns] = n_prs;
}
srslte_sequence_free(&seq);
}
srslte_sequence_free(&seq);
return SRSLTE_SUCCESS;
}
@ -160,9 +161,9 @@ static int generate_srslte_sequence_hopping_v(srslte_refsignal_ul_t *q) {
return SRSLTE_ERROR;
}
q->v_pusch[ns][delta_ss] = seq.c[ns];
srslte_sequence_free(&seq);
}
}
srslte_sequence_free(&seq);
return SRSLTE_SUCCESS;
}
@ -170,62 +171,79 @@ static int generate_srslte_sequence_hopping_v(srslte_refsignal_ul_t *q) {
/** Initializes srslte_refsignal_ul_t object according to 3GPP 36.211 5.5
*
*/
int srslte_refsignal_ul_init(srslte_refsignal_ul_t * q, srslte_cell_t cell)
int srslte_refsignal_ul_init(srslte_refsignal_ul_t * q, uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell)) {
if (q != NULL) {
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_refsignal_ul_t));
q->cell = cell;
// Allocate temporal buffer for computing signal argument
q->tmp_arg = srslte_vec_malloc(SRSLTE_NRE * q->cell.nof_prb * sizeof(cf_t));
q->tmp_arg = srslte_vec_malloc(SRSLTE_NRE * max_prb * sizeof(cf_t));
if (!q->tmp_arg) {
perror("malloc");
goto free_and_exit;
}
ret = SRSLTE_SUCCESS;
}
free_and_exit:
if (ret == SRSLTE_ERROR) {
srslte_refsignal_ul_free(q);
}
return ret;
}
void srslte_refsignal_ul_free(srslte_refsignal_ul_t * q) {
if (q->tmp_arg) {
free(q->tmp_arg);
}
bzero(q, sizeof(srslte_refsignal_ul_t));
}
/** Initializes srslte_refsignal_ul_t object according to 3GPP 36.211 5.5
*
*/
int srslte_refsignal_ul_set_cell(srslte_refsignal_ul_t * q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell)) {
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
srslte_pucch_cfg_default(&q->pucch_cfg);
// Precompute n_prs
if (generate_n_prs(q)) {
goto free_and_exit;
return SRSLTE_ERROR;
}
// Precompute group hopping values u.
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
goto free_and_exit;
return SRSLTE_ERROR;
}
// Precompute sequence hopping values v. Uses f_ss_pusch
if (generate_srslte_sequence_hopping_v(q)) {
goto free_and_exit;
return SRSLTE_ERROR;
}
if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) {
goto free_and_exit;
return SRSLTE_ERROR;
}
ret = SRSLTE_SUCCESS;
}
free_and_exit:
if (ret == SRSLTE_ERROR) {
srslte_refsignal_ul_free(q);
ret = SRSLTE_SUCCESS;
}
return ret;
}
void srslte_refsignal_ul_free(srslte_refsignal_ul_t * q) {
if (q->tmp_arg) {
free(q->tmp_arg);
}
bzero(q, sizeof(srslte_refsignal_ul_t));
}
void srslte_refsignal_ul_set_cfg(srslte_refsignal_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pucch_cfg_t *pucch_cfg,
@ -363,15 +381,38 @@ void compute_r(srslte_refsignal_ul_t *q, uint32_t nof_prb, uint32_t ns, uint32_t
}
int srslte_refsignal_dmrs_pusch_pregen_init(srslte_refsignal_ul_t *q, srslte_refsignal_ul_dmrs_pregen_t *pregen,
uint32_t max_prb)
{
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
for (uint32_t cs=0;cs<SRSLTE_NOF_CSHIFT;cs++) {
pregen->r[cs][sf_idx] = (cf_t**) calloc(sizeof(cf_t*), max_prb + 1);
if (pregen->r[cs][sf_idx]) {
for (uint32_t n=0;n<=max_prb;n++) {
if (srslte_dft_precoding_valid_prb(n)) {
pregen->r[cs][sf_idx][n] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*n*2*SRSLTE_NRE);
if (pregen->r[cs][sf_idx][n]) {
} else {
return SRSLTE_ERROR;
}
}
}
} else {
return SRSLTE_ERROR;
}
}
}
return SRSLTE_SUCCESS;
}
int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q, srslte_refsignal_ul_dmrs_pregen_t *pregen)
{
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
for (uint32_t cs=0;cs<SRSLTE_NOF_CSHIFT;cs++) {
pregen->r[cs][sf_idx] = (cf_t**) calloc(sizeof(cf_t*), q->cell.nof_prb + 1);
if (pregen->r[cs][sf_idx]) {
for (uint32_t n=0;n<=q->cell.nof_prb;n++) {
if (srslte_dft_precoding_valid_prb(n)) {
pregen->r[cs][sf_idx][n] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*n*2*SRSLTE_NRE);
if (pregen->r[cs][sf_idx][n]) {
if (srslte_refsignal_dmrs_pusch_gen(q, n, sf_idx, cs, pregen->r[cs][sf_idx][n])) {
return SRSLTE_ERROR;

@ -29,6 +29,7 @@
#include <strings.h>
#include <unistd.h>
#include <complex.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/srslte.h"
@ -128,10 +129,13 @@ int main(int argc, char **argv) {
cid = cell.id;
max_cid = cell.id;
}
if (srslte_chest_dl_init(&est, cell.nof_prb)) {
fprintf(stderr, "Error initializing equalizer\n");
goto do_exit;
}
while(cid <= max_cid) {
cell.id = cid;
if (srslte_chest_dl_init(&est, cell)) {
if (srslte_chest_dl_set_cell(&est, cell)) {
fprintf(stderr, "Error initializing equalizer\n");
goto do_exit;
}
@ -214,10 +218,10 @@ int main(int argc, char **argv) {
}
}
}
srslte_chest_dl_free(&est);
cid+=10;
INFO("cid=%d\n", cid);
}
srslte_chest_dl_free(&est);
ret = 0;

@ -125,9 +125,13 @@ int main(int argc, char **argv) {
max_cid = cell.id;
}
printf("max_cid=%d, cid=%d, cell.id=%d\n", max_cid, cid, cell.id);
if (srslte_chest_ul_init(&est, cell.nof_prb)) {
fprintf(stderr, "Error initializing equalizer\n");
goto do_exit;
}
while(cid <= max_cid) {
cell.id = cid;
if (srslte_chest_ul_init(&est, cell)) {
if (srslte_chest_ul_set_cell(&est, cell)) {
fprintf(stderr, "Error initializing equalizer\n");
goto do_exit;
}
@ -213,9 +217,9 @@ int main(int argc, char **argv) {
}
cid+=10;
printf("cid=%d\n", cid);
srslte_chest_ul_free(&est);
}
srslte_chest_ul_free(&est);
if (fmatlab) {
fprintf(fmatlab, "input=");

@ -81,7 +81,12 @@ int main(int argc, char **argv) {
parse_args(argc,argv);
if (srslte_refsignal_ul_init(&refs, cell)) {
if (srslte_refsignal_ul_init(&refs, cell.nof_prb)) {
fprintf(stderr, "Error initializing UL reference signal\n");
goto do_exit;
}
if (srslte_refsignal_ul_set_cell(&refs, cell)) {
fprintf(stderr, "Error initializing UL reference signal\n");
goto do_exit;
}

@ -235,7 +235,7 @@ int srslte_symbol_sz_power2(uint32_t nof_prb) {
return 1024;
} else if (nof_prb<=75) {
return 1536;
} else if (nof_prb<=100) {
} else if (nof_prb<=110) {
return 2048;
} else {
return -1;
@ -257,7 +257,7 @@ int srslte_symbol_sz(uint32_t nof_prb) {
return 768;
} else if (nof_prb<=75) {
return 1024;
} else if (nof_prb<=100) {
} else if (nof_prb<=110) {
return 1536;
} else {
return SRSLTE_ERROR;

@ -27,7 +27,8 @@
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <assert.h>
#include <pthread.h>
#include <srslte/phy/common/sequence.h>
#include "srslte/phy/common/sequence.h"
#include "srslte/phy/utils/vector.h"
@ -35,26 +36,75 @@
#define Nc 1600
#define MAX_SEQ_LEN (128*1024)
#define static_memory
/*
* Pseudo Random Sequence generation.
* It follows the 3GPP Release 8 (LTE) 36.211
* Section 7.2
*/
void srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t seed) {
#ifdef static_memory
static uint8_t x1[Nc+MAX_SEQ_LEN+31];
static uint8_t x2[Nc+MAX_SEQ_LEN+31];
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) {
int n;
if (len > q->max_len) {
fprintf(stderr, "Error generating pseudo-random sequence: len %d exceeds maximum len %d\n",
len, MAX_SEQ_LEN);
return -1;
}
if (len > q->max_len) {
fprintf(stderr, "Error generating pseudo-random sequence: len %d is greater than allocated len %d\n",
len, q->max_len);
return -1;
}
pthread_mutex_lock(&mutex);
for (n = 0; n < 31; n++) {
x2[n] = (seed >> n) & 0x1;
}
x1[0] = 1;
for (n = 0; n < Nc + len; n++) {
x1[n + 31] = (x1[n + 3] + x1[n]) & 0x1;
x2[n + 31] = (x2[n + 3] + x2[n + 2] + x2[n+1] + x2[n]) & 0x1;
}
for (n = 0; n < len; n++) {
q->c[n] = (x1[n + Nc] + x2[n + Nc]) & 0x1;
}
pthread_mutex_unlock(&mutex);
return 0;
}
#else
int srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) {
int n;
uint32_t *x1, *x2;
x1 = calloc(Nc + q->len + 31, sizeof(uint32_t));
if (len > q->max_len) {
fprintf(stderr, "Error generating pseudo-random sequence: len %d is greater than allocated len %d\n",
len, q->max_len);
return -1;
}
x1 = calloc(Nc + len + 31, sizeof(uint32_t));
if (!x1) {
perror("calloc");
return;
return -1;
}
x2 = calloc(Nc + q->len + 31, sizeof(uint32_t));
x2 = calloc(Nc + len + 31, sizeof(uint32_t));
if (!x2) {
free(x1);
perror("calloc");
return;
return -1;
}
for (n = 0; n < 31; n++) {
@ -62,25 +112,29 @@ void srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t seed) {
}
x1[0] = 1;
for (n = 0; n < Nc + q->len; n++) {
for (n = 0; n < Nc + len; n++) {
x1[n + 31] = (x1[n + 3] + x1[n]) & 0x1;
x2[n + 31] = (x2[n + 3] + x2[n + 2] + +x2[n+1] + x2[n]) & 0x1;
}
for (n = 0; n < q->len; n++) {
for (n = 0; n < len; n++) {
q->c[n] = (x1[n + Nc] + x2[n + Nc]) & 0x1;
}
free(x1);
free(x2);
return 0;
}
#endif
int srslte_sequence_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) {
if (srslte_sequence_init(q, len)) {
return SRSLTE_ERROR;
}
q->len = len;
srslte_sequence_set_LTE_pr(q, seed);
q->cur_len = len;
srslte_sequence_set_LTE_pr(q, len, seed);
srslte_bit_pack_vector(q->c, q->c_bytes, len);
for (int i=0;i<len;i++) {
q->c_float[i] = (1-2*q->c[i]);
@ -90,17 +144,8 @@ int srslte_sequence_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) {
}
int srslte_sequence_init(srslte_sequence_t *q, uint32_t len) {
if (q->c && (q->len != len)) {
free(q->c);
if (q->c_bytes) {
free(q->c_bytes);
}
if (q->c_float) {
free(q->c_float);
}
if (q->c_short) {
free(q->c_short);
}
if (q->c && len > q->max_len) {
srslte_sequence_free(q);
}
if (!q->c) {
q->c = srslte_vec_malloc(len * sizeof(uint8_t));
@ -119,7 +164,7 @@ int srslte_sequence_init(srslte_sequence_t *q, uint32_t len) {
if (!q->c_short) {
return SRSLTE_ERROR;
}
q->len = len;
q->max_len = len;
}
return SRSLTE_SUCCESS;
}

@ -29,6 +29,7 @@
#include <complex.h>
#include <fftw3.h>
#include <string.h>
#include <srslte/srslte.h>
#include "srslte/phy/dft/dft.h"
#include "srslte/phy/utils/vector.h"
@ -38,14 +39,27 @@
#define FFTW_WISDOM_FILE ".fftw_wisdom"
#ifdef FFTW_WISDOM_FILE
#define FFTW_TYPE FFTW_MEASURE
#else
#define FFTW_TYPE 0
#endif
void srslte_dft_load() {
#ifdef FFTW_WISDOM_FILE
fftwf_import_wisdom_from_filename(FFTW_WISDOM_FILE);
#else
printf("Warning: FFTW Wisdom file not defined\n");
#endif
}
void srslte_dft_exit() {
#ifdef FFTW_WISDOM_FILE
if (!fftwf_export_wisdom_to_filename(FFTW_WISDOM_FILE)) {
fprintf(stderr, "Error saving FFTW wisdom to file %s\n", FFTW_WISDOM_FILE);
}
#endif
}
int srslte_dft_plan(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir,
@ -58,19 +72,50 @@ int srslte_dft_plan(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_di
return 0;
}
int srslte_dft_replan(srslte_dft_plan_t *plan, const int new_dft_points) {
if (new_dft_points <= plan->init_size) {
if(plan->mode == SRSLTE_DFT_COMPLEX){
return srslte_dft_replan_c(plan,new_dft_points);
} else {
return srslte_dft_replan_r(plan,new_dft_points);
}
} else {
fprintf(stderr, "DFT: Error calling replan: new_dft_points (%d) must be lower or equal "
"dft_size passed initially (%d)\n", new_dft_points, plan->init_size);
return -1;
}
}
static void allocate(srslte_dft_plan_t *plan, int size_in, int size_out, int len) {
plan->in = fftwf_malloc(size_in*len);
plan->out = fftwf_malloc(size_out*len);
}
int srslte_dft_replan_c(srslte_dft_plan_t *plan, const int new_dft_points) {
int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD;
if (plan->p) {
fftwf_destroy_plan(plan->p);
plan->p = NULL;
}
plan->p = fftwf_plan_dft_1d(new_dft_points, plan->in, plan->out, sign, FFTW_TYPE);
if (!plan->p) {
return -1;
}
plan->size = new_dft_points;
return 0;
}
int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) {
allocate(plan,sizeof(fftwf_complex),sizeof(fftwf_complex), dft_points);
int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD;
plan->p = fftwf_plan_dft_1d(dft_points, plan->in, plan->out, sign, FFTW_MEASURE);
plan->p = fftwf_plan_dft_1d(dft_points, plan->in, plan->out, sign, FFTW_TYPE);
if (!plan->p) {
return -1;
}
plan->size = dft_points;
plan->init_size = plan->size;
plan->mode = SRSLTE_DFT_COMPLEX;
plan->dir = dir;
plan->forward = (dir==SRSLTE_DFT_FORWARD)?true:false;
@ -82,14 +127,29 @@ int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_
return 0;
}
int srslte_dft_replan_r(srslte_dft_plan_t *plan, const int new_dft_points) {
int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R;
if (plan->p) {
fftwf_destroy_plan(plan->p);
plan->p = NULL;
}
plan->p = fftwf_plan_r2r_1d(new_dft_points, plan->in, plan->out, sign, FFTW_TYPE);
if (!plan->p) {
return -1;
}
plan->size = new_dft_points;
return 0;
}
int srslte_dft_plan_r(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) {
allocate(plan,sizeof(float),sizeof(float), dft_points);
int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R;
plan->p = fftwf_plan_r2r_1d(dft_points, plan->in, plan->out, sign, FFTW_MEASURE);
plan->p = fftwf_plan_r2r_1d(dft_points, plan->in, plan->out, sign, FFTW_TYPE);
if (!plan->p) {
return -1;
}
plan->size = dft_points;
plan->init_size = plan->size;
plan->mode = SRSLTE_REAL;
plan->dir = dir;
plan->forward = (dir==SRSLTE_DFT_FORWARD)?true:false;

@ -40,7 +40,8 @@
#include "srslte/phy/dft/dft_precoding.h"
/* Create DFT plans for transform precoding */
int srslte_dft_precoding_init(srslte_dft_precoding_t *q, uint32_t max_prb)
int srslte_dft_precoding_init(srslte_dft_precoding_t *q, uint32_t max_prb, bool is_tx)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
bzero(q, sizeof(srslte_dft_precoding_t));
@ -50,16 +51,11 @@ int srslte_dft_precoding_init(srslte_dft_precoding_t *q, uint32_t max_prb)
for (uint32_t i=1;i<=max_prb;i++) {
if(srslte_dft_precoding_valid_prb(i)) {
DEBUG("Initiating DFT precoding plan for %d PRBs\n", i);
if (srslte_dft_plan_c(&q->dft_plan[i], i*SRSLTE_NRE, SRSLTE_DFT_FORWARD)) {
if (srslte_dft_plan_c(&q->dft_plan[i], i*SRSLTE_NRE, is_tx?SRSLTE_DFT_FORWARD:SRSLTE_DFT_BACKWARD)) {
fprintf(stderr, "Error: Creating DFT plan %d\n",i);
goto clean_exit;
}
srslte_dft_plan_set_norm(&q->dft_plan[i], true);
if (srslte_dft_plan_c(&q->idft_plan[i], i*SRSLTE_NRE, SRSLTE_DFT_BACKWARD)) {
fprintf(stderr, "Error: Creating DFT plan %d\n",i);
goto clean_exit;
}
srslte_dft_plan_set_norm(&q->idft_plan[i], true);
}
}
q->max_prb = max_prb;
@ -73,13 +69,21 @@ clean_exit:
return ret;
}
int srslte_dft_precoding_init_rx(srslte_dft_precoding_t *q, uint32_t max_prb)
{
return srslte_dft_precoding_init(q, max_prb, false);
}
int srslte_dft_precoding_init_tx(srslte_dft_precoding_t *q, uint32_t max_prb) {
return srslte_dft_precoding_init(q, max_prb, true);
}
/* Free DFT plans for transform precoding */
void srslte_dft_precoding_free(srslte_dft_precoding_t *q)
{
for (uint32_t i=1;i<=q->max_prb;i++) {
if(srslte_dft_precoding_valid_prb(i)) {
srslte_dft_plan_free(&q->dft_plan[i]);
srslte_dft_plan_free(&q->idft_plan[i]);
}
}
bzero(q, sizeof(srslte_dft_precoding_t));
@ -112,19 +116,3 @@ int srslte_dft_precoding(srslte_dft_precoding_t *q, cf_t *input, cf_t *output,
return SRSLTE_SUCCESS;
}
int srslte_dft_predecoding(srslte_dft_precoding_t *q, cf_t *input, cf_t *output,
uint32_t nof_prb, uint32_t nof_symbols)
{
if (!srslte_dft_precoding_valid_prb(nof_prb) && nof_prb <= q->max_prb) {
fprintf(stderr, "Error invalid number of PRB (%d)\n", nof_prb);
return SRSLTE_ERROR;
}
for (uint32_t i=0;i<nof_symbols;i++) {
srslte_dft_run_c(&q->idft_plan[nof_prb], &input[i*SRSLTE_NRE*nof_prb], &output[i*SRSLTE_NRE*nof_prb]);
}
return SRSLTE_SUCCESS;
}

@ -29,6 +29,7 @@
#include <stdlib.h>
#include <complex.h>
#include <math.h>
#include <srslte/srslte.h>
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/dft/dft.h"
@ -48,6 +49,12 @@ int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_p
return -1;
}
q->shift_buffer = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN(symbol_sz));
if (!q->shift_buffer) {
perror("malloc");
return -1;
}
srslte_dft_plan_set_mirror(&q->fft_plan, true);
srslte_dft_plan_set_dc(&q->fft_plan, true);
@ -55,7 +62,6 @@ int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_p
q->nof_symbols = SRSLTE_CP_NSYMB(cp);
q->cp = cp;
q->freq_shift = false;
q->shift_buffer = NULL;
q->nof_re = nof_prb * SRSLTE_NRE;
q->nof_guards = ((symbol_sz - q->nof_re) / 2);
q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz);
@ -67,6 +73,32 @@ int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_p
return SRSLTE_SUCCESS;
}
int srslte_ofdm_replan_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_prb) {
if (srslte_dft_replan_c(&q->fft_plan, symbol_sz)) {
fprintf(stderr, "Error: Creating DFT plan\n");
return -1;
}
q->symbol_sz = (uint32_t) symbol_sz;
q->nof_symbols = SRSLTE_CP_NSYMB(cp);
q->cp = cp;
q->nof_re = nof_prb * SRSLTE_NRE;
q->nof_guards = ((symbol_sz - q->nof_re) / 2);
q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz);
if (q->freq_shift) {
srslte_ofdm_set_freq_shift(q, q->freq_shift_f);
}
DEBUG("Replan symbol_sz=%d, nof_symbols=%d, cp=%s, nof_re=%d, nof_guards=%d\n",
q->symbol_sz, q->nof_symbols,
q->cp==SRSLTE_CP_NORM?"Normal":"Extended", q->nof_re, q->nof_guards);
return SRSLTE_SUCCESS;
}
void srslte_ofdm_free_(srslte_ofdm_t *q) {
srslte_dft_plan_free(&q->fft_plan);
if (q->tmp) {
@ -78,34 +110,69 @@ void srslte_ofdm_free_(srslte_ofdm_t *q) {
bzero(q, sizeof(srslte_ofdm_t));
}
int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) {
int symbol_sz = srslte_symbol_sz(max_prb);
if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", max_prb);
return -1;
}
q->max_prb = max_prb;
return srslte_ofdm_init_(q, cp, symbol_sz, max_prb, SRSLTE_DFT_FORWARD);
}
int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) {
uint32_t i;
int ret;
int symbol_sz = srslte_symbol_sz(max_prb);
if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", max_prb);
return -1;
}
q->max_prb = max_prb;
ret = srslte_ofdm_init_(q, cp, symbol_sz, max_prb, SRSLTE_DFT_BACKWARD);
if (ret == SRSLTE_SUCCESS) {
srslte_dft_plan_set_norm(&q->fft_plan, false);
/* set now zeros at CP */
for (i=0;i<q->nof_symbols;i++) {
bzero(q->tmp, q->nof_guards * sizeof(cf_t));
bzero(&q->tmp[q->nof_re + q->nof_guards], q->nof_guards * sizeof(cf_t));
}
}
return ret;
}
int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
if (nof_prb <= q->max_prb) {
int symbol_sz = srslte_symbol_sz(nof_prb);
if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb);
return -1;
}
return srslte_ofdm_init_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_FORWARD);
return srslte_ofdm_replan_(q, cp, symbol_sz, nof_prb);
} else {
fprintf(stderr, "OFDM: Error calling set_prb: nof_prb must be equal or lower initialized max_prb\n");
return -1;
}
void srslte_ofdm_rx_free(srslte_ofdm_t *q) {
srslte_ofdm_free_(q);
}
int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
uint32_t i;
int ret;
if (nof_prb <= q->max_prb) {
int symbol_sz = srslte_symbol_sz(nof_prb);
if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb);
return -1;
}
ret = srslte_ofdm_init_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_BACKWARD);
ret = srslte_ofdm_replan_(q, cp, symbol_sz, nof_prb);
if (ret == SRSLTE_SUCCESS) {
srslte_dft_plan_set_norm(&q->fft_plan, false);
/* set now zeros at CP */
for (i=0;i<q->nof_symbols;i++) {
bzero(q->tmp, q->nof_guards * sizeof(cf_t));
@ -113,6 +180,15 @@ int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
}
}
return ret;
} else {
fprintf(stderr, "OFDM: Error calling set_prb: nof_prb must be equal or lower initialized max_prb\n");
return -1;
}
}
void srslte_ofdm_rx_free(srslte_ofdm_t *q) {
srslte_ofdm_free_(q);
}
/* Shifts the signal after the iFFT or before the FFT.
@ -120,11 +196,6 @@ int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
* Caution: This function shall not be called during run-time
*/
int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q, float freq_shift) {
q->shift_buffer = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN(q->symbol_sz));
if (!q->shift_buffer) {
perror("malloc");
return -1;
}
cf_t *ptr = q->shift_buffer;
for (uint32_t n=0;n<2;n++) {
for (uint32_t i=0;i<q->nof_symbols;i++) {
@ -140,7 +211,7 @@ int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q, float freq_shift) {
srslte_dft_plan_set_dc(&q->fft_plan, false);
q->freq_shift = true;
q->freq_shift_f = freq_shift;
return SRSLTE_SUCCESS;
}

@ -29,6 +29,8 @@
#include <complex.h>
#include <math.h>
#include <string.h>
#include <srslte/phy/common/phy_common.h>
#include <srslte/srslte.h>
#define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb)
@ -39,78 +41,67 @@
#define SRSLTE_ENB_RF_AMP 0.1
int srslte_enb_dl_init(srslte_enb_dl_t *q, srslte_cell_t cell)
int srslte_enb_dl_init(srslte_enb_dl_t *q, uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
if (q != NULL)
{
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_enb_dl_t));
q->cell = cell;
q->cfi = 3;
q->tx_amp = SRSLTE_ENB_RF_AMP;
if (srslte_ofdm_tx_init(&q->ifft, q->cell.cp, q->cell.nof_prb)) {
if (srslte_ofdm_tx_init(&q->ifft, SRSLTE_CP_NORM, max_prb)) {
fprintf(stderr, "Error initiating FFT\n");
goto clean_exit;
}
srslte_ofdm_set_normalize(&q->ifft, true);
if (srslte_regs_init(&q->regs, q->cell)) {
fprintf(stderr, "Error initiating REGs\n");
goto clean_exit;
}
if (srslte_pbch_init(&q->pbch, q->cell)) {
if (srslte_pbch_init(&q->pbch)) {
fprintf(stderr, "Error creating PBCH object\n");
goto clean_exit;
}
if (srslte_pcfich_init(&q->pcfich, &q->regs, q->cell)) {
if (srslte_pcfich_init(&q->pcfich, 0)) {
fprintf(stderr, "Error creating PCFICH object\n");
goto clean_exit;
}
if (srslte_phich_init(&q->phich, &q->regs, q->cell)) {
if (srslte_phich_init(&q->phich, 0)) {
fprintf(stderr, "Error creating PHICH object\n");
goto clean_exit;
}
if (srslte_pdcch_init(&q->pdcch, &q->regs, q->cell)) {
if (srslte_pdcch_init_enb(&q->pdcch, max_prb)) {
fprintf(stderr, "Error creating PDCCH object\n");
goto clean_exit;
}
if (srslte_pdsch_init_tx(&q->pdsch, q->cell)) {
if (srslte_pdsch_init_enb(&q->pdsch, max_prb)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto clean_exit;
}
if (srslte_refsignal_cs_init(&q->csr_signal, q->cell)) {
if (srslte_refsignal_cs_init(&q->csr_signal, max_prb)) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
goto clean_exit;
}
for (int i=0;i<q->cell.nof_ports;i++) {
q->sf_symbols[i] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
q->sf_symbols[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->sf_symbols[i]) {
perror("malloc");
goto clean_exit;
}
q->slot1_symbols[i] = &q->sf_symbols[i][CURRENT_SLOTLEN_RE];
q->slot1_symbols[i] = &q->sf_symbols[i][SRSLTE_SLOT_LEN_RE(max_prb, SRSLTE_CP_NORM)];
}
/* Generate PSS/SSS signals */
srslte_pss_generate(q->pss_signal, cell.id%3);
srslte_sss_generate(q->sss_signal0, q->sss_signal5, cell.id);
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
fprintf(stderr, "Invalid parameters\n");
}
clean_exit:
@ -125,6 +116,7 @@ void srslte_enb_dl_free(srslte_enb_dl_t *q)
if (q) {
srslte_ofdm_tx_free(&q->ifft);
srslte_regs_free(&q->regs);
srslte_pbch_free(&q->pbch);
srslte_pcfich_free(&q->pcfich);
srslte_phich_free(&q->phich);
srslte_pdcch_free(&q->pdcch);
@ -141,6 +133,71 @@ void srslte_enb_dl_free(srslte_enb_dl_t *q)
}
}
int srslte_enb_dl_set_cell(srslte_enb_dl_t *q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
srslte_enb_dl_set_cfi(q, 3);
q->tx_amp = SRSLTE_ENB_RF_AMP;
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
if (q->cell.nof_prb != 0) {
srslte_regs_free(&q->regs);
}
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
if (srslte_regs_init(&q->regs, q->cell)) {
fprintf(stderr, "Error resizing REGs\n");
return SRSLTE_ERROR;
}
if (srslte_ofdm_rx_set_prb(&q->ifft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating FFT\n");
return SRSLTE_ERROR;
}
if (srslte_pbch_set_cell(&q->pbch, q->cell)) {
fprintf(stderr, "Error creating PBCH object\n");
return SRSLTE_ERROR;
}
if (srslte_pcfich_set_cell(&q->pcfich, &q->regs, q->cell)) {
fprintf(stderr, "Error creating PCFICH object\n");
return SRSLTE_ERROR;
}
if (srslte_phich_set_cell(&q->phich, &q->regs, q->cell)) {
fprintf(stderr, "Error creating PHICH object\n");
return SRSLTE_ERROR;
}
if (srslte_pdcch_set_cell(&q->pdcch, &q->regs, q->cell)) {
fprintf(stderr, "Error creating PDCCH object\n");
return SRSLTE_ERROR;
}
if (srslte_pdsch_set_cell(&q->pdsch, q->cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
return SRSLTE_ERROR;
}
if (srslte_refsignal_cs_set_cell(&q->csr_signal, q->cell)) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
return SRSLTE_ERROR;
}
/* Generate PSS/SSS signals */
srslte_pss_generate(q->pss_signal, cell.id%3);
srslte_sss_generate(q->sss_signal0, q->sss_signal5, cell.id);
}
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
}
return ret;
}
void srslte_enb_dl_set_amp(srslte_enb_dl_t *q, float amp)
{
q->tx_amp = amp;
@ -263,11 +320,11 @@ int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q, srslte_ra_ul_dci_t *grant,
}
int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, srslte_ra_dl_grant_t *grant, srslte_softbuffer_tx_t *softbuffer[SRSLTE_MAX_CODEWORDS],
uint16_t rnti, uint32_t rv_idx, uint32_t sf_idx,
uint8_t *data[SRSLTE_MAX_CODEWORDS])
uint16_t rnti, int rv_idx[SRSLTE_MAX_CODEWORDS], uint32_t sf_idx,
uint8_t *data[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type, uint32_t pmi)
{
/* Configure pdsch_cfg parameters */
if (srslte_pdsch_cfg(&q->pdsch_cfg, q->cell, grant, q->cfi, sf_idx, rv_idx)) {
if (srslte_pdsch_cfg_mimo(&q->pdsch_cfg, q->cell, grant, q->cfi, sf_idx, rv_idx, mimo_type, pmi)) {
fprintf(stderr, "Error configuring PDSCH\n");
return SRSLTE_ERROR;
}

@ -39,78 +39,54 @@
#define MAX_CANDIDATES 16
int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell,
srslte_prach_cfg_t *prach_cfg,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pusch_hopping_cfg_t *hopping_cfg,
srslte_pucch_cfg_t *pucch_cfg)
int srslte_enb_ul_init(srslte_enb_ul_t *q,
uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
if (q != NULL)
{
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_enb_ul_t));
q->cell = cell;
if (hopping_cfg) {
memcpy(&q->hopping_cfg, hopping_cfg, sizeof(srslte_pusch_hopping_cfg_t));
}
q->users = calloc(sizeof(srslte_enb_ul_user_t*), (1+SRSLTE_SIRNTI));
if (!q->users) {
perror("malloc");
goto clean_exit;
}
if (srslte_ofdm_rx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) {
if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) {
fprintf(stderr, "Error initiating FFT\n");
goto clean_exit;
}
srslte_ofdm_set_normalize(&q->fft, false);
srslte_ofdm_set_freq_shift(&q->fft, -0.5);
if (srslte_pucch_init(&q->pucch, q->cell)) {
if (srslte_pucch_init(&q->pucch)) {
fprintf(stderr, "Error creating PUCCH object\n");
goto clean_exit;
}
if (srslte_pusch_init(&q->pusch, q->cell)) {
if (srslte_pusch_init_enb(&q->pusch, max_prb)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit;
}
if (prach_cfg) {
if (srslte_prach_init_cfg(&q->prach, prach_cfg, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating PRACH\n");
goto clean_exit;
}
srslte_prach_set_detect_factor(&q->prach, 60);
}
srslte_pucch_set_threshold(&q->pucch, 0.8);
if (srslte_chest_ul_init(&q->chest, cell)) {
if (srslte_chest_ul_init(&q->chest, max_prb)) {
fprintf(stderr, "Error initiating channel estimator\n");
goto clean_exit;
}
// Configure common PUCCH configuration
srslte_pucch_set_cfg(&q->pucch, pucch_cfg, pusch_cfg->group_hopping_en);
// SRS is a dedicated configuration
srslte_chest_ul_set_cfg(&q->chest, pusch_cfg, pucch_cfg, NULL);
q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->sf_symbols) {
perror("malloc");
goto clean_exit;
}
q->ce = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
q->ce = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->ce) {
perror("malloc");
goto clean_exit;
@ -119,8 +95,7 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell,
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
fprintf(stderr, "Invalid parameters\n");
}
clean_exit:
@ -135,7 +110,7 @@ void srslte_enb_ul_free(srslte_enb_ul_t *q)
if (q) {
if (q->users) {
for (int i=0;i<SRSLTE_SIRNTI;i++) {
for (int i=0;i<=SRSLTE_SIRNTI;i++) {
if (q->users[i]) {
free(q->users[i]);
}
@ -158,6 +133,68 @@ void srslte_enb_ul_free(srslte_enb_ul_t *q)
}
}
int srslte_enb_ul_set_cell(srslte_enb_ul_t *q, srslte_cell_t cell,
srslte_prach_cfg_t *prach_cfg,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pusch_hopping_cfg_t *hopping_cfg,
srslte_pucch_cfg_t *pucch_cfg)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
if (hopping_cfg) {
memcpy(&q->hopping_cfg, hopping_cfg, sizeof(srslte_pusch_hopping_cfg_t));
}
if (srslte_ofdm_rx_set_prb(&q->fft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating FFT\n");
return SRSLTE_ERROR;
}
if (srslte_pucch_set_cell(&q->pucch, q->cell)) {
fprintf(stderr, "Error creating PUCCH object\n");
return SRSLTE_ERROR;
}
if (srslte_pusch_set_cell(&q->pusch, q->cell)) {
fprintf(stderr, "Error creating PUSCH object\n");
return SRSLTE_ERROR;
}
if (prach_cfg) {
if (srslte_prach_init_cfg(&q->prach, prach_cfg, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating PRACH\n");
return SRSLTE_ERROR;
}
srslte_prach_set_detect_factor(&q->prach, 60);
}
if (srslte_chest_ul_set_cell(&q->chest, cell)) {
fprintf(stderr, "Error initiating channel estimator\n");
return SRSLTE_ERROR;
}
// Configure common PUCCH configuration
srslte_pucch_set_cfg(&q->pucch, pucch_cfg, pusch_cfg->group_hopping_en);
// SRS is a dedicated configuration
srslte_chest_ul_set_cfg(&q->chest, pusch_cfg, pucch_cfg, NULL);
ret = SRSLTE_SUCCESS;
}
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
}
return ret;
}
int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q, uint16_t rnti)
{
if (!q->users[rnti]) {
@ -183,7 +220,7 @@ void srslte_enb_ul_rem_rnti(srslte_enb_ul_t *q, uint16_t rnti)
if (q->users[rnti]) {
free(q->users[rnti]);
q->users[rnti] = NULL;
srslte_pusch_clear_rnti(&q->pusch, rnti);
srslte_pusch_free_rnti(&q->pusch, rnti);
}
}

@ -272,10 +272,10 @@ float srslte_cqi_to_coderate(uint32_t cqi) {
* Table III.
*/
// From paper
static float cqi_to_snr_table[15] = { 1.95, 4, 6, 8, 10, 11.95, 14.05, 16, 17.9, 19.9, 21.5, 23.45, 25.0, 27.30, 29};
//static float cqi_to_snr_table[15] = { 1.95, 4, 6, 8, 10, 11.95, 14.05, 16, 17.9, 19.9, 21.5, 23.45, 25.0, 27.30, 29};
// From experimental measurements @ 5 MHz
//static float cqi_to_snr_table[15] = { 1, 1.75, 3, 4, 5, 6, 7.5, 9, 11.5, 13.0, 15.0, 18, 20, 22.5, 26.5};
static float cqi_to_snr_table[15] = { 1, 1.75, 3, 4, 5, 6, 7.5, 9, 11.5, 13.0, 15.0, 18, 20, 22.5, 26.5};
uint8_t srslte_cqi_from_snr(float snr)
{

@ -32,6 +32,8 @@
#include <stdbool.h>
#include <assert.h>
#include <math.h>
#include <srslte/srslte.h>
#include <srslte/phy/common/phy_common.h>
#include "prb_dl.h"
#include "srslte/phy/phch/pbch.h"
@ -43,7 +45,6 @@
#define PBCH_RE_CP_NORM 240
#define PBCH_RE_CP_EXT 216
const uint8_t srslte_crc_mask[4][16] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
@ -139,33 +140,18 @@ int srslte_pbch_get(cf_t *slot1_data, cf_t *pbch, srslte_cell_t cell) {
* At the receiver, the field nof_ports in the cell structure indicates the
* maximum number of BS transmitter ports to look for.
*/
int srslte_pbch_init(srslte_pbch_t *q, srslte_cell_t cell) {
int srslte_pbch_init(srslte_pbch_t *q) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
if (q != NULL)
{
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_pbch_t));
if (cell.nof_ports == 0) {
q->search_all_ports = true;
cell.nof_ports = SRSLTE_MAX_PORTS;
} else {
q->search_all_ports = false;
}
q->cell = cell;
q->nof_symbols = (SRSLTE_CP_ISNORM(q->cell.cp)) ? PBCH_RE_CP_NORM : PBCH_RE_CP_EXT;
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
goto clean;
}
if (srslte_sequence_pbch(&q->seq, q->cell.cp, q->cell.id)) {
goto clean;
}
int poly[3] = { 0x6D, 0x4F, 0x57 };
if (srslte_viterbi_init(&q->decoder, SRSLTE_VITERBI_37, poly, 40, true)) {
goto clean;
@ -178,12 +164,14 @@ int srslte_pbch_init(srslte_pbch_t *q, srslte_cell_t cell) {
q->encoder.tail_biting = true;
memcpy(q->encoder.poly, poly, 3 * sizeof(int));
q->nof_symbols = PBCH_RE_CP_NORM;
q->d = srslte_vec_malloc(sizeof(cf_t) * q->nof_symbols);
if (!q->d) {
goto clean;
}
int i;
for (i = 0; i < q->cell.nof_ports; i++) {
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
q->ce[i] = srslte_vec_malloc(sizeof(cf_t) * q->nof_symbols);
if (!q->ce[i]) {
goto clean;
@ -209,6 +197,7 @@ int srslte_pbch_init(srslte_pbch_t *q, srslte_cell_t cell) {
if (!q->rm_b) {
goto clean;
}
ret = SRSLTE_SUCCESS;
}
clean:
@ -219,11 +208,11 @@ clean:
}
void srslte_pbch_free(srslte_pbch_t *q) {
if (q->d) {
free(q->d);
}
srslte_sequence_free(&q->seq);
srslte_modem_table_free(&q->mod);
srslte_viterbi_free(&q->decoder);
int i;
for (i = 0; i < q->cell.nof_ports; i++) {
for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
if (q->ce[i]) {
free(q->ce[i]);
}
@ -243,12 +232,36 @@ void srslte_pbch_free(srslte_pbch_t *q) {
if (q->rm_b) {
free(q->rm_b);
}
srslte_sequence_free(&q->seq);
srslte_modem_table_free(&q->mod);
srslte_viterbi_free(&q->decoder);
if (q->d) {
free(q->d);
}
bzero(q, sizeof(srslte_pbch_t));
}
int srslte_pbch_set_cell(srslte_pbch_t *q, srslte_cell_t cell) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
if (cell.nof_ports == 0) {
q->search_all_ports = true;
cell.nof_ports = SRSLTE_MAX_PORTS;
} else {
q->search_all_ports = false;
}
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
if (srslte_sequence_pbch(&q->seq, q->cell.cp, q->cell.id)) {
return SRSLTE_ERROR;
}
}
q->nof_symbols = (SRSLTE_CP_ISNORM(q->cell.cp)) ? PBCH_RE_CP_NORM : PBCH_RE_CP_EXT;
ret = SRSLTE_SUCCESS;
}
return ret;
}
@ -476,6 +489,7 @@ int srslte_pbch_decode(srslte_pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[SRS
} else {
nant = q->cell.nof_ports;
}
do {
if (nant != 3) {
DEBUG("Trying %d TX antennas with %d frames\n", nant, q->frame_idx);

@ -57,38 +57,24 @@ bool srslte_pcfich_exists(int nframe, int nslot) {
return true;
}
int srslte_pcfich_init(srslte_pcfich_t *q, srslte_regs_t *regs, srslte_cell_t cell) {
return srslte_pcfich_init_multi(q, regs, cell, 1);
}
/** Initializes the pcfich channel receiver.
* On error, returns -1 and frees the structrure
*/
int srslte_pcfich_init_multi(srslte_pcfich_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas) {
int srslte_pcfich_init(srslte_pcfich_t *q, uint32_t nof_rx_antennas) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
regs != NULL &&
srslte_cell_isvalid(&cell))
if (q != NULL)
{
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_pcfich_t));
q->cell = cell;
q->regs = regs;
q->nof_symbols = PCFICH_RE;
q->nof_rx_antennas = nof_rx_antennas;
q->nof_symbols = PCFICH_RE;
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
goto clean;
}
for (int nsf = 0; nsf < SRSLTE_NSUBFRAMES_X_FRAME; nsf++) {
if (srslte_sequence_pcfich(&q->seq[nsf], 2 * nsf, q->cell.id)) {
goto clean;
}
}
/* convert cfi bit tables to floats for demodulation */
for (int i=0;i<3;i++) {
for (int j=0;j<PCFICH_CFI_LEN;j++) {
@ -115,6 +101,28 @@ void srslte_pcfich_free(srslte_pcfich_t *q) {
bzero(q, sizeof(srslte_pcfich_t));
}
int srslte_pcfich_set_cell(srslte_pcfich_t *q, srslte_regs_t *regs, srslte_cell_t cell) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
regs != NULL &&
srslte_cell_isvalid(&cell))
{
q->regs = regs;
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
for (int nsf = 0; nsf < SRSLTE_NSUBFRAMES_X_FRAME; nsf++) {
if (srslte_sequence_pcfich(&q->seq[nsf], 2 * nsf, q->cell.id)) {
return SRSLTE_ERROR;
}
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
/** Finds the CFI with minimum distance with the vector of received 32 bits.
* Saves the CFI value in the cfi pointer and returns the distance.
*/

@ -61,41 +61,20 @@ float srslte_pdcch_coderate(uint32_t nof_bits, uint32_t l) {
}
/** Initializes the PDCCH transmitter and receiver */
int srslte_pdcch_init(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell) {
return srslte_pdcch_init_multi(q, regs, cell, 1);
}
int srslte_pdcch_init_tx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell) {
return srslte_pdcch_init_txrx(q, regs, cell, 1, false);
}
int srslte_pdcch_init_rx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas) {
return srslte_pdcch_init_txrx(q, regs, cell, nof_rx_antennas, true);
}
int srslte_pdcch_init_multi(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas) {
return srslte_pdcch_init_txrx(q, regs, cell, nof_rx_antennas, true);
}
int srslte_pdcch_init_txrx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas, bool isReceiver)
static int pdcch_init(srslte_pdcch_t *q, uint32_t max_prb, uint32_t nof_rx_antennas, bool is_ue)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
regs != NULL &&
srslte_cell_isvalid(&cell))
if (q != NULL)
{
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_pdcch_t));
q->cell = cell;
q->regs = regs;
q->nof_rx_antennas = nof_rx_antennas;
q->is_ue = is_ue;
/* Allocate memory for the maximum number of PDCCH bits (CFI=3) */
q->max_bits = (srslte_regs_pdcch_nregs(q->regs, 3) / 9) * 72;
q->max_bits = max_prb*3*12*2;
INFO("Init PDCCH: Max bits: %d, %d ports.\n",
q->max_bits, q->cell.nof_ports);
INFO("Init PDCCH: Max bits: %d\n", q->max_bits);
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
goto clean;
@ -104,14 +83,6 @@ int srslte_pdcch_init_txrx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t
goto clean;
}
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
// we need to pregenerate the sequence for the maximum number of bits, which is 8 times
// the maximum number of REGs (for CFI=3)
if (srslte_sequence_pdcch(&q->seq[i], 2 * i, q->cell.id, 8*srslte_regs_pdcch_nregs(q->regs, 3))) {
goto clean;
}
}
int poly[3] = { 0x6D, 0x4F, 0x57 };
if (srslte_viterbi_init(&q->decoder, SRSLTE_VITERBI_37, poly, SRSLTE_DCI_MAX_BITS + 16, true)) {
goto clean;
@ -134,30 +105,24 @@ int srslte_pdcch_init_txrx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t
goto clean;
}
if (isReceiver) {
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
for (int j = 0; j < q->nof_rx_antennas; j++) {
q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->ce[i][j]) {
goto clean;
}
}
}
}
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->x[i]) {
goto clean;
}
q->symbols[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->symbols[i]) {
goto clean;
}
for (int j = 0; j < ((isReceiver) ? q->nof_rx_antennas : cell.nof_ports); j++) {
q->symbols[j] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->symbols[j]) {
if (q->is_ue) {
for (int j = 0; j < q->nof_rx_antennas; j++) {
q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->ce[i][j]) {
goto clean;
}
}
}
}
ret = SRSLTE_SUCCESS;
}
@ -168,6 +133,14 @@ int srslte_pdcch_init_txrx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t
return ret;
}
int srslte_pdcch_init_enb(srslte_pdcch_t *q, uint32_t max_prb) {
return pdcch_init(q, max_prb, 0, false);
}
int srslte_pdcch_init_ue(srslte_pdcch_t *q, uint32_t max_prb, uint32_t nof_rx_antennas) {
return pdcch_init(q, max_prb, nof_rx_antennas, true);
}
void srslte_pdcch_free(srslte_pdcch_t *q) {
if (q->e) {
@ -180,18 +153,18 @@ void srslte_pdcch_free(srslte_pdcch_t *q) {
free(q->d);
}
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
for (int j=0;j<q->nof_rx_antennas;j++) {
if (q->ce[i][j]) {
free(q->ce[i][j]);
}
}
if (q->x[i]) {
free(q->x[i]);
}
if (q->symbols[i]) {
free(q->symbols[i]);
}
if (q->is_ue) {
for (int j=0;j<q->nof_rx_antennas;j++) {
if (q->symbols[j]) {
free(q->symbols[j]);
if (q->ce[i][j]) {
free(q->ce[i][j]);
}
}
}
}
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
@ -205,6 +178,39 @@ void srslte_pdcch_free(srslte_pdcch_t *q) {
}
int srslte_pdcch_set_cell(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
regs != NULL &&
srslte_cell_isvalid(&cell))
{
q->regs = regs;
/* Allocate memory for the maximum number of PDCCH bits (CFI=3) */
q->max_bits = (srslte_regs_pdcch_nregs(q->regs, 3) / 9) * 72;
INFO("PDCCH: Cell config PCI=%d, %d ports.\n",
q->cell.id, q->cell.nof_ports);
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
// we need to pregenerate the sequence for the maximum number of bits, which is 8 times
// the maximum number of REGs (for CFI=3)
if (srslte_sequence_pdcch(&q->seq[i], 2 * i, q->cell.id, 8*srslte_regs_pdcch_nregs(q->regs, 3))) {
return SRSLTE_ERROR;
}
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
uint32_t srslte_pdcch_ue_locations(srslte_pdcch_t *q, srslte_dci_location_t *c, uint32_t max_candidates,
uint32_t nsubframe, uint32_t cfi, uint16_t rnti)
{

@ -27,25 +27,22 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <math.h>
#include <srslte/phy/phch/pdsch_cfg.h>
#include <srslte/phy/common/sequence.h>
#include <srslte/phy/phch/pdsch.h>
#include "prb_dl.h"
#include "srslte/phy/phch/pdsch.h"
#include "srslte/phy/phch/sch.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/utils/bit.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
#include "srslte/phy/utils/bit.h"
#define MAX_PDSCH_RE(cp) (2 * SRSLTE_CP_NSYMB(cp) * 12)
const static srslte_mod_t modulations[4] =
{ SRSLTE_MOD_BPSK, SRSLTE_MOD_QPSK, SRSLTE_MOD_16QAM, SRSLTE_MOD_64QAM };
@ -197,30 +194,24 @@ int srslte_pdsch_get(srslte_pdsch_t *q, cf_t *sf_symbols, cf_t *symbols,
return srslte_pdsch_cp(q, sf_symbols, symbols, grant, lstart, subframe, false);
}
/** Initializes the PDCCH transmitter or receiver */
int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antennas, bool is_receiver)
/** Initializes the PDSCH transmitter and receiver */
static int pdsch_init(srslte_pdsch_t *q, uint32_t max_prb, bool is_ue, uint32_t nof_antennas)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
int i;
if (q != NULL &&
srslte_cell_isvalid(&cell) &&
nof_antennas <= SRSLTE_MAX_PORTS)
if (q != NULL)
{
bzero(q, sizeof(srslte_pdsch_t));
ret = SRSLTE_ERROR;
q->cell = cell;
q->max_re = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp);
if (is_receiver) {
q->max_re = max_prb * MAX_PDSCH_RE(q->cell.cp);
q->is_ue = is_ue;
q->nof_rx_antennas = nof_antennas;
}
INFO("Init PDSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports,
q->cell.nof_prb, q->max_re);
INFO("Init PDSCH: %d PRBs, max_symbols: %d\n", max_prb, q->max_re);
for (i = 0; i < 4; i++) {
for (int i = 0; i < 4; i++) {
if (srslte_modem_table_lte(&q->mod[i], modulations[i])) {
goto clean;
}
@ -232,7 +223,7 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antenn
goto clean;
}
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
// Allocate int16_t for reception (LLRs)
q->e[i] = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM));
if (!q->e[i]) {
@ -245,17 +236,16 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antenn
}
}
/* Layer mapped symbols memory allocation */
for (i = 0; i < q->cell.nof_ports; i++) {
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->x[i]) {
goto clean;
}
q->symbols[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->symbols[i]) {
goto clean;
}
/* If it is the receiver side, allocate estimated channel */
if (is_receiver) {
for (i = 0; i < q->cell.nof_ports; i++) {
if (q->is_ue) {
for (int j=0;j<q->nof_rx_antennas;j++) {
q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->ce[i][j]) {
@ -264,22 +254,19 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antenn
}
}
}
for (int j=0;j<SRSLTE_MAX(q->nof_rx_antennas, q->cell.nof_ports);j++) {
q->symbols[j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->symbols[j]) {
goto clean;
}
}
/* Allocate User memory (all zeros) */
q->users = calloc(sizeof(srslte_pdsch_user_t*), 1+SRSLTE_SIRNTI);
q->users = calloc(sizeof(srslte_pdsch_user_t*), q->is_ue?1:(1+SRSLTE_SIRNTI));
if (!q->users) {
perror("malloc");
goto clean;
}
if (srslte_sequence_init(&q->tmp_seq, q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
goto clean;
}
ret = SRSLTE_SUCCESS;
}
clean:
if (ret == SRSLTE_ERROR) {
@ -288,18 +275,19 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antenn
return ret;
}
int srslte_pdsch_init_tx(srslte_pdsch_t *q, srslte_cell_t cell) {
return srslte_pdsch_init(q, cell, 0, false);
int srslte_pdsch_init_ue(srslte_pdsch_t *q, uint32_t max_prb, uint32_t nof_antennas)
{
return pdsch_init(q, max_prb, true, nof_antennas);
}
int srslte_pdsch_init_rx(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antennas) {
return srslte_pdsch_init(q, cell, nof_antennas, true);
int srslte_pdsch_init_enb(srslte_pdsch_t *q, uint32_t max_prb)
{
return pdsch_init(q, max_prb, false, 0);
}
void srslte_pdsch_free(srslte_pdsch_t *q) {
int i;
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (q->e[i]) {
free(q->e[i]);
@ -313,69 +301,107 @@ void srslte_pdsch_free(srslte_pdsch_t *q) {
/* Free sch objects */
srslte_sch_free(&q->dl_sch);
for (i = 0; i < q->cell.nof_ports; i++) {
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
if (q->x[i]) {
free(q->x[i]);
}
if (q->symbols[i]) {
free(q->symbols[i]);
}
if (q->is_ue) {
for (int j=0;j<q->nof_rx_antennas;j++) {
if (q->ce[i][j]) {
free(q->ce[i][j]);
}
}
}
for (int j=0;j<SRSLTE_MAX_PORTS;j++) {
if (q->symbols[j]) {
free(q->symbols[j]);
}
}
if (q->users) {
for (uint16_t u=0;u<SRSLTE_SIRNTI;u++) {
if (q->is_ue) {
srslte_pdsch_free_rnti(q, 0);
} else {
for (int u=0;u<=SRSLTE_SIRNTI;u++) {
if (q->users[u]) {
srslte_pdsch_free_rnti(q, u);
}
}
}
free(q->users);
}
for (i = 0; i < 4; i++) {
srslte_sequence_free(&q->tmp_seq);
for (int i = 0; i < 4; i++) {
srslte_modem_table_free(&q->mod[i]);
}
bzero(q, sizeof(srslte_pdsch_t));
}
int srslte_pdsch_set_cell(srslte_pdsch_t *q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
q->max_re = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp);
INFO("PDSCH: Cell config PCI=%d, %d ports, %d PRBs, max_symbols: %d\n", q->cell.nof_ports,
q->cell.id, q->cell.nof_prb, q->max_re);
ret = SRSLTE_SUCCESS;
}
return ret;
}
/* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while
* to execute, so shall be called once the final C-RNTI has been allocated for the session.
*/
int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) {
uint32_t i, j;
if (!q->users[rnti]) {
q->users[rnti] = calloc(1, sizeof(srslte_pdsch_user_t));
if (q->users[rnti]) {
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
for (j = 0; j < SRSLTE_MAX_CODEWORDS; j++) {
if (srslte_sequence_pdsch(&q->users[rnti]->seq[j][i], rnti, j, 2 * i, q->cell.id,
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
ERROR("Generating scrambling sequence");
return SRSLTE_ERROR;
uint32_t rnti_idx = q->is_ue?0:rnti;
if (!q->users[rnti_idx] || q->is_ue) {
if (!q->users[rnti_idx]) {
q->users[rnti_idx] = calloc(1, sizeof(srslte_pdsch_user_t));
if(!q->users[rnti_idx]) {
perror("calloc");
return -1;
}
}
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
for (int j = 0; j < SRSLTE_MAX_CODEWORDS; j++) {
if (srslte_sequence_pdsch(&q->users[rnti_idx]->seq[j][i], rnti, j, 2 * i, q->cell.id,
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM)))
{
fprintf(stderr, "Error initializing PDSCH scrambling sequence\n");
srslte_pdsch_free_rnti(q, rnti);
return SRSLTE_ERROR;
}
}
q->users[rnti]->sequence_generated = true;
}
q->ue_rnti = rnti;
q->users[rnti_idx]->cell_id = q->cell.id;
q->users[rnti_idx]->sequence_generated = true;
} else {
fprintf(stderr, "Error generating PDSCH sequence: rnti=0x%x already generated\n", rnti);
}
return SRSLTE_SUCCESS;
}
void srslte_pdsch_free_rnti(srslte_pdsch_t* q, uint16_t rnti)
{
if (q->users[rnti]) {
uint32_t rnti_idx = q->is_ue?0:rnti;
if (q->users[rnti_idx]) {
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
for (int j = 0; j < SRSLTE_MAX_CODEWORDS; j++) {
srslte_sequence_free(&q->users[rnti]->seq[j][i]);
srslte_sequence_free(&q->users[rnti_idx]->seq[j][i]);
}
}
free(q->users[rnti]);
q->users[rnti] = NULL;
free(q->users[rnti_idx]);
q->users[rnti_idx] = NULL;
q->ue_rnti = 0;
}
}
@ -390,7 +416,7 @@ static void pdsch_decode_debug(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg,
break;
}
DEBUG("SAVED FILE %s: received subframe symbols\n", filename);
srslte_vec_save_file(filename, sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
srslte_vec_save_file(filename, sf_symbols[j], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
for (int i = 0; i < q->cell.nof_ports; i++) {
if (snprintf(filename, FILENAME_MAX, "hest_%d%d.dat", i, j) < 0) {
@ -401,11 +427,21 @@ static void pdsch_decode_debug(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg,
srslte_vec_save_file(filename, ce[i][j], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
}
}
DEBUG("SAVED FILE pdsch_symbols.dat: symbols after equalization\n",0);
srslte_vec_save_file("pdsch_symbols.dat", q->d, cfg->nbits[0].nof_re*sizeof(cf_t));
for (int i=0;i<cfg->nof_layers;i++) {
if (snprintf(filename, FILENAME_MAX, "pdsch_symbols_%d.dat", i) < 0) {
ERROR("Generating file name");
break;
}
DEBUG("SAVED FILE %s: symbols after equalization\n", filename);
srslte_vec_save_file(filename, q->d[i], cfg->nbits[0].nof_re*sizeof(cf_t));
DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n",0);
srslte_vec_save_file("llr.dat", q->e, cfg->nbits[0].nof_bits*sizeof(int16_t));
if (snprintf(filename, FILENAME_MAX, "llr_%d.dat", i) < 0) {
ERROR("Generating file name");
break;
}
DEBUG("SAVED FILE %s: LLR estimates after demodulation and descrambling\n", filename);
srslte_vec_save_file(filename, q->e[i], cfg->nbits[0].nof_bits*sizeof(int16_t));
}
}
}
@ -491,7 +527,25 @@ int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra
}
}
static int srslte_pdsch_codeword_encode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_t *cfg,
static srslte_sequence_t *get_user_sequence(srslte_pdsch_t *q, uint16_t rnti,
uint32_t codeword_idx, uint32_t sf_idx, uint32_t len)
{
uint32_t rnti_idx = q->is_ue?0:rnti;
// The scrambling sequence is pregenerated for all RNTIs in the eNodeB but only for C-RNTI in the UE
if (q->users[rnti_idx] && q->users[rnti_idx]->sequence_generated &&
q->users[rnti_idx]->cell_id == q->cell.id &&
q->ue_rnti == rnti &&
((rnti >= SRSLTE_CRNTI_START && rnti < SRSLTE_CRNTI_END) || !q->is_ue))
{
return &q->users[rnti_idx]->seq[codeword_idx][sf_idx];
} else {
srslte_sequence_pdsch(&q->tmp_seq, rnti, codeword_idx, 2 * sf_idx, q->cell.id, len);
return &q->tmp_seq;
}
}
static int srslte_pdsch_codeword_encode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer, uint16_t rnti, uint8_t *data,
uint32_t codeword_idx) {
srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx];
@ -504,38 +558,28 @@ static int srslte_pdsch_codeword_encode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_
nbits->nof_re, nbits->nof_bits, rv);
/* Channel coding */
if (srslte_dlsch_encode2(&pdsch->dl_sch, cfg, softbuffer, data, pdsch->e[codeword_idx], codeword_idx)) {
if (srslte_dlsch_encode2(&q->dl_sch, cfg, softbuffer, data, q->e[codeword_idx], codeword_idx)) {
ERROR("Error encoding TB %d", codeword_idx);
return SRSLTE_ERROR;
}
/* Bit scrambling */
if (!pdsch->users[rnti]) {
srslte_sequence_t seq;
if (srslte_sequence_pdsch(&seq, rnti, codeword_idx, 2 * cfg->sf_idx, pdsch->cell.id, nbits->nof_bits)) {
ERROR("Initialising scrambling sequence");
return SRSLTE_ERROR;
}
srslte_scrambling_bytes(&seq, (uint8_t *) pdsch->e[codeword_idx], nbits->nof_bits);
srslte_sequence_free(&seq);
/* Select scrambling sequence */
srslte_sequence_t *seq = get_user_sequence(q, rnti, codeword_idx, cfg->sf_idx, nbits->nof_bits);
} else {
srslte_scrambling_bytes(&pdsch->users[rnti]->seq[codeword_idx][cfg->sf_idx],
(uint8_t *) pdsch->e[codeword_idx],
nbits->nof_bits);
}
/* Bit scrambling */
srslte_scrambling_bytes(seq, (uint8_t *) q->e[codeword_idx], nbits->nof_bits);
/* Bit mapping */
srslte_mod_modulate_bytes(&pdsch->mod[mcs->mod],
(uint8_t *) pdsch->e[codeword_idx],
pdsch->d[codeword_idx], nbits->nof_bits);
srslte_mod_modulate_bytes(&q->mod[mcs->mod],
(uint8_t *) q->e[codeword_idx],
q->d[codeword_idx], nbits->nof_bits);
}
return SRSLTE_SUCCESS;
}
static int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_t *cfg,
static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data,
uint32_t codeword_idx, bool *ack) {
srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx];
@ -552,24 +596,16 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
* thus we don't need tot set it in the LLRs normalization
*/
srslte_demod_soft_demodulate_s(mcs->mod, pdsch->d[codeword_idx], pdsch->e[codeword_idx], nbits->nof_re);
srslte_demod_soft_demodulate_s(mcs->mod, q->d[codeword_idx], q->e[codeword_idx], nbits->nof_re);
if (pdsch->users[rnti] && pdsch->users[rnti]->sequence_generated) {
srslte_scrambling_s_offset(&pdsch->users[rnti]->seq[codeword_idx][cfg->sf_idx], pdsch->e[codeword_idx],
0, nbits->nof_bits);
} else {
srslte_sequence_t seq;
if (srslte_sequence_pdsch(&seq, rnti, codeword_idx, 2 * cfg->sf_idx, pdsch->cell.id, nbits->nof_bits)) {
ERROR("Initialising scrambling sequence");
return SRSLTE_ERROR;
}
srslte_scrambling_s_offset(&seq, pdsch->e[codeword_idx], 0, nbits->nof_bits);
srslte_sequence_free(&seq);
}
/* Select scrambling sequence */
srslte_sequence_t *seq = get_user_sequence(q, rnti, codeword_idx, cfg->sf_idx, nbits->nof_bits);
/* Return */
ret = srslte_dlsch_decode2(&pdsch->dl_sch, cfg, softbuffer, pdsch->e[codeword_idx], data, codeword_idx);
/* Bit scrambling */
srslte_scrambling_s_offset(seq, q->e[codeword_idx], 0, nbits->nof_bits);
/* Return */
ret = srslte_dlsch_decode2(&q->dl_sch, cfg, softbuffer, q->e[codeword_idx], data, codeword_idx);
if (ret == SRSLTE_SUCCESS) {
*ack = true;
} else if (ret == SRSLTE_ERROR) {
@ -666,7 +702,6 @@ int srslte_pdsch_decode(srslte_pdsch_t *q,
pdsch_decode_debug(q, cfg, sf_symbols, ce);
return SRSLTE_SUCCESS;
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}

@ -32,6 +32,7 @@
#include <stdbool.h>
#include <assert.h>
#include <math.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/phy/phch/regs.h"
#include "srslte/phy/phch/phich.h"
@ -67,37 +68,22 @@ void srslte_phich_reset(srslte_phich_t *q, cf_t *slot_symbols[SRSLTE_MAX_PORTS])
}
}
int srslte_phich_init(srslte_phich_t *q, srslte_regs_t *regs, srslte_cell_t cell)
{
return srslte_phich_init_multi(q, regs, cell, 1);
}
/** Initializes the phich channel receiver */
int srslte_phich_init_multi(srslte_phich_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas)
int srslte_phich_init(srslte_phich_t *q, uint32_t nof_rx_antennas)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
regs != NULL &&
srslte_cell_isvalid(&cell))
if (q != NULL)
{
bzero(q, sizeof(srslte_phich_t));
ret = SRSLTE_ERROR;
q->cell = cell;
q->regs = regs;
q->nof_rx_antennas = nof_rx_antennas;
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_BPSK)) {
goto clean;
}
for (int nsf = 0; nsf < SRSLTE_NSUBFRAMES_X_FRAME; nsf++) {
if (srslte_sequence_phich(&q->seq[nsf], 2 * nsf, q->cell.id)) {
goto clean;
}
}
ret = SRSLTE_SUCCESS;
}
clean:
@ -114,8 +100,33 @@ void srslte_phich_free(srslte_phich_t *q) {
srslte_modem_table_free(&q->mod);
bzero(q, sizeof(srslte_phich_t));
}
int srslte_phich_set_cell(srslte_phich_t *q, srslte_regs_t *regs, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
regs != NULL &&
srslte_cell_isvalid(&cell))
{
q->regs = regs;
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
for (int nsf = 0; nsf < SRSLTE_NSUBFRAMES_X_FRAME; nsf++) {
if (srslte_sequence_phich(&q->seq[nsf], 2 * nsf, q->cell.id)) {
return SRSLTE_ERROR;
}
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
/* Computes n_group and n_seq according to Section 9.1.2 in 36.213 */
void srslte_phich_calc(srslte_phich_t *q, uint32_t n_prb_lowest, uint32_t n_dmrs,

@ -26,6 +26,7 @@
#include <math.h>
#include <string.h>
#include <srslte/srslte.h>
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/phch/prach.h"
@ -61,6 +62,8 @@ uint32_t prach_Tseq[5] = {24576, 24576, 2*24576, 2*24576, 4096};
// Table 5.7.2-2 - N_cs values for unrestricted sets
uint32_t prach_Ncs_unrestricted[16] = {0,13,15,18,22,26,32,38,46,59,76,93,119,167,279,419};
#define MAX_N_zc 839
// Table 5.7.2-2 - N_cs values for restricted sets
uint32_t prach_Ncs_restricted[15] = {15,18,22,26,32,38,46,55,68,82,100,128,158,202,237};
@ -328,7 +331,10 @@ int srslte_prach_gen_seqs(srslte_prach_t *p)
int srslte_prach_init_cfg(srslte_prach_t *p, srslte_prach_cfg_t *cfg, uint32_t nof_prb)
{
return srslte_prach_init(p,
if (srslte_prach_init(p, srslte_symbol_sz(nof_prb))) {
return -1;
}
return srslte_prach_set_cell(p,
srslte_symbol_sz(nof_prb),
cfg->config_idx,
cfg->root_seq_idx,
@ -336,7 +342,69 @@ int srslte_prach_init_cfg(srslte_prach_t *p, srslte_prach_cfg_t *cfg, uint32_t n
cfg->zero_corr_zone);
}
int srslte_prach_init(srslte_prach_t *p,
int srslte_prach_init(srslte_prach_t *p, uint32_t max_N_ifft_ul)
{
int ret = SRSLTE_ERROR;
if(p != NULL &&
max_N_ifft_ul < 2049)
{
bzero(p, sizeof(srslte_prach_t));
p->max_N_ifft_ul = max_N_ifft_ul;
// Set up containers
p->prach_bins = srslte_vec_malloc(sizeof(cf_t)*MAX_N_zc);
p->corr_spec = srslte_vec_malloc(sizeof(cf_t)*MAX_N_zc);
p->corr = srslte_vec_malloc(sizeof(float)*MAX_N_zc);
// Set up ZC FFTS
if(srslte_dft_plan(&p->zc_fft, MAX_N_zc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){
return SRSLTE_ERROR;
}
srslte_dft_plan_set_mirror(&p->zc_fft, false);
srslte_dft_plan_set_norm(&p->zc_fft, true);
if(srslte_dft_plan(&p->zc_ifft, MAX_N_zc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)){
return SRSLTE_ERROR;
}
srslte_dft_plan_set_mirror(&p->zc_ifft, false);
srslte_dft_plan_set_norm(&p->zc_ifft, false);
uint32_t fft_size_alloc = max_N_ifft_ul * DELTA_F/DELTA_F_RA;
p->ifft_in = (cf_t*)srslte_vec_malloc(fft_size_alloc*sizeof(cf_t));
p->ifft_out = (cf_t*)srslte_vec_malloc(fft_size_alloc*sizeof(cf_t));
if(srslte_dft_plan(&p->ifft, fft_size_alloc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) {
fprintf(stderr, "Error creating DFT plan\n");
return -1;
}
srslte_dft_plan_set_mirror(&p->ifft, true);
srslte_dft_plan_set_norm(&p->ifft, true);
if(srslte_dft_plan(&p->fft, fft_size_alloc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){
fprintf(stderr, "Error creating DFT plan\n");
return -1;
}
p->signal_fft = srslte_vec_malloc(sizeof(cf_t)*fft_size_alloc);
if (!p->signal_fft) {
fprintf(stderr, "Error allocating memory\n");
return -1;
}
srslte_dft_plan_set_mirror(&p->fft, true);
srslte_dft_plan_set_norm(&p->fft, false);
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid parameters\n");
}
return ret;
}
int srslte_prach_set_cell(srslte_prach_t *p,
uint32_t N_ifft_ul,
uint32_t config_idx,
uint32_t root_seq_index,
@ -349,6 +417,11 @@ int srslte_prach_init(srslte_prach_t *p,
config_idx < 64 &&
root_seq_index < MAX_ROOTS)
{
if (N_ifft_ul > p->max_N_ifft_ul) {
fprintf(stderr, "PRACH: Error in set_cell(): N_ifft_ul must be lower or equal max_N_ifft_ul in init()\n");
return -1;
}
uint32_t preamble_format = srslte_prach_get_preamble_format(config_idx);
p->config_idx = config_idx;
p->f = preamble_format;
@ -368,7 +441,7 @@ int srslte_prach_init(srslte_prach_t *p,
return SRSLTE_ERROR;
}
}else{
p->N_zc = 839;
p->N_zc = MAX_N_zc;
if(p->hs){
if (p->zczc < 15) {
p->N_cs = prach_Ncs_restricted[p->zczc];
@ -386,25 +459,15 @@ int srslte_prach_init(srslte_prach_t *p,
}
}
// 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);
p->corr = srslte_vec_malloc(sizeof(float)*p->N_zc);
// Set up ZC FFTS
p->zc_fft = (srslte_dft_plan_t*)srslte_vec_malloc(sizeof(srslte_dft_plan_t));
if(srslte_dft_plan(p->zc_fft, p->N_zc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){
if (p->N_zc != MAX_N_zc) {
if(srslte_dft_replan(&p->zc_fft, p->N_zc)){
return SRSLTE_ERROR;
}
srslte_dft_plan_set_mirror(p->zc_fft, false);
srslte_dft_plan_set_norm(p->zc_fft, true);
p->zc_ifft = (srslte_dft_plan_t*)srslte_vec_malloc(sizeof(srslte_dft_plan_t));
if(srslte_dft_plan(p->zc_ifft, p->N_zc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)){
if(srslte_dft_replan(&p->zc_ifft, p->N_zc)){
return SRSLTE_ERROR;
}
srslte_dft_plan_set_mirror(p->zc_ifft, false);
srslte_dft_plan_set_norm(p->zc_ifft, false);
}
// Generate our 64 sequences
p->N_roots = 0;
@ -412,7 +475,7 @@ int srslte_prach_init(srslte_prach_t *p,
// Generate sequence FFTs
for(int i=0;i<N_SEQS;i++){
srslte_dft_run(p->zc_fft, p->seqs[i], p->dft_seqs[i]);
srslte_dft_run(&p->zc_fft, p->seqs[i], p->dft_seqs[i]);
}
// Create our FFT objects and buffers
@ -433,31 +496,15 @@ int srslte_prach_init(srslte_prach_t *p,
p->deadzone = (uint32_t) ceil((float) samp_rate/((float) p->N_zc*subcarrier_spacing));
}*/
p->ifft_in = (cf_t*)srslte_vec_malloc(p->N_ifft_prach*sizeof(cf_t));
p->ifft_out = (cf_t*)srslte_vec_malloc(p->N_ifft_prach*sizeof(cf_t));
p->ifft = (srslte_dft_plan_t*)srslte_vec_malloc(sizeof(srslte_dft_plan_t));
if(srslte_dft_plan(p->ifft, p->N_ifft_prach, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) {
if(srslte_dft_replan(&p->ifft, p->N_ifft_prach)) {
fprintf(stderr, "Error creating DFT plan\n");
return -1;
}
srslte_dft_plan_set_mirror(p->ifft, true);
srslte_dft_plan_set_norm(p->ifft, true);
p->fft = (srslte_dft_plan_t*)srslte_vec_malloc(sizeof(srslte_dft_plan_t));
if(srslte_dft_plan(p->fft, p->N_ifft_prach, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){
if(srslte_dft_replan(&p->fft, p->N_ifft_prach)){
fprintf(stderr, "Error creating DFT plan\n");
return -1;
}
p->signal_fft = srslte_vec_malloc(sizeof(cf_t)*p->N_ifft_prach);
if (!p->signal_fft) {
fprintf(stderr, "Error allocating memory\n");
return -1;
}
srslte_dft_plan_set_mirror(p->fft, true);
srslte_dft_plan_set_norm(p->fft, false);
p->N_seq = prach_Tseq[p->f]*p->N_ifft_ul/2048;
p->N_cp = prach_Tcp[p->f]*p->N_ifft_ul/2048;
p->T_seq = prach_Tseq[p->f]*SRSLTE_LTE_TS;
@ -500,7 +547,7 @@ int srslte_prach_gen(srslte_prach_t *p,
memcpy(&p->ifft_in[begin], p->dft_seqs[seq_index], p->N_zc * sizeof(cf_t));
memset(&p->ifft_in[begin+p->N_zc], 0, (p->N_ifft_prach - begin - p->N_zc) * sizeof(cf_t));
srslte_dft_run(p->ifft, p->ifft_in, p->ifft_out);
srslte_dft_run(&p->ifft, p->ifft_in, p->ifft_out);
// Copy CP into buffer
memcpy(signal, &p->ifft_out[p->N_ifft_prach-p->N_cp], p->N_cp*sizeof(cf_t));
@ -552,7 +599,7 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
}
// FFT incoming signal
srslte_dft_run(p->fft, signal, p->signal_fft);
srslte_dft_run(&p->fft, signal, p->signal_fft);
*n_indices = 0;
@ -569,7 +616,7 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
srslte_vec_prod_conj_ccc(p->prach_bins, root_spec, p->corr_spec, p->N_zc);
srslte_dft_run(p->zc_ifft, p->corr_spec, p->corr_spec);
srslte_dft_run(&p->zc_ifft, p->corr_spec, p->corr_spec);
srslte_vec_abs_square_cf(p->corr_spec, p->corr, p->N_zc);
@ -632,16 +679,12 @@ int srslte_prach_free(srslte_prach_t *p) {
free(p->prach_bins);
free(p->corr_spec);
free(p->corr);
srslte_dft_plan_free(p->ifft);
free(p->ifft);
srslte_dft_plan_free(&p->ifft);
free(p->ifft_in);
free(p->ifft_out);
srslte_dft_plan_free(p->fft);
free(p->fft);
srslte_dft_plan_free(p->zc_fft);
free(p->zc_fft);
srslte_dft_plan_free(p->zc_ifft);
free(p->zc_ifft);
srslte_dft_plan_free(&p->fft);
srslte_dft_plan_free(&p->zc_fft);
srslte_dft_plan_free(&p->zc_ifft);
if (p->signal_fft) {
free(p->signal_fft);

@ -416,33 +416,20 @@ void srslte_pucch_set_threshold(srslte_pucch_t *q, float format1_threshold) {
}
/** Initializes the PDCCH transmitter and receiver */
int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
int srslte_pucch_init(srslte_pucch_t *q) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell)) {
if (q != NULL) {
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_pucch_t));
q->cell = cell;
srslte_pucch_cfg_default(&q->pucch_cfg);
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
return SRSLTE_ERROR;
}
// Precompute group hopping values u.
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
return SRSLTE_ERROR;
}
if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) {
return SRSLTE_ERROR;
}
q->users = calloc(sizeof(srslte_pucch_user_t*), 1+SRSLTE_SIRNTI);
if (!q->users) {
perror("malloc");
return SRSLTE_ERROR;
goto clean_exit;
}
srslte_uci_cqi_pucch_init(&q->cqi);
@ -455,12 +442,16 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
ret = SRSLTE_SUCCESS;
}
clean_exit:
if (ret == SRSLTE_ERROR) {
srslte_pucch_free(q);
}
return ret;
}
void srslte_pucch_free(srslte_pucch_t *q) {
if (q->users) {
for (int rnti=0;rnti<SRSLTE_SIRNTI;rnti++) {
for (int rnti=0;rnti<=SRSLTE_SIRNTI;rnti++) {
srslte_pucch_clear_rnti(q, rnti);
}
free(q->users);
@ -480,6 +471,31 @@ void srslte_pucch_free(srslte_pucch_t *q) {
bzero(q, sizeof(srslte_pucch_t));
}
int srslte_pucch_set_cell(srslte_pucch_t *q, srslte_cell_t cell) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell)) {
srslte_pucch_cfg_default(&q->pucch_cfg);
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
// Precompute group hopping values u.
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
return SRSLTE_ERROR;
}
if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) {
return SRSLTE_ERROR;
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
void srslte_pucch_clear_rnti(srslte_pucch_t *q, uint16_t rnti) {
if (q->users[rnti]) {
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
@ -498,6 +514,7 @@ int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t rnti) {
// Precompute scrambling sequence for pucch format 2
if (srslte_sequence_pucch(&q->users[rnti]->seq_f2[sf_idx], rnti, 2*sf_idx, q->cell.id)) {
fprintf(stderr, "Error computing PUCCH Format 2 scrambling sequence\n");
srslte_pucch_clear_rnti(q, rnti);
return SRSLTE_ERROR;
}
}

@ -32,6 +32,8 @@
#include <stdbool.h>
#include <assert.h>
#include <math.h>
#include <srslte/srslte.h>
#include <srslte/phy/phch/pusch.h>
#include "srslte/phy/ch_estimation/refsignal_ul.h"
#include "srslte/phy/phch/pusch.h"
@ -185,22 +187,18 @@ int pusch_get(srslte_pusch_t *q, srslte_ra_ul_grant_t *grant, cf_t *input, cf_t
/** Initializes the PDCCH transmitter and receiver */
int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) {
int pusch_init(srslte_pusch_t *q, uint32_t max_prb, bool is_ue) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
int i;
if (q != NULL &&
srslte_cell_isvalid(&cell))
if (q != NULL)
{
bzero(q, sizeof(srslte_pusch_t));
ret = SRSLTE_ERROR;
q->max_re = max_prb * MAX_PUSCH_RE(SRSLTE_CP_NORM);
q->cell = cell;
q->max_re = q->cell.nof_prb * MAX_PUSCH_RE(q->cell.cp);
INFO("Init PUSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports,
q->cell.nof_prb, q->max_re);
INFO("Init PUSCH: %d PRBs\n", max_prb);
for (i = 0; i < 4; i++) {
if (srslte_modem_table_lte(&q->mod[i], modulations[i])) {
@ -209,21 +207,21 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) {
srslte_modem_table_bytes(&q->mod[i]);
}
q->users = calloc(sizeof(srslte_pusch_user_t*), 1+SRSLTE_SIRNTI);
q->is_ue = is_ue;
q->users = calloc(sizeof(srslte_pusch_user_t*), q->is_ue?1:(1+SRSLTE_SIRNTI));
if (!q->users) {
perror("malloc");
goto clean;
}
/* Precompute sequence for type2 frequency hopping */
if (srslte_sequence_LTE_pr(&q->seq_type2_fo, 210, q->cell.id)) {
fprintf(stderr, "Error initiating type2 frequency hopping sequence\n");
if (srslte_sequence_init(&q->tmp_seq, q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
goto clean;
}
srslte_sch_init(&q->ul_sch);
if (srslte_dft_precoding_init(&q->dft_precoding, cell.nof_prb)) {
if (srslte_dft_precoding_init(&q->dft_precoding, max_prb, is_ue)) {
fprintf(stderr, "Error initiating DFT transform precoding\n");
goto clean;
}
@ -244,10 +242,12 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) {
goto clean;
}
if (!q->is_ue) {
q->ce = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->ce) {
goto clean;
}
}
q->z = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->z) {
goto clean;
@ -262,6 +262,14 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) {
return ret;
}
int srslte_pusch_init_ue(srslte_pusch_t *q, uint32_t max_prb) {
return pusch_init(q, max_prb, true);
}
int srslte_pusch_init_enb(srslte_pusch_t *q, uint32_t max_prb) {
return pusch_init(q, max_prb, false);
}
void srslte_pusch_free(srslte_pusch_t *q) {
int i;
@ -284,13 +292,20 @@ void srslte_pusch_free(srslte_pusch_t *q) {
srslte_dft_precoding_free(&q->dft_precoding);
if (q->users) {
for (int rnti=0;rnti<SRSLTE_SIRNTI;rnti++) {
srslte_pusch_clear_rnti(q, rnti);
if (q->is_ue) {
srslte_pusch_free_rnti(q, 0);
} else {
for (int rnti=0;rnti<=SRSLTE_SIRNTI;rnti++) {
srslte_pusch_free_rnti(q, rnti);
}
}
free(q->users);
}
srslte_sequence_free(&q->seq_type2_fo);
srslte_sequence_free(&q->tmp_seq);
for (i = 0; i < 4; i++) {
srslte_modem_table_free(&q->mod[i]);
}
@ -300,6 +315,33 @@ void srslte_pusch_free(srslte_pusch_t *q) {
}
int srslte_pusch_set_cell(srslte_pusch_t *q, srslte_cell_t cell) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell))
{
q->max_re = cell.nof_prb * MAX_PUSCH_RE(q->cell.cp);
INFO("PUSCH: Cell config PCI=5d, %d ports %d PRBs, max_symbols: %d\n",
q->cell.id, q->cell.nof_ports, q->cell.nof_prb, q->max_re);
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
/* Precompute sequence for type2 frequency hopping */
if (srslte_sequence_LTE_pr(&q->seq_type2_fo, 210, q->cell.id)) {
fprintf(stderr, "Error initiating type2 frequency hopping sequence\n");
return SRSLTE_ERROR;
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
/* Configures the structure srslte_pusch_cfg_t from the UL DCI allocation dci_msg.
* If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant
*/
@ -392,28 +434,62 @@ int srslte_pusch_cfg(srslte_pusch_t *q,
int srslte_pusch_set_rnti(srslte_pusch_t *q, uint16_t rnti) {
uint32_t i;
if (!q->users[rnti]) {
q->users[rnti] = calloc(1, sizeof(srslte_pusch_user_t));
if (q->users[rnti]) {
uint32_t rnti_idx = q->is_ue?0:rnti;
if (!q->users[rnti_idx] || q->is_ue) {
if (!q->users[rnti_idx]) {
q->users[rnti_idx] = calloc(1, sizeof(srslte_pusch_user_t));
if (!q->users[rnti_idx]) {
perror("calloc");
return -1;
}
}
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
if (srslte_sequence_pusch(&q->users[rnti]->seq[i], rnti, 2 * i, q->cell.id,
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
if (srslte_sequence_pusch(&q->users[rnti_idx]->seq[i], rnti, 2 * i, q->cell.id,
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM)))
{
fprintf(stderr, "Error initializing PUSCH scrambling sequence\n");
srslte_pusch_free_rnti(q, rnti);
return SRSLTE_ERROR;
}
}
q->users[rnti]->sequences_generated = true;
}
q->ue_rnti = rnti;
q->users[rnti_idx]->cell_id = q->cell.id;
q->users[rnti_idx]->sequence_generated = true;
} else {
fprintf(stderr, "Error generating PUSCH sequence: rnti=0x%x already generated\n", rnti);
}
return SRSLTE_SUCCESS;
}
void srslte_pusch_clear_rnti(srslte_pusch_t *q, uint16_t rnti) {
if (q->users[rnti]) {
void srslte_pusch_free_rnti(srslte_pusch_t *q, uint16_t rnti) {
uint32_t rnti_idx = q->is_ue?0:rnti;
if (q->users[rnti_idx]) {
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
srslte_sequence_free(&q->users[rnti]->seq[i]);
srslte_sequence_free(&q->users[rnti_idx]->seq[i]);
}
free(q->users[rnti]);
q->users[rnti] = NULL;
free(q->users[rnti_idx]);
q->users[rnti_idx] = NULL;
q->ue_rnti = 0;
}
}
static srslte_sequence_t *get_user_sequence(srslte_pusch_t *q, uint16_t rnti, uint32_t sf_idx, uint32_t len)
{
uint32_t rnti_idx = q->is_ue?0:rnti;
// The scrambling sequence is pregenerated for all RNTIs in the eNodeB but only for C-RNTI in the UE
if (q->users[rnti_idx] && q->users[rnti_idx]->sequence_generated &&
q->users[rnti_idx]->cell_id == q->cell.id &&
q->ue_rnti == rnti &&
((rnti >= SRSLTE_CRNTI_START && rnti < SRSLTE_CRNTI_END) || !q->is_ue))
{
return &q->users[rnti_idx]->seq[sf_idx];
} else {
srslte_sequence_pusch(&q->tmp_seq, rnti, 2 * sf_idx, q->cell.id, len);
return &q->tmp_seq;
}
}
@ -445,16 +521,11 @@ int srslte_pusch_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softb
return SRSLTE_ERROR;
}
if (q->users[rnti] && q->users[rnti]->sequences_generated) {
srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t*) q->q, cfg->nbits.nof_bits);
} else {
srslte_sequence_t seq;
if (srslte_sequence_pusch(&seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
return SRSLTE_ERROR;
}
srslte_scrambling_bytes(&seq, (uint8_t*) q->q, cfg->nbits.nof_bits);
srslte_sequence_free(&seq);
}
// Generate scrambling sequence if not pre-generated
srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits);
// Run scrambling
srslte_scrambling_bytes(seq, (uint8_t*) q->q, cfg->nbits.nof_bits);
// Correct UCI placeholder/repetition bits
uint8_t *d = q->q;
@ -528,22 +599,13 @@ int srslte_pusch_decode(srslte_pusch_t *q,
srslte_predecoding_single(q->d, q->ce, q->z, cfg->nbits.nof_re, noise_estimate);
// DFT predecoding
srslte_dft_predecoding(&q->dft_precoding, q->z, q->d, cfg->grant.L_prb, cfg->nbits.nof_symb);
srslte_dft_precoding(&q->dft_precoding, q->z, q->d, cfg->grant.L_prb, cfg->nbits.nof_symb);
// Soft demodulation
srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->q, cfg->nbits.nof_re);
srslte_sequence_t *seq = NULL;
// Create sequence if does not exist
if (q->users[rnti] && q->users[rnti]->sequences_generated) {
seq = &q->users[rnti]->seq[cfg->sf_idx];
} else {
seq = &q->tmp_seq;
if (srslte_sequence_pusch(seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
return SRSLTE_ERROR;
}
}
// Generate scrambling sequence if not pre-generated
srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits);
// Decode RI/HARQ bits before descrambling
if (srslte_ulsch_uci_decode_ri_ack(&q->ul_sch, cfg, softbuffer, q->q, seq->c, uci_data)) {
@ -554,10 +616,6 @@ int srslte_pusch_decode(srslte_pusch_t *q,
// Descrambling
srslte_scrambling_s_offset(seq, q->q, 0, cfg->nbits.nof_bits);
if (!(q->users[rnti] && q->users[rnti]->sequences_generated)) {
srslte_sequence_free(seq);
}
return srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data);
} else {
return SRSLTE_ERROR_INVALID_INPUTS;

@ -33,7 +33,6 @@
* 36.211 6.6.1
*/
int srslte_sequence_pbch(srslte_sequence_t *seq, srslte_cp_t cp, uint32_t cell_id) {
bzero(seq, sizeof(srslte_sequence_t));
return srslte_sequence_LTE_pr(seq, SRSLTE_CP_ISNORM(cp)?1920:1728, cell_id);
}
@ -41,7 +40,6 @@ int srslte_sequence_pbch(srslte_sequence_t *seq, srslte_cp_t cp, uint32_t cell_i
* 36.211 6.7.1
*/
int srslte_sequence_pcfich(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_id) {
bzero(seq, sizeof(srslte_sequence_t));
return srslte_sequence_LTE_pr(seq, 32, (nslot/2+1) * (2*cell_id + 1) * 512 + cell_id);
}
@ -50,7 +48,6 @@ int srslte_sequence_pcfich(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell
* 36.211 6.9.1
*/
int srslte_sequence_phich(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_id) {
bzero(seq, sizeof(srslte_sequence_t));
return srslte_sequence_LTE_pr(seq, 12, (nslot/2+1) * (2*cell_id + 1) * 512 + cell_id);
}
@ -58,7 +55,6 @@ int srslte_sequence_phich(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_
* 36.211 6.8.2
*/
int srslte_sequence_pdcch(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_id, uint32_t len) {
bzero(seq, sizeof(srslte_sequence_t));
return srslte_sequence_LTE_pr(seq, len, (nslot/2) * 512 + cell_id);
}
@ -66,7 +62,6 @@ int srslte_sequence_pdcch(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_
* 36.211 6.3.1
*/
int srslte_sequence_pdsch(srslte_sequence_t *seq, uint16_t rnti, int q, uint32_t nslot, uint32_t cell_id, uint32_t len) {
bzero(seq, sizeof(srslte_sequence_t));
return srslte_sequence_LTE_pr(seq, len, (rnti<<14) + (q<<13) + ((nslot/2)<<9) + cell_id);
}
@ -74,7 +69,6 @@ int srslte_sequence_pdsch(srslte_sequence_t *seq, uint16_t rnti, int q, uint32_t
* 36.211 5.3.1
*/
int srslte_sequence_pusch(srslte_sequence_t *seq, uint16_t rnti, uint32_t nslot, uint32_t cell_id, uint32_t len) {
bzero(seq, sizeof(srslte_sequence_t));
return srslte_sequence_LTE_pr(seq, len, (rnti<<14) + ((nslot/2)<<9) + cell_id);
}
@ -82,6 +76,5 @@ int srslte_sequence_pusch(srslte_sequence_t *seq, uint16_t rnti, uint32_t nslot,
* 36.211 5.4.2
*/
int srslte_sequence_pucch(srslte_sequence_t *seq, uint16_t rnti, uint32_t nslot, uint32_t cell_id) {
bzero(seq, sizeof(srslte_sequence_t));
return srslte_sequence_LTE_pr(seq, 20, ((((nslot/2)+1)*(2*cell_id+1))<<16)+rnti);
}

@ -131,7 +131,11 @@ int base_init() {
return -1;
}
if (srslte_chest_dl_init(&chest, cell)) {
if (srslte_chest_dl_init(&chest, cell.nof_prb)) {
fprintf(stderr, "Error initializing equalizer\n");
return -1;
}
if (srslte_chest_dl_set_cell(&chest, cell)) {
fprintf(stderr, "Error initializing equalizer\n");
return -1;
}
@ -141,7 +145,11 @@ int base_init() {
return -1;
}
if (srslte_pbch_init(&pbch, cell)) {
if (srslte_pbch_init(&pbch)) {
fprintf(stderr, "Error initiating PBCH\n");
return -1;
}
if (srslte_pbch_set_cell(&pbch, cell)) {
fprintf(stderr, "Error initiating PBCH\n");
return -1;
}

@ -104,7 +104,11 @@ int main(int argc, char **argv) {
}
}
if (srslte_pbch_init(&pbch, cell)) {
if (srslte_pbch_init(&pbch)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
if (srslte_pbch_set_cell(&pbch, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}

@ -142,7 +142,11 @@ int base_init() {
}
}
if (srslte_chest_dl_init(&chest, cell)) {
if (srslte_chest_dl_init(&chest, cell.nof_prb)) {
fprintf(stderr, "Error initializing equalizer\n");
return -1;
}
if (srslte_chest_dl_set_cell(&chest, cell)) {
fprintf(stderr, "Error initializing equalizer\n");
return -1;
}
@ -157,7 +161,11 @@ int base_init() {
return -1;
}
if (srslte_pcfich_init(&pcfich, &regs, cell)) {
if (srslte_pcfich_init(&pcfich, 1)) {
fprintf(stderr, "Error creating PBCH object\n");
return -1;
}
if (srslte_pcfich_set_cell(&pcfich, &regs, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
return -1;
}

@ -124,7 +124,11 @@ int main(int argc, char **argv) {
exit(-1);
}
if (srslte_pcfich_init(&pcfich, &regs, cell)) {
if (srslte_pcfich_init(&pcfich, 1)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
if (srslte_pcfich_set_cell(&pcfich, &regs, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}

@ -148,7 +148,11 @@ int base_init() {
}
}
if (srslte_chest_dl_init(&chest, cell)) {
if (srslte_chest_dl_init(&chest, cell.nof_prb)) {
fprintf(stderr, "Error initializing equalizer\n");
return -1;
}
if (srslte_chest_dl_set_cell(&chest, cell)) {
fprintf(stderr, "Error initializing equalizer\n");
return -1;
}
@ -167,7 +171,11 @@ int base_init() {
fprintf(stderr, "Error setting CFI %d\n", cfi);
return -1;
}
if (srslte_pdcch_init(&pdcch, &regs, cell)) {
if (srslte_pdcch_init_ue(&pdcch, cell.nof_prb, 1)) {
fprintf(stderr, "Error creating PDCCH object\n");
exit(-1);
}
if (srslte_pdcch_set_cell(&pdcch, &regs, cell)) {
fprintf(stderr, "Error creating PDCCH object\n");
exit(-1);
}

@ -204,15 +204,23 @@ int main(int argc, char **argv) {
exit(-1);
}
if (srslte_pdcch_init_tx(&pdcch_tx, &regs, cell)) {
if (srslte_pdcch_init_enb(&pdcch_tx, cell.nof_prb)) {
fprintf(stderr, "Error creating PDCCH object\n");
exit(-1);
}
if (srslte_pdcch_set_cell(&pdcch_tx, &regs, cell)) {
fprintf(stderr, "Error setting cell in PDCCH object\n");
exit(-1);
}
if (srslte_pdcch_init_rx(&pdcch_rx, &regs, cell, nof_rx_ant)) {
if (srslte_pdcch_init_ue(&pdcch_rx, cell.nof_prb, nof_rx_ant)) {
fprintf(stderr, "Error creating PDCCH object\n");
exit(-1);
}
if (srslte_pdcch_set_cell(&pdcch_rx, &regs, cell)) {
fprintf(stderr, "Error setting cell in PDCCH object\n");
exit(-1);
}
/* Resource allocate init */
nof_dcis = 0;

@ -137,7 +137,11 @@ int base_init() {
exit(-1);
}
if (srslte_ue_dl_init(&ue_dl, cell, 1)) {
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) {
fprintf(stderr, "Error initializing UE DL\n");
return -1;
}
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
fprintf(stderr, "Error initializing UE DL\n");
return -1;
}

@ -153,7 +153,7 @@ int main(int argc, char **argv) {
int ret = -1;
struct timeval t[3];
srslte_softbuffer_tx_t *softbuffers_tx[SRSLTE_MAX_CODEWORDS];
int M=10;
int M=1;
bool acks[SRSLTE_MAX_CODEWORDS] = {false};
parse_args(argc,argv);
@ -213,8 +213,6 @@ int main(int argc, char **argv) {
return ret;
}
#ifdef DO_OFDM
srslte_ofdm_tx_init(&ofdm_tx, cell.cp, cell.nof_prb);
srslte_ofdm_rx_init(&ofdm_rx, cell.cp, cell.nof_prb);
@ -276,7 +274,11 @@ int main(int argc, char **argv) {
}
}
if (srslte_pdsch_init_rx(&pdsch_rx, cell, nof_rx_antennas)) {
if (srslte_pdsch_init_ue(&pdsch_rx, cell.nof_prb, nof_rx_antennas)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto quit;
}
if (srslte_pdsch_set_cell(&pdsch_rx, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto quit;
}
@ -334,17 +336,25 @@ int main(int argc, char **argv) {
#endif
srslte_chest_dl_t chest;
if (srslte_chest_dl_init(&chest, cell)) {
if (srslte_chest_dl_init(&chest, cell.nof_prb)) {
fprintf(stderr, "Error initializing equalizer\n");
exit(-1);
}
if (srslte_chest_dl_set_cell(&chest, cell)) {
printf("Error initializing equalizer\n");
exit(-1);
}
srslte_chest_dl_estimate(&chest, rx_slot_symbols[0], ce[0], subframe);
srslte_chest_dl_free(&chest);
srslte_filesource_free(&fsrc);
} else {
if (srslte_pdsch_init_tx(&pdsch_tx, cell)) {
if (srslte_pdsch_init_enb(&pdsch_tx, cell.nof_prb)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto quit;
}
if (srslte_pdsch_set_cell(&pdsch_tx, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto quit;
}

@ -29,6 +29,7 @@
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/srslte.h"
@ -165,7 +166,11 @@ int base_init() {
}
}
if (srslte_chest_dl_init(&chest, cell)) {
if (srslte_chest_dl_init(&chest, cell.nof_prb)) {
fprintf(stderr, "Error initializing equalizer\n");
return -1;
}
if (srslte_chest_dl_set_cell(&chest, cell)) {
fprintf(stderr, "Error initializing equalizer\n");
return -1;
}
@ -180,7 +185,11 @@ int base_init() {
return -1;
}
if (srslte_phich_init(&phich, &regs, cell)) {
if (srslte_phich_init(&phich, 1)) {
fprintf(stderr, "Error creating PBCH object\n");
return -1;
}
if (srslte_phich_set_cell(&phich, &regs, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
return -1;
}

@ -142,6 +142,10 @@ int main(int argc, char **argv) {
cid = cell.id;
max_cid = cell.id;
}
if (srslte_phich_init(&phich, 1)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
while(cid <= max_cid) {
cell.id = cid;
@ -152,7 +156,7 @@ int main(int argc, char **argv) {
exit(-1);
}
if (srslte_phich_init(&phich, &regs, cell)) {
if (srslte_phich_set_cell(&phich, &regs, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
@ -198,10 +202,10 @@ int main(int argc, char **argv) {
}
}
}
srslte_phich_free(&phich);
srslte_regs_free(&regs);
cid++;
}
srslte_phich_free(&phich);
for (i=0;i<SRSLTE_MAX_PORTS;i++) {
free(ce[i]);

@ -85,7 +85,9 @@ int main(int argc, char **argv) {
cf_t preamble[MAX_LEN];
memset(preamble, 0, sizeof(cf_t)*MAX_LEN);
srslte_prach_init(p,
srslte_prach_init(p, N_ifft_ul);
srslte_prach_set_cell( p,
N_ifft_ul,
config_idx,
root_seq_idx,

@ -90,7 +90,9 @@ int main(int argc, char **argv) {
cf_t preamble_sum[MAX_LEN];
memset(preamble_sum, 0, sizeof(cf_t)*MAX_LEN);
srslte_prach_init(p,
srslte_prach_init(p, N_ifft_ul);
srslte_prach_set_cell( p,
N_ifft_ul,
preamble_format,
root_seq_idx,

@ -133,6 +133,9 @@ int main(int argc, char **argv) {
memset(preamble, 0, sizeof(cf_t)*MAX_LEN);
srslte_prach_init(p,
srslte_symbol_sz(nof_prb));
srslte_prach_set_cell(p,
srslte_symbol_sz(nof_prb),
preamble_format,
root_seq_idx,

@ -87,11 +87,19 @@ int main(int argc, char **argv) {
parse_args(argc,argv);
if (srslte_pucch_init(&pucch, cell)) {
if (srslte_pucch_init(&pucch)) {
fprintf(stderr, "Error creating PDSCH object\n");
exit(-1);
}
if (srslte_refsignal_ul_init(&dmrs, cell)) {
if (srslte_pucch_set_cell(&pucch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
exit(-1);
}
if (srslte_refsignal_ul_init(&dmrs, cell.nof_prb)) {
fprintf(stderr, "Error creating PDSCH object\n");
exit(-1);
}
if (srslte_refsignal_ul_set_cell(&dmrs, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
exit(-1);
}

@ -110,7 +110,8 @@ void parse_args(int argc, char **argv) {
}
int main(int argc, char **argv) {
srslte_pusch_t pusch;
srslte_pusch_t pusch_tx;
srslte_pusch_t pusch_rx;
uint8_t *data = NULL;
cf_t *sf_symbols = NULL;
cf_t *ce = NULL;
@ -145,8 +146,20 @@ int main(int argc, char **argv) {
ul_hopping.hopping_offset = 0;
ul_hopping.hop_mode = SRSLTE_PUSCH_HOP_MODE_INTER_SF;
if (srslte_pusch_init(&pusch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
if (srslte_pusch_init_ue(&pusch_tx, cell.nof_prb)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto quit;
}
if (srslte_pusch_set_cell(&pusch_tx, cell)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto quit;
}
if (srslte_pusch_init_enb(&pusch_rx, cell.nof_prb)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto quit;
}
if (srslte_pusch_set_cell(&pusch_rx, cell)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto quit;
}
@ -159,13 +172,18 @@ int main(int argc, char **argv) {
uci_cfg.I_offset_ri = 2;
uci_cfg.I_offset_ack = 4;
if (srslte_pusch_cfg(&pusch, &cfg, &grant, &uci_cfg, &ul_hopping, NULL, subframe, 0, 0)) {
if (srslte_pusch_cfg(&pusch_tx, &cfg, &grant, &uci_cfg, &ul_hopping, NULL, subframe, 0, 0)) {
fprintf(stderr, "Error configuring PDSCH\n");
exit(-1);
}
if (srslte_pusch_cfg(&pusch_rx, &cfg, &grant, &uci_cfg, &ul_hopping, NULL, subframe, 0, 0)) {
fprintf(stderr, "Error configuring PDSCH\n");
exit(-1);
}
uint16_t rnti = 1234;
srslte_pusch_set_rnti(&pusch, rnti);
srslte_pusch_set_rnti(&pusch_tx, rnti);
srslte_pusch_set_rnti(&pusch_rx, rnti);
srslte_uci_data_t uci_data_tx;
srslte_uci_data_t uci_data_rx;
@ -212,13 +230,13 @@ int main(int argc, char **argv) {
uint32_t ntrials = 100;
if (srslte_pusch_encode(&pusch, &cfg, &softbuffer_tx, data, uci_data_tx, rnti, sf_symbols)) {
if (srslte_pusch_encode(&pusch_tx, &cfg, &softbuffer_tx, data, uci_data_tx, rnti, sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
exit(-1);
}
if (rv_idx > 0) {
cfg.rv = rv_idx;
if (srslte_pusch_encode(&pusch, &cfg, &softbuffer_tx, data, uci_data_tx, rnti, sf_symbols)) {
if (srslte_pusch_encode(&pusch_tx, &cfg, &softbuffer_tx, data, uci_data_tx, rnti, sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
exit(-1);
}
@ -234,7 +252,7 @@ int main(int argc, char **argv) {
}
gettimeofday(&t[1], NULL);
int r = srslte_pusch_decode(&pusch, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, &uci_data_rx);
int r = srslte_pusch_decode(&pusch_rx, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, &uci_data_rx);
gettimeofday(&t[2], NULL);
get_time_interval(t);
if (r) {
@ -274,7 +292,8 @@ int main(int argc, char **argv) {
}
quit:
srslte_pusch_free(&pusch);
srslte_pusch_free(&pusch_tx);
srslte_pusch_free(&pusch_rx);
srslte_softbuffer_tx_free(&softbuffer_tx);
if (sf_symbols) {

@ -28,6 +28,7 @@
#include <math.h>
#include <stdlib.h>
#include <strings.h>
#include <srslte/srslte.h>
#include "srslte/phy/resampling/interp.h"
#include "srslte/phy/utils/vector.h"
@ -109,10 +110,22 @@ int srslte_interp_linear_vector_init(srslte_interp_linsrslte_vec_t *q, uint32_t
return SRSLTE_ERROR;
}
q->vector_len = vector_len;
q->max_vector_len = vector_len;
}
return ret;
}
int srslte_interp_linear_vector_resize(srslte_interp_linsrslte_vec_t *q, uint32_t vector_len)
{
if (vector_len <= q->max_vector_len) {
q->vector_len = vector_len;
return SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Error resizing interp_linear: vector_len must be lower or equal than initialized\n");
return SRSLTE_ERROR;
}
}
void srslte_interp_linear_vector_free(srslte_interp_linsrslte_vec_t *q) {
if (q->diff_vec) {
free(q->diff_vec);
@ -190,6 +203,8 @@ int srslte_interp_linear_init(srslte_interp_lin_t *q, uint32_t vector_len, uint3
q->vector_len = vector_len;
q->M = M;
q->max_vector_len = vector_len;
q->max_M = M;
}
return ret;
}
@ -209,6 +224,24 @@ void srslte_interp_linear_free(srslte_interp_lin_t *q) {
}
int srslte_interp_linear_resize(srslte_interp_lin_t *q, uint32_t vector_len, uint32_t M)
{
if (vector_len <= q->max_vector_len && M <= q->max_M) {
for (int i=0;i<M;i++) {
q->ramp[i] = (float) i;
}
q->vector_len = vector_len;
q->M = M;
return SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Error resizing interp_linear: vector_len and M must be lower or equal than initialized\n");
return SRSLTE_ERROR;
}
}
void srslte_interp_linear_offset(srslte_interp_lin_t *q, cf_t *input, cf_t *output,
uint32_t off_st, uint32_t off_end)
{

@ -117,6 +117,7 @@ static void* async_thread(void *h) {
return NULL;
}
}
uhd_async_metadata_free(&md);
return NULL;
}
@ -226,7 +227,7 @@ int rf_uhd_start_rx_stream(void *h)
.stream_now = false
};
uhd_usrp_get_time_now(handler->usrp, 0, &stream_cmd.time_spec_full_secs, &stream_cmd.time_spec_frac_secs);
stream_cmd.time_spec_frac_secs += 0.5;
stream_cmd.time_spec_frac_secs += 0.1;
if (stream_cmd.time_spec_frac_secs > 1) {
stream_cmd.time_spec_frac_secs -= 1;
stream_cmd.time_spec_full_secs += 1;
@ -457,15 +458,18 @@ int rf_uhd_close(void *h)
uhd_rx_metadata_free(&handler->rx_md_first);
uhd_rx_metadata_free(&handler->rx_md);
uhd_meta_range_free(&handler->rx_gain_range);
uhd_tx_streamer_free(&handler->tx_stream);
uhd_rx_streamer_free(&handler->rx_stream);
if (handler->has_rssi) {
uhd_sensor_value_free(&handler->rssi_value);
}
handler->async_thread_running = false;
pthread_join(handler->async_thread, NULL);
uhd_tx_streamer_free(&handler->tx_stream);
uhd_rx_streamer_free(&handler->rx_stream);
uhd_usrp_free(&handler->usrp);
free(handler);
/** Something else to close the USRP?? */
return 0;
}
@ -488,7 +492,6 @@ double rf_uhd_set_rx_srate(void *h, double freq)
for (int i=0;i<handler->nof_rx_channels;i++) {
uhd_usrp_set_rx_rate(handler->usrp, freq, i);
}
uhd_usrp_get_rx_rate(handler->usrp, 0, &freq);
return freq;
}
@ -498,7 +501,6 @@ double rf_uhd_set_tx_srate(void *h, double freq)
for (int i=0;i<handler->nof_tx_channels;i++) {
uhd_usrp_set_tx_rate(handler->usrp, freq, i);
}
uhd_usrp_get_tx_rate(handler->usrp, 0, &freq);
handler->tx_rate = freq;
return freq;
}
@ -509,7 +511,6 @@ double rf_uhd_set_rx_gain(void *h, double gain)
for (int i=0;i<handler->nof_rx_channels;i++) {
uhd_usrp_set_rx_gain(handler->usrp, gain, i, "");
}
uhd_usrp_get_rx_gain(handler->usrp, 0, "", &gain);
return gain;
}
@ -519,7 +520,6 @@ double rf_uhd_set_tx_gain(void *h, double gain)
for (int i=0;i<handler->nof_tx_channels;i++) {
uhd_usrp_set_tx_gain(handler->usrp, gain, i, "");
}
uhd_usrp_get_tx_gain(handler->usrp, 0, "", &gain);
return gain;
}
@ -551,7 +551,6 @@ double rf_uhd_set_rx_freq(void *h, double freq)
for (int i=0;i<handler->nof_rx_channels;i++) {
uhd_usrp_set_rx_freq(handler->usrp, &tune_request, i, &tune_result);
}
uhd_usrp_get_rx_freq(handler->usrp, 0, &freq);
return freq;
}
@ -567,7 +566,6 @@ double rf_uhd_set_tx_freq(void *h, double freq)
for (int i=0;i<handler->nof_tx_channels;i++) {
uhd_usrp_set_tx_freq(handler->usrp, &tune_request, i, &tune_result);
}
uhd_usrp_get_tx_freq(handler->usrp, 0, &freq);
return freq;
}
@ -629,6 +627,8 @@ int rf_uhd_recv_with_time_multi(void *h,
log_overflow(handler);
} else if (error_code == UHD_RX_METADATA_ERROR_CODE_LATE_COMMAND) {
log_late(handler);
} else if (error_code == UHD_RX_METADATA_ERROR_CODE_TIMEOUT) {
fprintf(stderr, "Error timed out while receiving asynchronoous messages from UHD.\n");
} else if (error_code != UHD_RX_METADATA_ERROR_CODE_NONE ) {
fprintf(stderr, "Error code 0x%x was returned during streaming. Aborting.\n", error_code);
}

@ -103,7 +103,12 @@ int rf_mib_decoder(srslte_rf_t *rf, uint32_t nof_rx_antennas,cell_search_cfg_t *
srslte_ue_mib_sync_t ue_mib;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
if (srslte_ue_mib_sync_init_multi(&ue_mib, cell->id, cell->cp, srslte_rf_recv_wrapper_cs, nof_rx_antennas, (void*) rf)) {
if (srslte_ue_mib_sync_init_multi(&ue_mib, srslte_rf_recv_wrapper_cs, nof_rx_antennas, (void*) rf)) {
fprintf(stderr, "Error initiating srslte_ue_mib_sync\n");
goto clean_exit;
}
if (srslte_ue_mib_sync_set_cell(&ue_mib, cell->id, cell->cp)) {
fprintf(stderr, "Error initiating srslte_ue_mib_sync\n");
goto clean_exit;
}
@ -168,7 +173,6 @@ int rf_cell_search(srslte_rf_t *rf, uint32_t nof_rx_antennas,
fprintf(stderr, "Error initiating UE cell detect\n");
return SRSLTE_ERROR;
}
if (config->nof_valid_pss_frames) {
srslte_ue_cellsearch_set_nof_valid_frames(&cs, config->nof_valid_pss_frames);
}

@ -33,29 +33,29 @@
#include "srslte/phy/scrambling/scrambling.h"
void srslte_scrambling_f(srslte_sequence_t *s, float *data) {
srslte_scrambling_f_offset(s, data, 0, s->len);
srslte_scrambling_f_offset(s, data, 0, s->cur_len);
}
void srslte_scrambling_f_offset(srslte_sequence_t *s, float *data, int offset, int len) {
assert (len + offset <= s->len);
assert (len + offset <= s->cur_len);
srslte_vec_prod_fff(data, &s->c_float[offset], data, len);
}
void srslte_scrambling_s(srslte_sequence_t *s, short *data) {
srslte_scrambling_s_offset(s, data, 0, s->len);
srslte_scrambling_s_offset(s, data, 0, s->cur_len);
}
void srslte_scrambling_s_offset(srslte_sequence_t *s, short *data, int offset, int len) {
assert (len + offset <= s->len);
assert (len + offset <= s->cur_len);
srslte_vec_prod_sss(data, &s->c_short[offset], data, len);
}
void srslte_scrambling_c(srslte_sequence_t *s, cf_t *data) {
srslte_scrambling_c_offset(s, data, 0, s->len);
srslte_scrambling_c_offset(s, data, 0, s->cur_len);
}
void srslte_scrambling_c_offset(srslte_sequence_t *s, cf_t *data, int offset, int len) {
assert (len + offset <= s->len);
assert (len + offset <= s->cur_len);
srslte_vec_prod_cfc(data, &s->c_float[offset], data, len);
}
@ -81,7 +81,7 @@ void scrambling_b_word(uint8_t *c, uint8_t *data, int len) {
void srslte_scrambling_b(srslte_sequence_t *s, uint8_t *data) {
scrambling_b_word(s->c, data, s->len);
scrambling_b_word(s->c, data, s->cur_len);
}
void srslte_scrambling_b_offset(srslte_sequence_t *s, uint8_t *data, int offset, int len) {

@ -84,8 +84,10 @@ void parse_args(int argc, char **argv) {
int init_sequence(srslte_sequence_t *seq, char *name) {
if (!strcmp(name, "PBCH")) {
bzero(seq, sizeof(srslte_sequence_t));
return srslte_sequence_pbch(seq, cp, cell_id);
} else if (!strcmp(name, "PDSCH")) {
bzero(seq, sizeof(srslte_sequence_t));
return srslte_sequence_pdsch(seq, 1234, 0, 0, cell_id, nof_bits);
} else {
fprintf(stderr, "Unsupported sequence name %s\n", name);
@ -109,18 +111,18 @@ int main(int argc, char **argv) {
}
if (!do_floats) {
input_b = malloc(sizeof(uint8_t) * seq.len);
input_b = malloc(sizeof(uint8_t) * seq.cur_len);
if (!input_b) {
perror("malloc");
exit(-1);
}
scrambled_b = malloc(sizeof(uint8_t) * seq.len);
scrambled_b = malloc(sizeof(uint8_t) * seq.cur_len);
if (!scrambled_b) {
perror("malloc");
exit(-1);
}
for (i=0;i<seq.len;i++) {
for (i=0;i<seq.cur_len;i++) {
input_b[i] = rand()%2;
scrambled_b[i] = input_b[i];
}
@ -131,9 +133,9 @@ int main(int argc, char **argv) {
srslte_scrambling_b(&seq, scrambled_b);
get_time_interval(t);
printf("Texec=%ld us for %d bits\n", t[0].tv_usec, seq.len);
printf("Texec=%ld us for %d bits\n", t[0].tv_usec, seq.cur_len);
for (i=0;i<seq.len;i++) {
for (i=0;i<seq.cur_len;i++) {
if (scrambled_b[i] != input_b[i]) {
printf("Error in %d\n", i);
exit(-1);
@ -142,18 +144,18 @@ int main(int argc, char **argv) {
free(input_b);
free(scrambled_b);
} else {
input_f = malloc(sizeof(float) * seq.len);
input_f = malloc(sizeof(float) * seq.cur_len);
if (!input_f) {
perror("malloc");
exit(-1);
}
scrambled_f = malloc(sizeof(float) * seq.len);
scrambled_f = malloc(sizeof(float) * seq.cur_len);
if (!scrambled_f) {
perror("malloc");
exit(-1);
}
for (i=0;i<seq.len;i++) {
for (i=0;i<seq.cur_len;i++) {
input_f[i] = 100*(rand()/RAND_MAX);
scrambled_f[i] = input_f[i];
}
@ -164,9 +166,9 @@ int main(int argc, char **argv) {
srslte_scrambling_f(&seq, scrambled_f);
get_time_interval(t);
printf("Texec=%ld us for %d bits\n", t[0].tv_usec, seq.len);
printf("Texec=%ld us for %d bits\n", t[0].tv_usec, seq.cur_len);
for (i=0;i<seq.len;i++) {
for (i=0;i<seq.cur_len;i++) {
if (scrambled_f[i] != input_f[i]) {
printf("Error in %d\n", i);
exit(-1);

@ -27,6 +27,7 @@
#include <strings.h>
#include <stdlib.h>
#include <math.h>
#include <srslte/srslte.h>
#include "srslte/phy/utils/cexptab.h"
#include "srslte/phy/sync/cfo.h"
@ -47,6 +48,7 @@ int srslte_cfo_init(srslte_cfo_t *h, uint32_t nsamples) {
h->tol = SRSLTE_CFO_TOLERANCE;
h->last_freq = 0;
h->nsamples = nsamples;
h->max_samples = nsamples;
srslte_cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, h->nsamples);
ret = SRSLTE_SUCCESS;
@ -69,14 +71,14 @@ void srslte_cfo_set_tol(srslte_cfo_t *h, float tol) {
h->tol = tol;
}
int srslte_cfo_realloc(srslte_cfo_t *h, uint32_t samples) {
h->cur_cexp = realloc(h->cur_cexp, sizeof(cf_t) * samples);
if (!h->cur_cexp) {
perror("realloc");
return SRSLTE_ERROR;
}
int srslte_cfo_resize(srslte_cfo_t *h, uint32_t samples) {
if (samples <= h->max_samples) {
srslte_cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, samples);
h->nsamples = samples;
} else {
fprintf(stderr, "Error in cfo_resize(): nof_samples must be lower than initialized\n");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}

@ -25,6 +25,7 @@
*/
#include <stdlib.h>
#include <srslte/srslte.h>
#include "srslte/phy/sync/cp.h"
#include "srslte/phy/utils/vector.h"
@ -33,6 +34,7 @@
int srslte_cp_synch_init(srslte_cp_synch_t *q, uint32_t symbol_sz)
{
q->symbol_sz = symbol_sz;
q->max_symbol_sz = symbol_sz;
q->corr = srslte_vec_malloc(sizeof(cf_t) * q->symbol_sz);
if (!q->corr) {
@ -49,6 +51,18 @@ void srslte_cp_synch_free(srslte_cp_synch_t *q)
}
}
int srslte_cp_synch_resize(srslte_cp_synch_t *q, uint32_t symbol_sz)
{
if (symbol_sz > q->max_symbol_sz) {
fprintf(stderr, "Error in cp_synch_resize(): symbol_sz must be lower than initialized\n");
return SRSLTE_ERROR;
}
q->symbol_sz = symbol_sz;
return SRSLTE_SUCCESS;
}
uint32_t srslte_cp_synch(srslte_cp_synch_t *q, cf_t *input, uint32_t max_offset, uint32_t nof_symbols, uint32_t cp_len)
{
if (max_offset > q->symbol_sz) {

@ -30,6 +30,7 @@
#include <stdlib.h>
#include <complex.h>
#include <math.h>
#include <srslte/phy/sync/pss.h>
#include "srslte/phy/sync/pss.h"
#include "srslte/phy/dft/dft.h"
@ -93,8 +94,10 @@ int srslte_pss_synch_init_fft_offset(srslte_pss_synch_t *q, uint32_t frame_size,
* It correlates a signal of frame_size samples with the PSS sequence in the frequency
* domain. The PSS sequence is transformed using fft_size samples.
*/
int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, uint32_t frame_size, uint32_t fft_size, int offset, int decimate) {
int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q,
uint32_t max_frame_size, uint32_t max_fft_size,
int offset, int decimate)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL) {
@ -108,17 +111,19 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, uint32_t frame
q->N_id_2 = 10;
q->ema_alpha = 0.2;
q->max_fft_size = max_fft_size;
q->max_frame_size = max_frame_size;
q->decimate = decimate;
fft_size = fft_size/q->decimate;
frame_size = frame_size/q->decimate;
uint32_t fft_size = max_fft_size/q->decimate;
uint32_t frame_size = max_frame_size/q->decimate;
q->fft_size = fft_size;
q->frame_size = frame_size;
buffer_size = fft_size + frame_size + 1;
if(q->decimate > 1)
{
if(q->decimate > 1) {
int filter_order = 3;
srslte_filt_decim_cc_init(&q->filter,q->decimate,filter_order);
q->filter.filter_output = srslte_vec_malloc((buffer_size) * sizeof(cf_t));
@ -175,7 +180,6 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, uint32_t frame
goto clean_and_exit;
}
bzero(&q->pss_signal_time[N_id_2][q->fft_size], q->frame_size * sizeof(cf_t));
}
#ifdef CONVOLUTION_FFT
@ -187,8 +191,7 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, uint32_t frame
fprintf(stderr, "Error initiating convolution FFT\n");
goto clean_and_exit;
}
for(int i =0; i< 3; i++)
{
for(int i=0; i<3; i++) {
srslte_dft_run_c(&q->conv_fft.filter_plan, q->pss_signal_time[i], q->pss_signal_freq_full[i]);
}
@ -208,6 +211,79 @@ clean_and_exit:
}
/* Initializes the PSS synchronization object.
*
* It correlates a signal of frame_size samples with the PSS sequence in the frequency
* domain. The PSS sequence is transformed using fft_size samples.
*/
int srslte_pss_synch_resize(srslte_pss_synch_t *q, uint32_t frame_size, uint32_t fft_size, int offset) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL) {
ret = SRSLTE_ERROR;
if (fft_size > q->max_fft_size || frame_size > q->max_frame_size) {
fprintf(stderr, "Error in pss_synch_config(): fft_size and frame_size must be lower than initialized\n");
return SRSLTE_ERROR;
}
uint32_t N_id_2;
uint32_t buffer_size;
q->N_id_2 = 10;
q->ema_alpha = 0.2;
fft_size = fft_size/q->decimate;
frame_size = frame_size/q->decimate;
q->fft_size = fft_size;
q->frame_size = frame_size;
buffer_size = fft_size + frame_size + 1;
if (srslte_dft_replan(&q->dftp_input, fft_size)) {
fprintf(stderr, "Error creating DFT plan \n");
return SRSLTE_ERROR;
}
bzero(&q->tmp_input[q->frame_size], q->fft_size * sizeof(cf_t));
bzero(q->conv_output, sizeof(cf_t) * buffer_size);
bzero(q->conv_output_avg, sizeof(float) * buffer_size);
#ifdef SRSLTE_PSS_ACCUMULATE_ABS
bzero(q->conv_output_abs, sizeof(float) * buffer_size);
#endif
// Generate PSS sequences for this FFT size
for (N_id_2=0;N_id_2<3;N_id_2++) {
if (srslte_pss_synch_init_N_id_2(q->pss_signal_freq[N_id_2], q->pss_signal_time[N_id_2], N_id_2, fft_size, offset)) {
fprintf(stderr, "Error initiating PSS detector for N_id_2=%d fft_size=%d\n", N_id_2, fft_size);
return SRSLTE_ERROR;
}
bzero(&q->pss_signal_time[N_id_2][q->fft_size], q->frame_size * sizeof(cf_t));
}
#ifdef CONVOLUTION_FFT
if (srslte_conv_fft_cc_replan(&q->conv_fft, frame_size, fft_size)) {
fprintf(stderr, "Error initiating convolution FFT\n");
return SRSLTE_ERROR;
}
for(int i =0; i< 3; i++) {
srslte_dft_run_c(&q->conv_fft.filter_plan, q->pss_signal_time[i], q->pss_signal_freq_full[i]);
}
#endif
srslte_pss_synch_reset(q);
ret = SRSLTE_SUCCESS;
}
return ret;
}
void srslte_pss_synch_free(srslte_pss_synch_t *q) {
uint32_t i;

@ -58,6 +58,7 @@ int srslte_sss_synch_init(srslte_sss_synch_t *q, uint32_t fft_size) {
srslte_dft_plan_set_dc(&q->dftp_input, true);
q->fft_size = fft_size;
q->max_fft_size = fft_size;
generate_N_id_1_table(q->N_id_1_table);
@ -71,19 +72,18 @@ int srslte_sss_synch_init(srslte_sss_synch_t *q, uint32_t fft_size) {
return SRSLTE_ERROR_INVALID_INPUTS;
}
int srslte_sss_synch_realloc(srslte_sss_synch_t *q, uint32_t fft_size) {
int srslte_sss_synch_resize(srslte_sss_synch_t *q, uint32_t fft_size) {
if (q != NULL &&
fft_size <= 2048)
{
srslte_dft_plan_free(&q->dftp_input);
if (srslte_dft_plan(&q->dftp_input, fft_size, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)) {
if (fft_size > q->max_fft_size) {
fprintf(stderr, "Error in sss_synch_resize(): fft_size must be lower than initialized\n");
return SRSLTE_ERROR;
}
if (srslte_dft_replan(&q->dftp_input, fft_size)) {
srslte_sss_synch_free(q);
return SRSLTE_ERROR;
}
srslte_dft_plan_set_mirror(&q->dftp_input, true);
srslte_dft_plan_set_norm(&q->dftp_input, true);
srslte_dft_plan_set_dc(&q->dftp_input, true);
q->fft_size = fft_size;
return SRSLTE_SUCCESS;
}

@ -28,6 +28,8 @@
#include <strings.h>
#include <complex.h>
#include <math.h>
#include <srslte/srslte.h>
#include <srslte/phy/sync/sync.h>
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/common/phy_common.h"
@ -39,6 +41,8 @@
#define CFO_EMA_ALPHA 0.1
#define CP_EMA_ALPHA 0.1
#define DEFAULT_CFO_TOL 50.0 // Hz
static bool fft_size_isvalid(uint32_t fft_size) {
if (fft_size >= SRSLTE_SYNC_FFT_SZ_MIN && fft_size <= SRSLTE_SYNC_FFT_SZ_MAX && (fft_size%64) == 0) {
return true;
@ -77,6 +81,9 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o
q->frame_size = frame_size;
q->max_offset = max_offset;
q->sss_alg = SSS_FULL;
q->max_frame_size = frame_size;
q->mean_cfo_isunset = true;
q->mean_cfo2_isunset = true;
q->enable_cfo_corr = true;
if (srslte_cfo_init(&q->cfocorr, q->frame_size)) {
@ -89,11 +96,8 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o
goto clean_exit;
}
// Set a CFO tolerance of approx 50 Hz
srslte_cfo_set_tol(&q->cfocorr, 50.0/(15000.0*q->fft_size));
// Set a CFO tolerance of approx 50 Hz
srslte_cfo_set_tol(&q->cfocorr2, 50.0/(15000.0*q->fft_size));
// Set default CFO tolerance
srslte_sync_set_cfo_tol(q, DEFAULT_CFO_TOL);
for (int i=0;i<2;i++) {
q->cfo_i_corr[i] = srslte_vec_malloc(sizeof(cf_t)*q->frame_size);
@ -111,9 +115,9 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o
srslte_sync_set_cp(q, SRSLTE_CP_NORM);
q->decimate = decimate;
if(!decimate)
if(!decimate) {
decimate = 1;
}
if (srslte_pss_synch_init_fft_offset_decim(&q->pss, max_offset, fft_size, 0, decimate)) {
fprintf(stderr, "Error initializing PSS object\n");
@ -162,6 +166,80 @@ void srslte_sync_free(srslte_sync_t *q) {
}
}
int srslte_sync_resize(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offset, uint32_t fft_size) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
frame_size <= 307200 &&
fft_size_isvalid(fft_size))
{
ret = SRSLTE_ERROR;
if (frame_size > q->max_frame_size) {
fprintf(stderr, "Error in sync_resize(): frame_size must be lower than initialized\n");
return SRSLTE_ERROR;
}
q->detect_cp = true;
q->sss_en = true;
q->mean_cfo = 0;
q->mean_cfo2 = 0;
q->N_id_2 = 1000;
q->N_id_1 = 1000;
q->cfo_i = 0;
q->find_cfo_i = false;
q->find_cfo_i_initiated = false;
q->cfo_ema_alpha = CFO_EMA_ALPHA;
q->fft_size = fft_size;
q->frame_size = frame_size;
q->max_offset = max_offset;
q->sss_alg = SSS_FULL;
q->enable_cfo_corr = true;
if (srslte_pss_synch_resize(&q->pss, max_offset, fft_size, 0)) {
fprintf(stderr, "Error resizing PSS object\n");
return SRSLTE_ERROR;
}
if (srslte_sss_synch_resize(&q->sss, fft_size)) {
fprintf(stderr, "Error resizing SSS object\n");
return SRSLTE_ERROR;
}
if (srslte_cp_synch_resize(&q->cp_synch, fft_size)) {
fprintf(stderr, "Error resizing CFO\n");
return SRSLTE_ERROR;
}
if (srslte_cfo_resize(&q->cfocorr, q->frame_size)) {
fprintf(stderr, "Error resizing CFO\n");
return SRSLTE_ERROR;
}
if (srslte_cfo_resize(&q->cfocorr2, q->frame_size)) {
fprintf(stderr, "Error resizing CFO\n");
return SRSLTE_ERROR;
}
// Update CFO tolerance
srslte_sync_set_cfo_tol(q, q->current_cfo_tol);
DEBUG("SYNC init with frame_size=%d, max_offset=%d and fft_size=%d\n", frame_size, max_offset, fft_size);
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid parameters frame_size: %d, fft_size: %d\n", frame_size, fft_size);
}
return ret;
}
void srslte_sync_set_cfo_tol(srslte_sync_t *q, float tol) {
q->current_cfo_tol = tol;
srslte_cfo_set_tol(&q->cfocorr, tol/(15000.0*q->fft_size));
srslte_cfo_set_tol(&q->cfocorr2, tol/(15000.0*q->fft_size));
}
void srslte_sync_set_threshold(srslte_sync_t *q, float threshold) {
q->threshold = threshold;
}
@ -218,6 +296,9 @@ float srslte_sync_get_cfo(srslte_sync_t *q) {
void srslte_sync_set_cfo(srslte_sync_t *q, float cfo) {
q->mean_cfo = cfo;
q->mean_cfo2 = cfo;
q->mean_cfo2_isunset = false;
q->mean_cfo_isunset = false;
}
void srslte_sync_set_cfo_i(srslte_sync_t *q, int cfo_i) {
@ -447,8 +528,13 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t
if (q->enable_cfo_corr) {
float cfo = cfo_estimate(q, input);
if (q->mean_cfo_isunset) {
q->mean_cfo = cfo;
q->mean_cfo_isunset = false;
} else {
/* compute exponential moving average CFO */
q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, q->cfo_ema_alpha);
}
/* Correct CFO with the averaged CFO estimation */
srslte_cfo_correct(&q->cfocorr2, input, q->temp, -q->mean_cfo / q->fft_size);
@ -504,7 +590,12 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t
if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) {
float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]);
if (q->mean_cfo2_isunset) {
q->mean_cfo2 = cfo2;
q->mean_cfo2_isunset = true;
} else {
q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha);
}
ret = SRSLTE_SYNC_FOUND;
} else {

@ -29,6 +29,7 @@
#include <strings.h>
#include <assert.h>
#include <unistd.h>
#include <srslte/srslte.h>
#include "srslte/phy/ue/ue_cell_search.h"
@ -51,7 +52,12 @@ int srslte_ue_cellsearch_init(srslte_ue_cellsearch_t * q, uint32_t max_frames,
cell.id = SRSLTE_CELL_ID_UNKNOWN;
cell.nof_prb = SRSLTE_CS_NOF_PRB;
if (srslte_ue_sync_init(&q->ue_sync, cell, recv_callback, stream_handler)) {
if (srslte_ue_sync_init(&q->ue_sync, cell.nof_prb, true, recv_callback, stream_handler)) {
fprintf(stderr, "Error initiating ue_sync\n");
goto clean_exit;
}
if (srslte_ue_sync_set_cell(&q->ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n");
goto clean_exit;
}
@ -105,7 +111,11 @@ int srslte_ue_cellsearch_init_multi(srslte_ue_cellsearch_t * q, uint32_t max_fra
cell.id = SRSLTE_CELL_ID_UNKNOWN;
cell.nof_prb = SRSLTE_CS_NOF_PRB;
if (srslte_ue_sync_init_multi(&q->ue_sync, cell, recv_callback, nof_rx_antennas, stream_handler)) {
if (srslte_ue_sync_init_multi(&q->ue_sync, cell.nof_prb, true, recv_callback, nof_rx_antennas, stream_handler)) {
fprintf(stderr, "Error initiating ue_sync\n");
goto clean_exit;
}
if (srslte_ue_sync_set_cell(&q->ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n");
goto clean_exit;
}
@ -243,6 +253,7 @@ int srslte_ue_cellsearch_scan(srslte_ue_cellsearch_t * q,
int ret = 0;
float max_peak_value = -1.0;
uint32_t nof_detected_cells = 0;
for (uint32_t N_id_2=0;N_id_2<3 && ret >= 0;N_id_2++) {
ret = srslte_ue_cellsearch_scan_N_id_2(q, N_id_2, &found_cells[N_id_2]);
if (ret < 0) {
@ -275,6 +286,10 @@ int srslte_ue_cellsearch_scan_N_id_2(srslte_ue_cellsearch_t * q,
{
ret = SRSLTE_SUCCESS;
bzero(q->candidates, sizeof(srslte_ue_cellsearch_result_t)*q->max_frames);
bzero(q->mode_ntimes, sizeof(uint32_t)*q->max_frames);
bzero(q->mode_counted, sizeof(uint8_t)*q->max_frames);
srslte_ue_sync_set_N_id_2(&q->ue_sync, N_id_2);
srslte_ue_sync_reset(&q->ue_sync);
do {

@ -27,6 +27,7 @@
#include "srslte/phy/ue/ue_dl.h"
#include <string.h>
#include <srslte/srslte.h>
#define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb)
@ -35,6 +36,7 @@
#define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define MAX_SFLEN_RE SRSLTE_SF_LEN_RE(max_prb, q->cell.cp)
const static srslte_dci_format_t ue_dci_formats[8][2] = {
/* Mode 1 */ {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1},
@ -51,57 +53,50 @@ static srslte_dci_format_t common_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FO
const uint32_t nof_common_formats = 2;
int srslte_ue_dl_init(srslte_ue_dl_t *q,
srslte_cell_t cell,
uint32_t max_prb,
uint32_t nof_rx_antennas)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
nof_rx_antennas <= SRSLTE_MAX_PORTS &&
srslte_cell_isvalid(&cell))
nof_rx_antennas <= SRSLTE_MAX_PORTS)
{
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_ue_dl_t));
q->cell = cell;
q->pkt_errors = 0;
q->pkts_total = 0;
q->pending_ul_dci_rnti = 0;
q->sample_offset = 0;
q->nof_rx_antennas = nof_rx_antennas;
if (srslte_ofdm_rx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) {
if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) {
fprintf(stderr, "Error initiating FFT\n");
goto clean_exit;
}
if (srslte_chest_dl_init(&q->chest, cell)) {
if (srslte_chest_dl_init(&q->chest, max_prb)) {
fprintf(stderr, "Error initiating channel estimator\n");
goto clean_exit;
}
if (srslte_regs_init(&q->regs, q->cell)) {
fprintf(stderr, "Error initiating REGs\n");
goto clean_exit;
}
if (srslte_pcfich_init_multi(&q->pcfich, &q->regs, q->cell, nof_rx_antennas)) {
if (srslte_pcfich_init(&q->pcfich, nof_rx_antennas)) {
fprintf(stderr, "Error creating PCFICH object\n");
goto clean_exit;
}
if (srslte_phich_init(&q->phich, &q->regs, q->cell)) {
if (srslte_phich_init(&q->phich, nof_rx_antennas)) {
fprintf(stderr, "Error creating PHICH object\n");
goto clean_exit;
}
if (srslte_pdcch_init_multi(&q->pdcch, &q->regs, q->cell, nof_rx_antennas)) {
if (srslte_pdcch_init_ue(&q->pdcch, max_prb, nof_rx_antennas)) {
fprintf(stderr, "Error creating PDCCH object\n");
goto clean_exit;
}
if (srslte_pdsch_init_rx(&q->pdsch, q->cell, nof_rx_antennas)) {
if (srslte_pdsch_init_ue(&q->pdsch, max_prb, nof_rx_antennas)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto clean_exit;
}
for (int i = 0; i < SRSLTE_MAX_TB; i++) {
q->softbuffers[i] = srslte_vec_malloc(sizeof(srslte_softbuffer_rx_t));
if (!q->softbuffers[i]) {
@ -109,25 +104,25 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
goto clean_exit;
}
if (srslte_softbuffer_rx_init(q->softbuffers[i], q->cell.nof_prb)) {
if (srslte_softbuffer_rx_init(q->softbuffers[i], max_prb)) {
fprintf(stderr, "Error initiating soft buffer\n");
goto clean_exit;
}
}
if (srslte_cfo_init(&q->sfo_correct, q->cell.nof_prb*SRSLTE_NRE)) {
if (srslte_cfo_init(&q->sfo_correct, max_prb*SRSLTE_NRE)) {
fprintf(stderr, "Error initiating SFO correct\n");
goto clean_exit;
}
srslte_cfo_set_tol(&q->sfo_correct, 1e-5f/q->fft.symbol_sz);
for (int j=0;j<nof_rx_antennas;j++) {
q->sf_symbols_m[j] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
q->sf_symbols_m[j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t));
if (!q->sf_symbols_m[j]) {
perror("malloc");
goto clean_exit;
}
for (uint32_t i=0;i<q->cell.nof_ports;i++) {
q->ce_m[i][j] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
for (uint32_t i=0;i<SRSLTE_MAX_PORTS;i++) {
q->ce_m[i][j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t));
if (!q->ce_m[i][j]) {
perror("malloc");
goto clean_exit;
@ -136,14 +131,13 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
}
q->sf_symbols = q->sf_symbols_m[0];
for (int i=0;i<q->cell.nof_ports;i++) {
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
q->ce[i] = q->ce_m[i][0];
}
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
fprintf(stderr, "Invalid parametres\n");
}
clean_exit:
@ -173,7 +167,7 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) {
if (q->sf_symbols_m[j]) {
free(q->sf_symbols_m[j]);
}
for (uint32_t i=0;i<q->cell.nof_ports;i++) {
for (uint32_t i=0;i<SRSLTE_MAX_PORTS;i++) {
if (q->ce_m[i][j]) {
free(q->ce_m[i][j]);
}
@ -183,11 +177,74 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) {
}
}
int srslte_ue_dl_set_cell(srslte_ue_dl_t *q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
q->pkt_errors = 0;
q->pkts_total = 0;
q->pending_ul_dci_rnti = 0;
q->sample_offset = 0;
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
if (q->cell.nof_prb != 0) {
srslte_regs_free(&q->regs);
}
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
if (srslte_regs_init(&q->regs, q->cell)) {
fprintf(stderr, "Error resizing REGs\n");
return SRSLTE_ERROR;
}
if (srslte_cfo_resize(&q->sfo_correct, q->cell.nof_prb*SRSLTE_NRE)) {
fprintf(stderr, "Error resizing SFO correct\n");
return SRSLTE_ERROR;
}
srslte_cfo_set_tol(&q->sfo_correct, 1e-5/q->fft.symbol_sz);
if (srslte_ofdm_rx_set_prb(&q->fft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error resizing FFT\n");
return SRSLTE_ERROR;
}
if (srslte_chest_dl_set_cell(&q->chest, q->cell)) {
fprintf(stderr, "Error resizing channel estimator\n");
return SRSLTE_ERROR;
}
if (srslte_pcfich_set_cell(&q->pcfich, &q->regs, q->cell)) {
fprintf(stderr, "Error resizing PCFICH object\n");
return SRSLTE_ERROR;
}
if (srslte_phich_set_cell(&q->phich, &q->regs, q->cell)) {
fprintf(stderr, "Error resizing PHICH object\n");
return SRSLTE_ERROR;
}
if (srslte_pdcch_set_cell(&q->pdcch, &q->regs, q->cell)) {
fprintf(stderr, "Error resizing PDCCH object\n");
return SRSLTE_ERROR;
}
if (srslte_pdsch_set_cell(&q->pdsch, q->cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
return SRSLTE_ERROR;
}
q->current_rnti = 0;
}
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
}
return ret;
}
/* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while
* to execute, so shall be called once the final C-RNTI has been allocated for the session.
* For the connection procedure, use srslte_pusch_encode_rnti() or srslte_pusch_decode_rnti() functions
*/
void srslte_ue_dl_set_rnti(srslte_ue_dl_t *q, uint16_t rnti) {
srslte_pdsch_set_rnti(&q->pdsch, rnti);
// Compute UE-specific and Common search space for this RNTI
@ -739,11 +796,11 @@ bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_pr
}
void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuffer, uint32_t tti, uint32_t rv_idx, uint16_t rnti, uint32_t cfi) {
srslte_vec_save_file("sf_symbols", q->sf_symbols_m, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
srslte_vec_save_file("sf_symbols", q->sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
printf("%d samples\n", SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp));
srslte_vec_save_file("ce0", q->ce_m[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
srslte_vec_save_file("ce0", q->ce[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
if (q->cell.nof_ports > 1) {
srslte_vec_save_file("ce1", q->ce_m[1], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
srslte_vec_save_file("ce1", q->ce[1], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
}
srslte_vec_save_file("pcfich_ce0", q->pcfich.ce[0], q->pcfich.nof_symbols*sizeof(cf_t));
srslte_vec_save_file("pcfich_ce1", q->pcfich.ce[1], q->pcfich.nof_symbols*sizeof(cf_t));

@ -36,45 +36,40 @@
#include "srslte/phy/utils/vector.h"
int srslte_ue_mib_init(srslte_ue_mib_t * q,
srslte_cell_t cell)
uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
cell.nof_ports <= SRSLTE_MAX_PORTS)
if (q != NULL)
{
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_ue_mib_t));
if (srslte_pbch_init(&q->pbch, cell)) {
if (srslte_pbch_init(&q->pbch)) {
fprintf(stderr, "Error initiating PBCH\n");
goto clean_exit;
}
if (cell.nof_ports == 0) {
cell.nof_ports = SRSLTE_MAX_PORTS;
}
q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->sf_symbols) {
perror("malloc");
goto clean_exit;
}
for (int i=0;i<cell.nof_ports;i++) {
q->ce[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
q->ce[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->ce[i]) {
perror("malloc");
goto clean_exit;
}
}
if (srslte_ofdm_rx_init(&q->fft, cell.cp, cell.nof_prb)) {
if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) {
fprintf(stderr, "Error initializing FFT\n");
goto clean_exit;
}
if (srslte_chest_dl_init(&q->chest, cell)) {
if (srslte_chest_dl_init(&q->chest, max_prb)) {
fprintf(stderr, "Error initializing reference signal\n");
goto clean_exit;
}
@ -109,6 +104,38 @@ void srslte_ue_mib_free(srslte_ue_mib_t * q)
}
int srslte_ue_mib_set_cell(srslte_ue_mib_t * q,
srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
cell.nof_ports <= SRSLTE_MAX_PORTS)
{
if (srslte_pbch_set_cell(&q->pbch, cell)) {
fprintf(stderr, "Error initiating PBCH\n");
return SRSLTE_ERROR;
}
if (srslte_ofdm_rx_set_prb(&q->fft, cell.cp, cell.nof_prb)) {
fprintf(stderr, "Error initializing FFT\n");
return SRSLTE_ERROR;
}
if (cell.nof_ports == 0) {
cell.nof_ports = SRSLTE_MAX_PORTS;
}
if (srslte_chest_dl_set_cell(&q->chest, cell)) {
fprintf(stderr, "Error initializing reference signal\n");
return SRSLTE_ERROR;
}
srslte_ue_mib_reset(q);
ret = SRSLTE_SUCCESS;
}
return ret;
}
void srslte_ue_mib_reset(srslte_ue_mib_t * q)
{
@ -142,7 +169,7 @@ int srslte_ue_mib_decode(srslte_ue_mib_t * q, cf_t *input,
/* Decode PBCH */
ret = srslte_pbch_decode(&q->pbch, &q->sf_symbols[SRSLTE_SLOT_LEN_RE(q->chest.cell.nof_prb, q->chest.cell.cp)],
ce_slot1, srslte_chest_dl_get_noise_estimate(&q->chest),
ce_slot1, 0,
bch_payload, nof_tx_ports, sfn_offset);
@ -161,27 +188,21 @@ int srslte_ue_mib_decode(srslte_ue_mib_t * q, cf_t *input,
return ret;
}
int srslte_ue_mib_sync_init(srslte_ue_mib_sync_t *q,
uint32_t cell_id,
srslte_cp_t cp,
int (recv_callback)(void*, void*, uint32_t, srslte_timestamp_t*),
int srslte_ue_mib_sync_init_multi(srslte_ue_mib_sync_t *q,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*),
uint32_t nof_rx_antennas,
void *stream_handler)
{
srslte_cell_t cell;
// If the ports are set to 0, ue_mib goes through 1, 2 and 4 ports to blindly detect nof_ports
cell.nof_ports = 0;
cell.id = cell_id;
cell.cp = cp;
cell.nof_prb = SRSLTE_UE_MIB_NOF_PRB;
q->sf_buffer[0] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
q->nof_rx_antennas = 1;
for (int i=0;i<nof_rx_antennas;i++) {
q->sf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(SRSLTE_UE_MIB_NOF_PRB));
}
q->nof_rx_antennas = nof_rx_antennas;
if (srslte_ue_mib_init(&q->ue_mib, cell)) {
if (srslte_ue_mib_init(&q->ue_mib, SRSLTE_UE_MIB_NOF_PRB)) {
fprintf(stderr, "Error initiating ue_mib\n");
return SRSLTE_ERROR;
}
if (srslte_ue_sync_init(&q->ue_sync, cell, recv_callback, stream_handler)) {
if (srslte_ue_sync_init_multi(&q->ue_sync, SRSLTE_UE_MIB_NOF_PRB, false, recv_callback, nof_rx_antennas, stream_handler)) {
fprintf(stderr, "Error initiating ue_sync\n");
srslte_ue_mib_free(&q->ue_mib);
return SRSLTE_ERROR;
@ -190,12 +211,9 @@ int srslte_ue_mib_sync_init(srslte_ue_mib_sync_t *q,
return SRSLTE_SUCCESS;
}
int srslte_ue_mib_sync_init_multi(srslte_ue_mib_sync_t *q,
int srslte_ue_mib_sync_set_cell(srslte_ue_mib_sync_t *q,
uint32_t cell_id,
srslte_cp_t cp,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*),
uint32_t nof_rx_antennas,
void *stream_handler)
srslte_cp_t cp)
{
srslte_cell_t cell;
// If the ports are set to 0, ue_mib goes through 1, 2 and 4 ports to blindly detect nof_ports
@ -204,24 +222,19 @@ int srslte_ue_mib_sync_init_multi(srslte_ue_mib_sync_t *q,
cell.cp = cp;
cell.nof_prb = SRSLTE_UE_MIB_NOF_PRB;
for (int i=0;i<nof_rx_antennas;i++) {
q->sf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
q->nof_rx_antennas = nof_rx_antennas;
if (srslte_ue_mib_init(&q->ue_mib, cell)) {
if (srslte_ue_mib_set_cell(&q->ue_mib, cell)) {
fprintf(stderr, "Error initiating ue_mib\n");
return SRSLTE_ERROR;
}
if (srslte_ue_sync_init_multi(&q->ue_sync, cell, recv_callback, nof_rx_antennas, stream_handler)) {
if (srslte_ue_sync_set_cell(&q->ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n");
srslte_ue_mib_free(&q->ue_mib);
return SRSLTE_ERROR;
}
srslte_ue_sync_decode_sss_on_track(&q->ue_sync, true);
return SRSLTE_SUCCESS;
}
void srslte_ue_mib_sync_free(srslte_ue_mib_sync_t *q) {
for (int i=0;i<q->nof_rx_antennas;i++) {
if (q->sf_buffer[i]) {
@ -248,6 +261,8 @@ int srslte_ue_mib_sync_decode(srslte_ue_mib_sync_t * q,
uint32_t nof_frames = 0;
int mib_ret = SRSLTE_UE_MIB_NOTFOUND;
srslte_ue_mib_sync_reset(q);
if (q != NULL)
{
ret = SRSLTE_SUCCESS;

@ -29,6 +29,7 @@
#include <strings.h>
#include <assert.h>
#include <unistd.h>
#include <srslte/srslte.h>
#include "srslte/phy/ue/ue_sync.h"
@ -128,29 +129,32 @@ int recv_callback_multi_to_single(void *h, cf_t *x[SRSLTE_MAX_PORTS], uint32_t n
}
int srslte_ue_sync_init(srslte_ue_sync_t *q,
srslte_cell_t cell,
uint32_t max_prb,
bool search_cell,
int (recv_callback)(void*, void*, uint32_t,srslte_timestamp_t*),
void *stream_handler)
{
int ret = srslte_ue_sync_init_multi(q, cell, recv_callback_multi_to_single, 1, (void*) q);
int ret = srslte_ue_sync_init_multi(q, max_prb, search_cell, recv_callback_multi_to_single, 1, (void*) q);
q->recv_callback_single = recv_callback;
q->stream_single = stream_handler;
return ret;
}
int srslte_ue_sync_init_multi(srslte_ue_sync_t *q,
srslte_cell_t cell,
uint32_t max_prb,
bool search_cell,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t,srslte_timestamp_t*),
uint32_t nof_rx_antennas,
void *stream_handler)
{
return srslte_ue_sync_init_multi_decim(q, cell,recv_callback ,nof_rx_antennas,stream_handler,1);
return srslte_ue_sync_init_multi_decim(q, max_prb,search_cell, recv_callback ,nof_rx_antennas,stream_handler,1);
}
int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
srslte_cell_t cell,
uint32_t max_prb,
bool search_cell,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t,srslte_timestamp_t*),
uint32_t nof_rx_antennas,
void *stream_handler,
@ -160,7 +164,6 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
if (q != NULL &&
stream_handler != NULL &&
srslte_nofprb_isvalid(cell.nof_prb) &&
nof_rx_antennas <= SRSLTE_MAX_PORTS &&
recv_callback != NULL)
{
@ -171,8 +174,7 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
q->stream = stream_handler;
q->recv_callback = recv_callback;
q->nof_rx_antennas = nof_rx_antennas;
q->cell = cell;
q->fft_size = srslte_symbol_sz(q->cell.nof_prb);
q->fft_size = srslte_symbol_sz(max_prb);
q->sf_len = SRSLTE_SF_LEN(q->fft_size);
q->file_mode = false;
q->correct_cfo = true;
@ -180,34 +182,31 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
q->sample_offset_correct_period = DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD;
q->sfo_ema = DEFAULT_SFO_EMA_COEFF;
if (cell.id == 1000) {
q->max_prb = max_prb;
if (search_cell) {
/* If the cell is unkown, we search PSS/SSS in 5 ms */
q->nof_recv_sf = 5;
q->decode_sss_on_track = true;
} else {
/* If the cell is known, we work on a 1ms basis */
q->nof_recv_sf = 1;
q->decode_sss_on_track = true;
}
q->frame_len = q->nof_recv_sf*q->sf_len;
if(q->fft_size < 700 && q->decimate)
{
if(q->fft_size < 700 && q->decimate) {
q->decimate = 1;
}
if(srslte_sync_init_decim(&q->sfind, q->frame_len, q->frame_len, q->fft_size,q->decimate)) {
fprintf(stderr, "Error initiating sync find\n");
goto clean_exit;
}
if (cell.id == 1000) {
if (search_cell) {
if(srslte_sync_init(&q->strack, q->frame_len, TRACK_FRAME_SIZE, q->fft_size)) {
fprintf(stderr, "Error initiating sync track\n");
goto clean_exit;
@ -219,6 +218,90 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
}
}
ret = SRSLTE_SUCCESS;
}
clean_exit:
if (ret == SRSLTE_ERROR) {
srslte_ue_sync_free(q);
}
return ret;
}
uint32_t srslte_ue_sync_sf_len(srslte_ue_sync_t *q) {
return q->frame_len;
}
void srslte_ue_sync_free(srslte_ue_sync_t *q) {
if (q->do_agc) {
srslte_agc_free(&q->agc);
}
if (!q->file_mode) {
srslte_sync_free(&q->sfind);
srslte_sync_free(&q->strack);
} else {
srslte_filesource_free(&q->file_source);
}
bzero(q, sizeof(srslte_ue_sync_t));
}
int srslte_ue_sync_set_cell(srslte_ue_sync_t *q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_nofprb_isvalid(cell.nof_prb))
{
ret = SRSLTE_ERROR;
if (cell.nof_prb > q->max_prb) {
fprintf(stderr, "Error in ue_sync_set_cell(): cell.nof_prb must be lower than initialized\n");
return SRSLTE_ERROR;
}
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
q->fft_size = srslte_symbol_sz(q->cell.nof_prb);
q->sf_len = SRSLTE_SF_LEN(q->fft_size);
q->agc_period = 0;
if (cell.id == 1000) {
/* If the cell is unkown, we search PSS/SSS in 5 ms */
q->nof_recv_sf = 5;
q->decode_sss_on_track = true;
} else {
/* If the cell is known, we work on a 1ms basis */
q->nof_recv_sf = 1;
q->decode_sss_on_track = true;
}
q->frame_len = q->nof_recv_sf*q->sf_len;
if(q->fft_size < 700 && q->decimate) {
q->decimate = 1;
}
if(srslte_sync_resize(&q->sfind, q->frame_len, q->frame_len, q->fft_size)) {
fprintf(stderr, "Error initiating sync find\n");
return SRSLTE_ERROR;
}
if (cell.id == 1000) {
if(srslte_sync_resize(&q->strack, q->frame_len, TRACK_FRAME_SIZE, q->fft_size)) {
fprintf(stderr, "Error initiating sync track\n");
return SRSLTE_ERROR;
}
} else {
if(srslte_sync_resize(&q->strack, q->frame_len, SRSLTE_CP_LEN_NORM(1,q->fft_size), q->fft_size)) {
fprintf(stderr, "Error initiating sync track\n");
return SRSLTE_ERROR;
}
}
if (cell.id == 1000) {
/* If the cell id is unknown, enable CP detection on find */
// FIXME: CP detection not working very well. Not supporting Extended CP right now
@ -264,29 +347,9 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
ret = SRSLTE_SUCCESS;
}
clean_exit:
if (ret == SRSLTE_ERROR) {
srslte_ue_sync_free(q);
}
return ret;
}
uint32_t srslte_ue_sync_sf_len(srslte_ue_sync_t *q) {
return q->frame_len;
}
void srslte_ue_sync_free(srslte_ue_sync_t *q) {
if (q->do_agc) {
srslte_agc_free(&q->agc);
}
if (!q->file_mode) {
srslte_sync_free(&q->sfind);
srslte_sync_free(&q->strack);
} else {
srslte_filesource_free(&q->file_source);
}
bzero(q, sizeof(srslte_ue_sync_t));
}
void srslte_ue_sync_get_last_timestamp(srslte_ue_sync_t *q, srslte_timestamp_t *timestamp) {
memcpy(timestamp, &q->last_timestamp, sizeof(srslte_timestamp_t));
@ -317,6 +380,8 @@ void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, float cfo) {
srslte_sync_set_cfo(&q->strack, cfo/15000);
}
void srslte_ue_sync_set_cfo_tol(srslte_ue_sync_t *q, float cfo_tol) {}
float srslte_ue_sync_get_sfo(srslte_ue_sync_t *q) {
return q->mean_sfo/5e-3;
}
@ -649,7 +714,7 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE
}
if (q->correct_cfo) {
for (int i=0;i<q->nof_rx_antennas;i++) {
srslte_cfo_correct(&q->sfind.cfocorr,
srslte_cfo_correct(&q->strack.cfocorr,
input_buffer[i],
input_buffer[i],
-srslte_sync_get_cfo(&q->strack) / q->fft_size);

@ -36,22 +36,22 @@
#define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define MAX_SFLEN SRSLTE_SF_LEN(srslte_symbol_sz(max_prb))
#define DEFAULT_CFO_TOL 50.0 // Hz
int srslte_ue_ul_init(srslte_ue_ul_t *q,
srslte_cell_t cell)
uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
if (q != NULL)
{
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_ue_ul_t));
q->cell = cell;
if (srslte_ofdm_tx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) {
if (srslte_ofdm_tx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) {
fprintf(stderr, "Error initiating FFT\n");
goto clean_exit;
}
@ -60,41 +60,41 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
q->normalize_en = false;
if (srslte_cfo_init(&q->cfo, CURRENT_SFLEN)) {
if (srslte_cfo_init(&q->cfo, MAX_SFLEN)) {
fprintf(stderr, "Error creating CFO object\n");
goto clean_exit;
}
srslte_cfo_set_tol(&q->cfo, 0);
srslte_ue_ul_set_cfo_tol(q, DEFAULT_CFO_TOL);
if (srslte_pusch_init(&q->pusch, q->cell)) {
if (srslte_pusch_init_ue(&q->pusch, max_prb)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit;
}
if (srslte_pucch_init(&q->pucch, q->cell)) {
if (srslte_pucch_init(&q->pucch)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit;
}
if (srslte_softbuffer_tx_init(&q->softbuffer, q->cell.nof_prb)) {
if (srslte_softbuffer_tx_init(&q->softbuffer, max_prb)) {
fprintf(stderr, "Error initiating soft buffer\n");
goto clean_exit;
}
if (srslte_refsignal_ul_init(&q->signals, cell)) {
if (srslte_refsignal_ul_init(&q->signals, max_prb)) {
fprintf(stderr, "Error initiating srslte_refsignal_ul\n");
goto clean_exit;
}
q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_PRB(max_prb) * sizeof(cf_t));
if (!q->sf_symbols) {
perror("malloc");
goto clean_exit;
}
q->refsignal = srslte_vec_malloc(2 * SRSLTE_NRE * q->cell.nof_prb * sizeof(cf_t));
q->refsignal = srslte_vec_malloc(2 * SRSLTE_NRE * max_prb * sizeof(cf_t));
if (!q->refsignal) {
perror("malloc");
goto clean_exit;
}
q->srs_signal = srslte_vec_malloc(SRSLTE_NRE * q->cell.nof_prb * sizeof(cf_t));
q->srs_signal = srslte_vec_malloc(SRSLTE_NRE * max_prb * sizeof(cf_t));
if (!q->srs_signal) {
perror("malloc");
goto clean_exit;
@ -102,8 +102,7 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
q->signals_pregenerated = false;
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
fprintf(stderr, "Invalid parameters\n");
}
clean_exit:
@ -115,7 +114,7 @@ clean_exit:
void srslte_ue_ul_free(srslte_ue_ul_t *q) {
if (q) {
srslte_ofdm_rx_free(&q->fft);
srslte_ofdm_tx_free(&q->fft);
srslte_pusch_free(&q->pusch);
srslte_pucch_free(&q->pucch);
srslte_softbuffer_tx_free(&q->softbuffer);
@ -140,6 +139,54 @@ void srslte_ue_ul_free(srslte_ue_ul_t *q) {
}
}
int srslte_ue_ul_set_cell(srslte_ue_ul_t *q,
srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell))
{
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
if (srslte_ofdm_tx_set_prb(&q->fft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error resizing FFT\n");
return SRSLTE_ERROR;
}
if (srslte_cfo_resize(&q->cfo, SRSLTE_SF_LEN_PRB(q->cell.nof_prb))) {
fprintf(stderr, "Error resizing CFO object\n");
return SRSLTE_ERROR;
}
srslte_ue_ul_set_cfo_tol(q, q->current_cfo_tol);
if (srslte_pusch_set_cell(&q->pusch, q->cell)) {
fprintf(stderr, "Error resizing PUSCH object\n");
return SRSLTE_ERROR;
}
if (srslte_pucch_set_cell(&q->pucch, q->cell)) {
fprintf(stderr, "Error resizing PUSCH object\n");
return SRSLTE_ERROR;
}
if (srslte_refsignal_ul_set_cell(&q->signals, q->cell)) {
fprintf(stderr, "Error resizing srslte_refsignal_ul\n");
return SRSLTE_ERROR;
}
q->signals_pregenerated = false;
}
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
}
return ret;
}
void srslte_ue_ul_set_cfo_tol(srslte_ue_ul_t *q, float tol) {
q->current_cfo_tol = tol;
srslte_cfo_set_tol(&q->cfo, tol/(15000.0*srslte_symbol_sz(q->cell.nof_prb)));
}
void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q, float cur_cfo) {
q->current_cfo = cur_cfo;
}
@ -154,7 +201,7 @@ void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q, bool enabled)
q->normalize_en = enabled;
}
/* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while
/* Precalculate the PUSCH scramble sequences for a given RNTI. This function takes a while
* to execute, so shall be called once the final C-RNTI has been allocated for the session.
* For the connection procedure, use srslte_pusch_encode_rnti() or srslte_pusch_decode_rnti() functions
*/

@ -36,7 +36,7 @@ int srslte_cexptab_init(srslte_cexptab_t *h, uint32_t size) {
uint32_t i;
h->size = size;
h->tab = malloc(sizeof(cf_t) * size);
h->tab = malloc(sizeof(cf_t) * (1+size));
if (h->tab) {
for (i = 0; i < size; i++) {
h->tab[i] = cexpf(_Complex_I * 2 * M_PI * (float) i / size);

@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
#include <srslte/srslte.h>
#include "srslte/phy/dft/dft.h"
#include "srslte/phy/utils/vector.h"
@ -34,14 +35,17 @@
int srslte_conv_fft_cc_init(srslte_conv_fft_cc_t *q, uint32_t input_len, uint32_t filter_len) {
bzero(q, sizeof(srslte_conv_fft_cc_t));
q->input_len = input_len;
q->filter_len = filter_len;
q->output_len = input_len+filter_len;
q->max_filter_len = filter_len;
q->max_input_len = input_len;
q->input_fft = srslte_vec_malloc(sizeof(cf_t)*q->output_len);
q->filter_fft = srslte_vec_malloc(sizeof(cf_t)*q->output_len);
q->output_fft = srslte_vec_malloc(sizeof(cf_t)*q->output_len);
if (!q->input_fft || !q->filter_fft || !q->output_fft) {
return SRSLTE_ERROR;
}
@ -64,6 +68,34 @@ int srslte_conv_fft_cc_init(srslte_conv_fft_cc_t *q, uint32_t input_len, uint32_
return SRSLTE_SUCCESS;
}
int srslte_conv_fft_cc_replan(srslte_conv_fft_cc_t *q, uint32_t input_len, uint32_t filter_len) {
if (input_len > q->max_input_len || filter_len > q->max_filter_len) {
fprintf(stderr, "Error in conv_fft_cc_replan(): input_len and filter_len must be lower than initialized\n");
return -1;
}
q->input_len = input_len;
q->filter_len = filter_len;
q->output_len = input_len+filter_len;
if (!q->input_fft || !q->filter_fft || !q->output_fft) {
return SRSLTE_ERROR;
}
if (srslte_dft_replan(&q->input_plan,q->output_len)) {
fprintf(stderr, "Error initiating input plan\n");
return SRSLTE_ERROR;
}
if (srslte_dft_replan(&q->filter_plan,q->output_len)) {
fprintf(stderr, "Error initiating filter plan\n");
return SRSLTE_ERROR;
}
if (srslte_dft_replan(&q->output_plan,q->output_len)) {
fprintf(stderr, "Error initiating output plan\n");
return SRSLTE_ERROR;
}
return SRSLTE_SUCCESS;
}
void srslte_conv_fft_cc_free(srslte_conv_fft_cc_t *q) {
if (q->input_fft) {
free(q->input_fft);

@ -250,9 +250,13 @@ void radio::save_trace(uint32_t is_eob, srslte_timestamp_t *tx_time) {
}
}
void radio::set_rx_freq(float freq)
void radio::set_freq_offset(double freq) {
freq_offset = freq;
}
void radio::set_rx_freq(double freq)
{
rx_freq = srslte_rf_set_rx_freq(&rf_device, freq);
rx_freq = srslte_rf_set_rx_freq(&rf_device, freq+freq_offset);
}
void radio::set_rx_gain(float gain)
@ -265,19 +269,19 @@ double radio::set_rx_gain_th(float gain)
return srslte_rf_set_rx_gain_th(&rf_device, gain);
}
void radio::set_master_clock_rate(float rate)
void radio::set_master_clock_rate(double rate)
{
srslte_rf_set_master_clock_rate(&rf_device, rate);
}
void radio::set_rx_srate(float srate)
void radio::set_rx_srate(double srate)
{
srslte_rf_set_rx_srate(&rf_device, srate);
}
void radio::set_tx_freq(float freq)
void radio::set_tx_freq(double freq)
{
tx_freq = srslte_rf_set_tx_freq(&rf_device, freq);
tx_freq = srslte_rf_set_tx_freq(&rf_device, freq+freq_offset);
}
void radio::set_tx_gain(float gain)
@ -285,12 +289,12 @@ void radio::set_tx_gain(float gain)
srslte_rf_set_tx_gain(&rf_device, gain);
}
float radio::get_rx_freq()
double radio::get_rx_freq()
{
return rx_freq;
}
float radio::get_tx_freq()
double radio::get_tx_freq()
{
return tx_freq;
}
@ -305,7 +309,7 @@ float radio::get_rx_gain()
return srslte_rf_get_rx_gain(&rf_device);
}
void radio::set_tx_srate(float srate)
void radio::set_tx_srate(double srate)
{
cur_tx_srate = srslte_rf_set_tx_srate(&rf_device, srate);
burst_preamble_samples = (uint32_t) (cur_tx_srate * burst_preamble_sec);
@ -392,8 +396,6 @@ void radio::set_tx_srate(float srate)
// Calculate TX advance in seconds from samples and sampling rate
tx_adv_sec = nsamples/cur_tx_srate;
printf("Setting TX/RX offset %d samples, %.2f us\n", nsamples, tx_adv_sec*1e6);
}
void radio::start_rx()

@ -16,6 +16,8 @@ bool radio_multi::init_multi(uint32_t nof_rx_antennas, char* args, char* devname
cur_tx_srate = 0;
is_start_of_burst = true;
// Suppress radio stdout
srslte_rf_suppress_stdout(&rf_device);
tx_adv_auto = true;
// Set default preamble length each known device

@ -42,13 +42,14 @@ namespace srslte {
gw::gw()
:if_up(false)
{}
{
current_ip_addr = 0;
}
void gw::init(srsue::pdcp_interface_gw *pdcp_, srsue::rrc_interface_gw *rrc_, srsue::ue_interface *ue_, log *gw_log_, uint32_t lcid_)
void gw::init(srsue::pdcp_interface_gw *pdcp_, srsue::ue_interface *ue_, log *gw_log_, uint32_t lcid_)
{
pool = byte_buffer_pool::get_instance();
pdcp = pdcp_;
rrc = rrc_;
ue = ue_;
gw_log = gw_log_;
lcid = lcid_;
@ -78,6 +79,8 @@ void gw::stop()
thread_cancel();
}
wait_thread_finish();
current_ip_addr = 0;
}
// TODO: tear down TUN device?
@ -127,6 +130,7 @@ void gw::write_pdu(uint32_t lcid, byte_buffer_t *pdu)
*******************************************************************************/
error_t gw::setup_if_addr(uint32_t ip_addr, char *err_str)
{
if (ip_addr != current_ip_addr) {
if(!if_up)
{
if(init_if(err_str))
@ -157,8 +161,11 @@ error_t gw::setup_if_addr(uint32_t ip_addr, char *err_str)
return(ERROR_CANT_START);
}
current_ip_addr = ip_addr;
// Setup a thread to receive packets from the TUN device
start(GW_THREAD_PRIO);
}
return(ERROR_NONE);
}
@ -250,11 +257,6 @@ void gw::run_thread()
{
gw_log->info_hex(pdu->msg, pdu->N_bytes, "TX PDU");
while(run_enable && (!rrc->rrc_connected() || !rrc->have_drb())) {
rrc->rrc_connect();
usleep(1000);
}
if (!run_enable) {
break;
}

@ -138,18 +138,23 @@ typedef struct {
Main UE class
*******************************************************************************/
//#define LOG_STDOUT
class enb
:public enb_metrics_interface
{
:public enb_metrics_interface {
public:
static enb *get_instance(void);
static void cleanup(void);
bool init(all_args_t *args_);
void stop();
void start_plot();
static void rf_msg(srslte_rf_error_t error);
void handle_rf_msg(srslte_rf_error_t error);
// eNodeB metrics interface
@ -160,7 +165,9 @@ public:
private:
static enb *instance;
enb();
virtual ~enb();
srslte::radio radio;
@ -173,7 +180,11 @@ private:
srsenb::gtpu gtpu;
srsenb::s1ap s1ap;
#ifdef LOG_STDOUT
srslte::logger_stdout logger;
#else
srslte::logger_file logger;
#endif
srslte::log_filter rf_log;
std::vector<void*> phy_log;
srslte::log_filter mac_log;

@ -80,6 +80,7 @@ public:
************************************************************/
sched();
~sched();
void init(rrc_interface_mac *rrc, srslte::log *log);
void set_metric(metric_dl *dl_metric, metric_ul *ul_metric);

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save