Temporal commit before merge. Changed sequence objects to avoid reallocating memory. new NAS/RRC working with initial attachment

master
Ismael Gomez 7 years ago
parent c5bc3b11b7
commit e5feec1934

@ -95,6 +95,8 @@ else(POLARSSL_FOUND)
set(SEC_LIBRARIES "${MBEDTLS_LIBRARIES}") set(SEC_LIBRARIES "${MBEDTLS_LIBRARIES}")
endif(BUILD_STATIC) endif(BUILD_STATIC)
add_definitions(-DHAVE_MBEDTLS) add_definitions(-DHAVE_MBEDTLS)
else(MBEDTLS_FOUND)
message(FATAL_ERROR "Either PolarSSL or mbedTLS are required to build srsLTE")
endif (MBEDTLS_FOUND) endif (MBEDTLS_FOUND)
endif(POLARSSL_FOUND) endif(POLARSSL_FOUND)

@ -50,5 +50,5 @@ message(STATUS "MBEDTLS STATIC LIBRARIES: " ${MBEDTLS_STATIC_LIBRARIES})
message(STATUS "MBEDTLS INCLUDE DIRS: " ${MBEDTLS_INCLUDE_DIRS}) message(STATUS "MBEDTLS INCLUDE DIRS: " ${MBEDTLS_INCLUDE_DIRS})
INCLUDE(FindPackageHandleStandardArgs) INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MBEDTLS DEFAULT_MSG MBEDTLS_LIBRARIES MBEDTLS_STATIC_LIBRARIES MBEDTLS_INCLUDE_DIRS) FIND_PACKAGE_HANDLE_STANDARD_ARGS(MBEDTLS DEFAULT_MSG MBEDTLS_LIBRARIES MBEDTLS_INCLUDE_DIRS)
MARK_AS_ADVANCED(MBEDTLS_LIBRARIES MBEDTLS_STATIC_LIBRARIES MBEDTLS_INCLUDE_DIRS) MARK_AS_ADVANCED(MBEDTLS_LIBRARIES MBEDTLS_STATIC_LIBRARIES MBEDTLS_INCLUDE_DIRS)

@ -237,15 +237,27 @@ int main(int argc, char **argv) {
srslte_rf_stop_rx_stream(&rf); srslte_rf_stop_rx_stream(&rf);
srslte_rf_flush_buffer(&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"); fprintf(stderr, "Error initiating ue_sync\n");
return -1; return -1;
} }
if (srslte_ue_dl_init_multi(&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_multi(&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"); fprintf(stderr, "Error initiating UE downlink processing module\n");
return -1; 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"); fprintf(stderr, "Error initaiting UE MIB decoder\n");
return -1; return -1;
} }
@ -260,7 +272,11 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error initiating FFT\n"); fprintf(stderr, "Error initiating FFT\n");
return -1; 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"); fprintf(stderr, "Error initiating channel estimator\n");
return -1; return -1;
} }

@ -188,6 +188,18 @@ int main(int argc, char **argv) {
sigprocmask(SIG_UNBLOCK, &sigset, NULL); sigprocmask(SIG_UNBLOCK, &sigset, NULL);
signal(SIGINT, sig_int_handler); 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++) { for (freq=0;freq<nof_freqs && !go_exit;freq++) {
/* set rf_freq */ /* set rf_freq */
@ -204,25 +216,12 @@ int main(int argc, char **argv) {
bzero(found_cells, 3*sizeof(srslte_ue_cellsearch_result_t)); 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); 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); srslte_rf_set_rx_srate(&rf, SRSLTE_CS_SAMP_FREQ);
INFO("Starting receiver...\n", 0); INFO("Starting receiver...\n", 0);
srslte_rf_start_rx_stream(&rf); srslte_rf_start_rx_stream(&rf);
n = srslte_ue_cellsearch_scan(&cs, found_cells, NULL); n = srslte_ue_cellsearch_scan(&cs, found_cells, NULL);
srslte_ue_cellsearch_free(&cs);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error searching cell\n"); fprintf(stderr, "Error searching cell\n");
exit(-1); exit(-1);
@ -269,6 +268,7 @@ int main(int argc, char **argv) {
printf("\nBye\n"); printf("\nBye\n");
srslte_ue_cellsearch_free(&cs);
srslte_rf_close(&rf); srslte_rf_close(&rf);
exit(0); exit(0);
} }

@ -227,7 +227,11 @@ void base_init() {
exit(-1); exit(-1);
} }
srslte_ofdm_set_normalize(&ifft, true); 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"); fprintf(stderr, "Error creating PBCH object\n");
exit(-1); exit(-1);
} }
@ -237,7 +241,11 @@ void base_init() {
exit(-1); exit(-1);
} }
if (srslte_pcfich_init(&pcfich, &regs, cell)) { if (srslte_pcfich_init(&pcfich)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
if (srslte_pcfich_set_cell(&pcfich, &regs, cell)) {
fprintf(stderr, "Error creating PBCH object\n"); fprintf(stderr, "Error creating PBCH object\n");
exit(-1); exit(-1);
} }
@ -247,12 +255,20 @@ void base_init() {
exit(-1); exit(-1);
} }
if (srslte_pdcch_init(&pdcch, &regs, cell)) { if (srslte_pdcch_init(&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"); fprintf(stderr, "Error creating PDCCH object\n");
exit(-1); exit(-1);
} }
if (srslte_pdsch_init(&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"); fprintf(stderr, "Error creating PDSCH object\n");
exit(-1); exit(-1);
} }
@ -492,7 +508,11 @@ int main(int argc, char **argv) {
srslte_sss_generate(sss_signal0, sss_signal5, cell.id); srslte_sss_generate(sss_signal0, sss_signal5, cell.id);
/* Generate CRS signals */ /* 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"); fprintf(stderr, "Error initializing equalizer\n");
exit(-1); exit(-1);
} }

@ -455,19 +455,38 @@ int main(int argc, char **argv) {
//ue_sync.decimate = prog_args.decimate; //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"); fprintf(stderr, "Error initiating ue_sync\n");
exit(-1); exit(-1);
} }
#endif #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"); fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1); exit(-1);
} }
if (srslte_ue_dl_init_multi(&ue_dl, cell, prog_args.rf_nof_rx_ant)) { // This is the User RNTI if (srslte_ue_dl_init_multi(&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"); fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1); exit(-1);
} }

@ -158,7 +158,11 @@ int main(int argc, char **argv) {
cell.nof_prb = nof_prb; cell.nof_prb = nof_prb;
cell.nof_ports = 1; cell.nof_ports = 1;
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");
exit(-1);
}
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n"); fprintf(stderr, "Error initiating ue_sync\n");
exit(-1); exit(-1);
} }

@ -102,7 +102,6 @@ public:
virtual uint32_t get_ul_count() = 0; virtual uint32_t get_ul_count() = 0;
virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 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; virtual void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) = 0;
virtual void cell_selected() = 0;
}; };
// NAS interface for UE // NAS interface for UE
@ -140,19 +139,9 @@ public:
virtual void enable_capabilities() = 0; virtual void enable_capabilities() = 0;
virtual void plmn_search() = 0; virtual void plmn_search() = 0;
virtual void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) = 0; virtual void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) = 0;
virtual void connect() = 0;
}; };
// RRC interface for GW
class rrc_interface_gw
{
public:
virtual bool is_connected() = 0;
virtual void connect() = 0;
virtual bool have_drb() = 0;
};
// RRC interface for PDCP // RRC interface for PDCP
class rrc_interface_pdcp class rrc_interface_pdcp
{ {
@ -481,6 +470,7 @@ public:
virtual void cell_search_start() = 0; virtual void cell_search_start() = 0;
virtual void cell_search_next() = 0; virtual void cell_search_next() = 0;
virtual bool cell_select(uint32_t earfcn, srslte_cell_t cell) = 0; virtual bool cell_select(uint32_t earfcn, srslte_cell_t cell) = 0;
virtual bool sync_stop() = 0;
/* Is the PHY downlink synchronized? */ /* Is the PHY downlink synchronized? */
virtual bool sync_status() = 0; virtual bool sync_status() = 0;

@ -92,10 +92,13 @@ typedef struct {
SRSLTE_API int srslte_chest_dl_init(srslte_chest_dl_t *q, 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 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, SRSLTE_API void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q,
float *filter, float *filter,
uint32_t filter_len); uint32_t filter_len);

@ -77,10 +77,14 @@ typedef struct {
SRSLTE_API int srslte_chest_ul_init(srslte_chest_ul_t *q, 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 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_API void srslte_chest_ul_set_cfg(srslte_chest_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg, srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pucch_cfg_t *pucch_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, 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_cell_t cell);
SRSLTE_API void srslte_refsignal_cs_free(srslte_refsignal_cs_t *q); SRSLTE_API void srslte_refsignal_cs_free(srslte_refsignal_cs_t *q);

@ -94,6 +94,9 @@ typedef struct {
} srslte_refsignal_srs_pregen_t; } srslte_refsignal_srs_pregen_t;
SRSLTE_API int srslte_refsignal_ul_init(srslte_refsignal_ul_t *q, 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_cell_t cell);
SRSLTE_API void srslte_refsignal_ul_free(srslte_refsignal_ul_t *q); 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, srslte_refsignal_dmrs_pusch_cfg_t *cfg,
uint32_t nof_prb); 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_API int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q,
srslte_refsignal_ul_dmrs_pregen_t *pregen); srslte_refsignal_ul_dmrs_pregen_t *pregen);

@ -44,7 +44,8 @@ typedef struct SRSLTE_API {
uint8_t *c_bytes; uint8_t *c_bytes;
float *c_float; float *c_float;
short *c_short; short *c_short;
uint32_t len; uint32_t cur_len;
uint32_t max_len;
} srslte_sequence_t; } srslte_sequence_t;
SRSLTE_API int srslte_sequence_init(srslte_sequence_t *q, uint32_t len); 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 len,
uint32_t seed); 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); uint32_t seed);
SRSLTE_API int srslte_sequence_pbch(srslte_sequence_t *seq, SRSLTE_API int srslte_sequence_pbch(srslte_sequence_t *seq,

@ -58,6 +58,7 @@ typedef enum {
}srslte_dft_dir_t; }srslte_dft_dir_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
int init_size; // DFT length used in the first initialization
int size; // DFT length int size; // DFT length
void *in; // Input buffer void *in; // Input buffer
void *out; // Output buffer void *out; // Output buffer
@ -86,6 +87,16 @@ SRSLTE_API int srslte_dft_plan_r(srslte_dft_plan_t *plan,
int dft_points, int dft_points,
srslte_dft_dir_t dir); 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); SRSLTE_API void srslte_dft_plan_free(srslte_dft_plan_t *plan);
/* Set options */ /* Set options */

@ -45,11 +45,17 @@ typedef struct SRSLTE_API {
uint32_t max_prb; uint32_t max_prb;
srslte_dft_plan_t dft_plan[SRSLTE_MAX_PRB+1]; 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_dft_precoding_t;
SRSLTE_API int srslte_dft_precoding_init(srslte_dft_precoding_t *q, 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); uint32_t max_prb);
SRSLTE_API void srslte_dft_precoding_free(srslte_dft_precoding_t *q); 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_prb,
uint32_t nof_symbols); 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 #endif

@ -47,6 +47,7 @@
/* This is common for both directions */ /* This is common for both directions */
typedef struct SRSLTE_API{ typedef struct SRSLTE_API{
srslte_dft_plan_t fft_plan; srslte_dft_plan_t fft_plan;
uint32_t max_prb;
uint32_t nof_symbols; uint32_t nof_symbols;
uint32_t symbol_sz; uint32_t symbol_sz;
uint32_t nof_guards; uint32_t nof_guards;
@ -56,17 +57,26 @@ typedef struct SRSLTE_API{
cf_t *tmp; // for removing zero padding cf_t *tmp; // for removing zero padding
bool freq_shift; bool freq_shift;
float freq_shift_f;
cf_t *shift_buffer; cf_t *shift_buffer;
}srslte_ofdm_t; }srslte_ofdm_t;
SRSLTE_API int srslte_ofdm_init_(srslte_ofdm_t *q, SRSLTE_API int srslte_ofdm_init_(srslte_ofdm_t *q,
srslte_cp_t cp, srslte_cp_t cp,
int symbol_sz, int symbol_sz,
int nof_prb, int max_prb,
srslte_dft_dir_t dir); srslte_dft_dir_t dir);
SRSLTE_API int srslte_ofdm_rx_init(srslte_ofdm_t *q, SRSLTE_API int srslte_ofdm_rx_init(srslte_ofdm_t *q,
srslte_cp_t cp_type, 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); uint32_t nof_prb);
SRSLTE_API void srslte_ofdm_rx_free(srslte_ofdm_t *q); 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 */ /* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_enb_dl_init(srslte_enb_dl_t *q, 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 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, SRSLTE_API void srslte_enb_dl_set_cfi(srslte_enb_dl_t *q,
uint32_t cfi); uint32_t cfi);

@ -101,14 +101,17 @@ typedef struct {
/* This function shall be called just after the initial synchronization */ /* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_enb_ul_init(srslte_enb_ul_t *q, 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_cell_t cell,
srslte_prach_cfg_t* prach_cfg, srslte_prach_cfg_t* prach_cfg,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg, srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pusch_hopping_cfg_t *hopping_cfg, srslte_pusch_hopping_cfg_t *hopping_cfg,
srslte_pucch_cfg_t *pucch_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, SRSLTE_API int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q,
uint16_t rnti); uint16_t rnti);

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

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

@ -85,14 +85,16 @@ typedef struct SRSLTE_API {
} srslte_pdcch_t; } srslte_pdcch_t;
SRSLTE_API int srslte_pdcch_init(srslte_pdcch_t *q, SRSLTE_API int srslte_pdcch_init(srslte_pdcch_t *q,
srslte_regs_t *regs, uint32_t max_prb);
srslte_cell_t cell);
SRSLTE_API int srslte_pdcch_init_multi(srslte_pdcch_t *q, SRSLTE_API int srslte_pdcch_init_multi(srslte_pdcch_t *q,
srslte_regs_t *regs, uint32_t max_prb,
srslte_cell_t cell,
uint32_t nof_rx_antennas); uint32_t nof_rx_antennas);
SRSLTE_API int srslte_pdcch_set_cell(srslte_pdcch_t *q,
srslte_regs_t *regs,
srslte_cell_t cell);
SRSLTE_API void srslte_pdcch_free(srslte_pdcch_t *q); SRSLTE_API void srslte_pdcch_free(srslte_pdcch_t *q);

@ -60,6 +60,8 @@ typedef struct SRSLTE_API {
uint32_t max_re; uint32_t max_re;
bool is_ue;
/* buffers */ /* buffers */
// void buffers are shared for tx and rx // void buffers are shared for tx and rx
cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
@ -74,19 +76,31 @@ typedef struct SRSLTE_API {
// This is to generate the scrambling seq for multiple CRNTIs // This is to generate the scrambling seq for multiple CRNTIs
srslte_pdsch_user_t **users; srslte_pdsch_user_t **users;
srslte_sequence_t tmp_seq;
srslte_sch_t dl_sch; srslte_sch_t dl_sch;
} srslte_pdsch_t; } srslte_pdsch_t;
SRSLTE_API int srslte_pdsch_init(srslte_pdsch_t *q, SRSLTE_API int srslte_pdsch_init_ue(srslte_pdsch_t *q,
srslte_cell_t cell); uint32_t max_prb);
SRSLTE_API int srslte_pdsch_init_multi(srslte_pdsch_t *q, SRSLTE_API int srslte_pdsch_init_enb(srslte_pdsch_t *q,
srslte_cell_t cell, uint32_t max_prb);
SRSLTE_API int srslte_pdsch_init_multi_ue(srslte_pdsch_t *q,
uint32_t max_prb,
uint32_t nof_rx_antennas);
SRSLTE_API int srslte_pdsch_init_multi_enb(srslte_pdsch_t *q,
uint32_t max_prb,
uint32_t nof_rx_antennas); uint32_t nof_rx_antennas);
SRSLTE_API void srslte_pdsch_free(srslte_pdsch_t *q); 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, SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q,
uint16_t rnti); uint16_t rnti);

@ -85,17 +85,17 @@ typedef struct SRSLTE_API {
} srslte_phich_t; } srslte_phich_t;
SRSLTE_API int srslte_phich_init(srslte_phich_t *q, 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_API int srslte_phich_init_multi(srslte_phich_t *q,
srslte_regs_t *regs,
srslte_cell_t cell,
uint32_t nof_rx_antennas); uint32_t nof_rx_antennas);
SRSLTE_API void srslte_phich_free(srslte_phich_t *q); 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, SRSLTE_API void srslte_phich_calc(srslte_phich_t *q,
uint32_t n_prb_lowest, uint32_t n_prb_lowest,
uint32_t n_dmrs, uint32_t n_dmrs,

@ -44,6 +44,8 @@
#include "srslte/phy/common/phy_common.h" #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. /** Generation and detection of RACH signals for uplink.
* Currently only supports preamble formats 0-3. * Currently only supports preamble formats 0-3.
* Does not currently support high speed flag. * 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_ul; // IFFT size for uplink
uint32_t N_ifft_prach; // IFFT size for PRACH generation uint32_t N_ifft_prach; // IFFT size for PRACH generation
uint32_t max_N_ifft_ul;
// Working parameters // Working parameters
uint32_t N_zc; // PRACH sequence length uint32_t N_zc; // PRACH sequence length
uint32_t N_cs; // Cyclic shift size uint32_t N_cs; // Cyclic shift size
@ -82,12 +86,12 @@ typedef struct SRSLTE_API {
float *corr; float *corr;
// PRACH IFFT // PRACH IFFT
srslte_dft_plan_t *fft; srslte_dft_plan_t fft;
srslte_dft_plan_t *ifft; srslte_dft_plan_t ifft;
// ZC-sequence FFT and IFFT // ZC-sequence FFT and IFFT
srslte_dft_plan_t *zc_fft; srslte_dft_plan_t zc_fft;
srslte_dft_plan_t *zc_ifft; srslte_dft_plan_t zc_ifft;
cf_t *signal_fft; cf_t *signal_fft;
float detect_factor; 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_prach_sf_config_t *sf_config);
SRSLTE_API int srslte_prach_init(srslte_prach_t *p, 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 N_ifft_ul,
uint32_t config_idx, uint32_t config_idx,
uint32_t root_seq_index, uint32_t root_seq_index,

@ -45,7 +45,7 @@
#define SRSLTE_PUCCH_N_SEQ 12 #define SRSLTE_PUCCH_N_SEQ 12
#define SRSLTE_PUCCH2_NOF_BITS SRSLTE_UCI_CQI_CODED_PUCCH_B #define SRSLTE_PUCCH2_NOF_BITS SRSLTE_UCI_CQI_CODED_PUCCH_B
#define SRSLTE_PUCCH_MAX_BITS SRSLTE_CQI_MAX_BITS #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 { typedef enum SRSLTE_API {
SRSLTE_PUCCH_FORMAT_1 = 0, SRSLTE_PUCCH_FORMAT_1 = 0,
@ -100,9 +100,9 @@ typedef struct SRSLTE_API {
uint32_t f_gh[SRSLTE_NSLOTS_X_FRAME]; uint32_t f_gh[SRSLTE_NSLOTS_X_FRAME];
float tmp_arg[SRSLTE_PUCCH_N_SEQ]; float tmp_arg[SRSLTE_PUCCH_N_SEQ];
cf_t *z; cf_t z[SRSLTE_PUCCH_MAX_SYMBOLS];
cf_t *z_tmp; cf_t z_tmp[SRSLTE_PUCCH_MAX_SYMBOLS];
cf_t *ce; cf_t ce[SRSLTE_PUCCH_MAX_SYMBOLS];
bool shortened; bool shortened;
bool group_hopping_en; bool group_hopping_en;
@ -116,11 +116,13 @@ typedef struct SRSLTE_API {
}srslte_pucch_t; }srslte_pucch_t;
SRSLTE_API int srslte_pucch_init(srslte_pucch_t *q, SRSLTE_API int srslte_pucch_init(srslte_pucch_t *q);
srslte_cell_t cell);
SRSLTE_API void srslte_pucch_free(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_API bool srslte_pucch_set_cfg(srslte_pucch_t* q,
srslte_pucch_cfg_t* cfg, srslte_pucch_cfg_t* cfg,
bool group_hopping_en); bool group_hopping_en);

@ -62,13 +62,14 @@ typedef struct {
typedef struct { typedef struct {
srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME]; srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME];
bool sequences_generated; bool sequence_generated;
} srslte_pusch_user_t; } srslte_pusch_user_t;
/* PUSCH object */ /* PUSCH object */
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_cell_t cell; srslte_cell_t cell;
bool is_ue;
uint32_t max_re; uint32_t max_re;
srslte_dft_precoding_t dft_precoding; srslte_dft_precoding_t dft_precoding;
@ -96,11 +97,17 @@ typedef struct SRSLTE_API {
}srslte_pusch_t; }srslte_pusch_t;
SRSLTE_API int srslte_pusch_init(srslte_pusch_t *q, SRSLTE_API int srslte_pusch_init_ue(srslte_pusch_t *q,
srslte_cell_t cell); 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 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_API int srslte_pusch_cfg(srslte_pusch_t *q,
srslte_pusch_cfg_t *cfg, srslte_pusch_cfg_t *cfg,
srslte_ra_ul_grant_t *grant, srslte_ra_ul_grant_t *grant,

@ -68,6 +68,7 @@ SRSLTE_API void srslte_interp_linear_f(float *input,
typedef struct { typedef struct {
cf_t *diff_vec; cf_t *diff_vec;
uint32_t vector_len; uint32_t vector_len;
uint32_t max_vector_len;
} srslte_interp_linsrslte_vec_t; } srslte_interp_linsrslte_vec_t;
SRSLTE_API int srslte_interp_linear_vector_init(srslte_interp_linsrslte_vec_t *q, 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 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, SRSLTE_API void srslte_interp_linear_vector(srslte_interp_linsrslte_vec_t *q,
cf_t *in0, cf_t *in0,
cf_t *in1, cf_t *in1,
@ -108,6 +112,8 @@ typedef struct {
float *ramp; float *ramp;
uint32_t vector_len; uint32_t vector_len;
uint32_t M; uint32_t M;
uint32_t max_vector_len;
uint32_t max_M;
} srslte_interp_lin_t; } srslte_interp_lin_t;
SRSLTE_API int srslte_interp_linear_init(srslte_interp_lin_t *q, 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 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, SRSLTE_API void srslte_interp_linear_offset(srslte_interp_lin_t *q,
cf_t *input, cf_t *input,
cf_t *output, cf_t *output,

@ -49,6 +49,7 @@ typedef struct SRSLTE_API {
float last_freq; float last_freq;
float tol; float tol;
int nsamples; int nsamples;
int max_samples;
srslte_cexptab_t tab; srslte_cexptab_t tab;
cf_t *cur_cexp; cf_t *cur_cexp;
}srslte_cfo_t; }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 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); uint32_t samples);
SRSLTE_API void srslte_cfo_set_tol(srslte_cfo_t *h, SRSLTE_API void srslte_cfo_set_tol(srslte_cfo_t *h,

@ -35,6 +35,7 @@
typedef struct { typedef struct {
cf_t *corr; cf_t *corr;
uint32_t symbol_sz; uint32_t symbol_sz;
uint32_t max_symbol_sz;
} srslte_cp_synch_t; } srslte_cp_synch_t;
SRSLTE_API int srslte_cp_synch_init(srslte_cp_synch_t *q, 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 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, SRSLTE_API uint32_t srslte_cp_synch(srslte_cp_synch_t *q,
cf_t *input, cf_t *input,
uint32_t max_offset, uint32_t max_offset,

@ -79,6 +79,10 @@ typedef struct SRSLTE_API {
#endif #endif
int decimate; int decimate;
uint32_t max_frame_size;
uint32_t max_fft_size;
uint32_t frame_size; uint32_t frame_size;
uint32_t N_id_2; uint32_t N_id_2;
uint32_t fft_size; 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 cfo_i,
int decimate); 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, SRSLTE_API int srslte_pss_synch_init(srslte_pss_synch_t *q,
uint32_t frame_size); uint32_t frame_size);

@ -70,6 +70,7 @@ typedef struct SRSLTE_API {
srslte_dft_plan_t dftp_input; srslte_dft_plan_t dftp_input;
uint32_t fft_size; uint32_t fft_size;
uint32_t max_fft_size;
float corr_peak_threshold; float corr_peak_threshold;
uint32_t symbol_sz; uint32_t symbol_sz;
@ -89,7 +90,7 @@ typedef struct SRSLTE_API {
SRSLTE_API int srslte_sss_synch_init(srslte_sss_synch_t *q, SRSLTE_API int srslte_sss_synch_init(srslte_sss_synch_t *q,
uint32_t fft_size); 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); uint32_t fft_size);
SRSLTE_API void srslte_sss_synch_free(srslte_sss_synch_t *q); SRSLTE_API void srslte_sss_synch_free(srslte_sss_synch_t *q);

@ -97,6 +97,8 @@ typedef struct SRSLTE_API {
float M_ext_avg; float M_ext_avg;
cf_t *temp; cf_t *temp;
uint32_t max_frame_size;
}srslte_sync_t; }srslte_sync_t;
typedef enum { typedef enum {
@ -121,6 +123,11 @@ SRSLTE_API int srslte_sync_init_decim(srslte_sync_t *q,
SRSLTE_API void srslte_sync_free(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); SRSLTE_API void srslte_sync_reset(srslte_sync_t *q);
/* Finds a correlation peak in the input signal around position find_offset */ /* Finds a correlation peak in the input signal around position find_offset */

@ -114,14 +114,17 @@ typedef struct SRSLTE_API {
/* This function shall be called just after the initial synchronization */ /* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_dl_init(srslte_ue_dl_t *q, SRSLTE_API int srslte_ue_dl_init(srslte_ue_dl_t *q,
srslte_cell_t cell); uint32_t max_prb);
SRSLTE_API int srslte_ue_dl_init_multi(srslte_ue_dl_t *q, SRSLTE_API int srslte_ue_dl_init_multi(srslte_ue_dl_t *q,
srslte_cell_t cell, uint32_t max_prb,
uint32_t nof_rx_antennas); uint32_t nof_rx_antennas);
SRSLTE_API void srslte_ue_dl_free(srslte_ue_dl_t *q); 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, SRSLTE_API int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q,
cf_t *input, cf_t *input,
uint32_t sf_idx, uint32_t sf_idx,

@ -79,10 +79,13 @@ typedef struct SRSLTE_API {
} srslte_ue_mib_t; } srslte_ue_mib_t;
SRSLTE_API int srslte_ue_mib_init(srslte_ue_mib_t *q, 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 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 void srslte_ue_mib_reset(srslte_ue_mib_t * q);
SRSLTE_API int srslte_ue_mib_decode(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; uint32_t nof_rx_antennas;
} srslte_ue_mib_sync_t; } 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, 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 *), int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t *),
uint32_t nof_rx_antennas, uint32_t nof_rx_antennas,
void *stream_handler); void *stream_handler);
SRSLTE_API void srslte_ue_mib_sync_free(srslte_ue_mib_sync_t *q); 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 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, 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 sfind;
srslte_sync_t strack; srslte_sync_t strack;
uint32_t max_prb;
srslte_agc_t agc; srslte_agc_t agc;
bool do_agc; bool do_agc;
uint32_t agc_period; uint32_t agc_period;
@ -125,18 +127,21 @@ typedef struct SRSLTE_API {
} srslte_ue_sync_t; } srslte_ue_sync_t;
SRSLTE_API int srslte_ue_sync_init(srslte_ue_sync_t *q, 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*), int (recv_callback)(void*, void*, uint32_t, srslte_timestamp_t*),
void *stream_handler); void *stream_handler);
SRSLTE_API int srslte_ue_sync_init_multi(srslte_ue_sync_t *q, 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*), int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*),
uint32_t nof_rx_antennas, uint32_t nof_rx_antennas,
void *stream_handler); void *stream_handler);
SRSLTE_API int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q, 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*), int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*),
uint32_t nof_rx_antennas, uint32_t nof_rx_antennas,
void *stream_handler, void *stream_handler,
@ -150,6 +155,9 @@ SRSLTE_API int srslte_ue_sync_init_file(srslte_ue_sync_t *q,
SRSLTE_API void srslte_ue_sync_free(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, SRSLTE_API int srslte_ue_sync_start_agc(srslte_ue_sync_t *q,
double (set_gain_callback)(void*, double), double (set_gain_callback)(void*, double),
float init_gain_value); float init_gain_value);

@ -107,10 +107,13 @@ typedef struct SRSLTE_API {
/* This function shall be called just after the initial synchronization */ /* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_ul_init(srslte_ue_ul_t *q, 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 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(srslte_ue_ul_t *q, SRSLTE_API void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q,
float cur_cfo); float cur_cfo);

@ -46,6 +46,8 @@ typedef struct SRSLTE_API {
uint32_t input_len; uint32_t input_len;
uint32_t filter_len; uint32_t filter_len;
uint32_t output_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 input_plan;
srslte_dft_plan_t filter_plan; srslte_dft_plan_t filter_plan;
srslte_dft_plan_t output_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 input_len,
uint32_t filter_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); SRSLTE_API void srslte_conv_fft_cc_free(srslte_conv_fft_cc_t *q);

@ -46,7 +46,7 @@ class gw
{ {
public: public:
gw(); gw();
void init(srsue::pdcp_interface_gw *pdcp_, srsue::rrc_interface_gw *rrc_, srsue::ue_interface *ue_, log *gw_log_); void init(srsue::pdcp_interface_gw *pdcp_, srsue::ue_interface *ue_, log *gw_log_);
void stop(); void stop();
void get_metrics(gw_metrics_t &m); void get_metrics(gw_metrics_t &m);
@ -62,7 +62,6 @@ private:
static const int GW_THREAD_PRIO = 7; static const int GW_THREAD_PRIO = 7;
srsue::pdcp_interface_gw *pdcp; srsue::pdcp_interface_gw *pdcp;
srsue::rrc_interface_gw *rrc;
srsue::ue_interface *ue; srsue::ue_interface *ue;
byte_buffer_pool *pool; byte_buffer_pool *pool;

@ -32,6 +32,8 @@
#include <string.h> #include <string.h>
#include <complex.h> #include <complex.h>
#include <math.h> #include <math.h>
#include <srslte/phy/common/phy_common.h>
#include <srslte/srslte.h>
#include "srslte/config.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. * 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, uint32_t max_prb)
int srslte_chest_dl_init(srslte_chest_dl_t *q, srslte_cell_t cell)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL)
srslte_cell_isvalid(&cell))
{ {
bzero(q, sizeof(srslte_chest_dl_t)); 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) { if (ret != SRSLTE_SUCCESS) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret); fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
goto clean_exit; 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) { if (!q->tmp_noise) {
perror("malloc"); perror("malloc");
goto clean_exit; 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) { if (!q->pilot_estimates) {
perror("malloc"); perror("malloc");
goto clean_exit; 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) { if (!q->pilot_estimates_average) {
perror("malloc"); perror("malloc");
goto clean_exit; 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) { if (!q->pilot_recv_signal) {
perror("malloc"); perror("malloc");
goto clean_exit; 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"); fprintf(stderr, "Error initializing vector interpolator\n");
goto clean_exit; 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"); fprintf(stderr, "Error initializing interpolator\n");
goto clean_exit; 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->noise_alg = SRSLTE_NOISE_ALG_REFS;
q->smooth_filter_len = 3; q->smooth_filter_len = 3;
srslte_chest_dl_set_smooth_filter3_coeff(q, 0.1); srslte_chest_dl_set_smooth_filter3_coeff(q, 0.1);
q->cell = cell;
} }
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
@ -162,10 +157,45 @@ void srslte_chest_dl_free(srslte_chest_dl_t *q)
bzero(q, sizeof(srslte_chest_dl_t)); 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 */ /* 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) 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); int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id);
/* Substract noisy pilot estimates */ /* Substract noisy pilot estimates */
srslte_vec_sub_ccc(q->pilot_estimates_average, q->pilot_estimates, q->tmp_noise, nref); 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 */ /* 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], 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)); q->pilot_estimates, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
if (ce != NULL) { if (ce != NULL) {
/* Smooth estimates (if applicable) and interpolate */ /* Smooth estimates (if applicable) and interpolate */

@ -32,6 +32,8 @@
#include <string.h> #include <string.h>
#include <complex.h> #include <complex.h>
#include <math.h> #include <math.h>
#include <srslte/srslte.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/config.h" #include "srslte/config.h"
@ -43,6 +45,8 @@
#define NOF_REFS_SYM (q->cell.nof_prb*SRSLTE_NRE) #define NOF_REFS_SYM (q->cell.nof_prb*SRSLTE_NRE)
#define NOF_REFS_SF (NOF_REFS_SYM*2) // 2 reference symbols per subframe #define NOF_REFS_SF (NOF_REFS_SYM*2) // 2 reference symbols per subframe
#define MAX_REFS_SF (max_prb*SRSLTE_NRE*2) // 2 reference symbols per subframe
/** 3GPP LTE Downlink channel estimator and equalizer. /** 3GPP LTE Downlink channel estimator and equalizer.
* Estimates the channel in the resource elements transmitting references and interpolates for the rest * Estimates the channel in the resource elements transmitting references and interpolates for the rest
* of the resource grid. * of the resource grid.
@ -52,52 +56,49 @@
* This object depends on the srslte_refsignal_t object for creating the LTE CSR signal. * 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; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL)
srslte_cell_isvalid(&cell))
{ {
bzero(q, sizeof(srslte_chest_ul_t)); bzero(q, sizeof(srslte_chest_ul_t));
q->cell = cell; ret = srslte_refsignal_ul_init(&q->dmrs_signal, max_prb);
ret = srslte_refsignal_ul_init(&q->dmrs_signal, cell);
if (ret != SRSLTE_SUCCESS) { if (ret != SRSLTE_SUCCESS) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret); fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
goto clean_exit; 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) { if (!q->tmp_noise) {
perror("malloc"); perror("malloc");
goto clean_exit; 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) { if (!q->pilot_estimates) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
} }
for (int i=0;i<4;i++) { 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]) { if (!q->pilot_estimates_tmp[i]) {
perror("malloc"); perror("malloc");
goto clean_exit; 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) { if (!q->pilot_recv_signal) {
perror("malloc"); perror("malloc");
goto clean_exit; 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) { if (!q->pilot_known_signal) {
perror("malloc"); perror("malloc");
goto clean_exit; 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_SF)) {
fprintf(stderr, "Error initializing vector interpolator\n"); fprintf(stderr, "Error initializing vector interpolator\n");
goto clean_exit; goto clean_exit;
} }
@ -107,6 +108,11 @@ int srslte_chest_ul_init(srslte_chest_ul_t *q, srslte_cell_t cell)
q->dmrs_signal_configured = false; 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; ret = SRSLTE_SUCCESS;
@ -120,9 +126,8 @@ clean_exit:
void srslte_chest_ul_free(srslte_chest_ul_t *q) 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_dmrs_pusch_pregen_free(&q->dmrs_signal, &q->dmrs_pregen);
}
srslte_refsignal_ul_free(&q->dmrs_signal); srslte_refsignal_ul_free(&q->dmrs_signal);
if (q->tmp_noise) { if (q->tmp_noise) {
free(q->tmp_noise); free(q->tmp_noise);
@ -146,6 +151,30 @@ void srslte_chest_ul_free(srslte_chest_ul_t *q)
bzero(q, sizeof(srslte_chest_ul_t)); 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_SF)) {
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, void srslte_chest_ul_set_cfg(srslte_chest_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg, srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pucch_cfg_t *pucch_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 /** Allocates and precomputes the Cell-Specific Reference (CSR) signal for
* the 20 slots in a subframe * 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; 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 && if (q != NULL &&
srslte_cell_isvalid(&cell)) 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)); bzero(&seq, sizeof(srslte_sequence_t));
if (srslte_sequence_init(&seq, 2 * 2 * SRSLTE_MAX_PRB)) { if (srslte_sequence_init(&seq, 2*2*SRSLTE_MAX_PRB)) {
goto free_and_exit; return SRSLTE_ERROR;
} }
if (SRSLTE_CP_ISNORM(cell.cp)) { 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; 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 (ns=0;ns<SRSLTE_NSLOTS_X_FRAME;ns++) {
for (p=0;p<2;p++) { for (p=0;p<2;p++) {
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(2*p)/2; 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; + 2 * cell.id + N_cp;
/* generate sequence for this symbol and slot */ /* 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 */ /* Compute signal */
for (i = 0; i < 2*q->cell.nof_prb; i++) { 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); _Complex_I * (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2);
} }
} }
} }
} }
srslte_sequence_free(&seq); srslte_sequence_free(&seq);
ret = SRSLTE_SUCCESS;
} }
free_and_exit: ret = SRSLTE_SUCCESS;
if (ret == SRSLTE_ERROR) {
srslte_sequence_free(&seq);
srslte_refsignal_cs_free(q);
} }
return ret; return ret;
} }
@ -178,10 +190,8 @@ free_and_exit:
/** Deallocates a srslte_refsignal_cs_t object allocated with srslte_refsignal_cs_init */ /** Deallocates a srslte_refsignal_cs_t object allocated with srslte_refsignal_cs_init */
void srslte_refsignal_cs_free(srslte_refsignal_cs_t * q) void srslte_refsignal_cs_free(srslte_refsignal_cs_t * q)
{ {
int i, p; for (int p=0;p<2;p++) {
for (int i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
for (p=0;p<2;p++) {
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
if (q->pilots[p][i]) { if (q->pilots[p][i]) {
free(q->pilots[p][i]); free(q->pilots[p][i]);
} }

@ -29,6 +29,7 @@
#include <strings.h> #include <strings.h>
#include <stdlib.h> #include <stdlib.h>
#include <complex.h> #include <complex.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/phy/common/phy_common.h" #include "srslte/phy/common/phy_common.h"
#include "srslte/phy/ch_estimation/refsignal_ul.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; q->n_prs_pusch[delta_ss][ns] = n_prs;
} }
srslte_sequence_free(&seq);
} }
srslte_sequence_free(&seq);
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
@ -160,9 +161,9 @@ static int generate_srslte_sequence_hopping_v(srslte_refsignal_ul_t *q) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
q->v_pusch[ns][delta_ss] = seq.c[ns]; q->v_pusch[ns][delta_ss] = seq.c[ns];
srslte_sequence_free(&seq);
} }
} }
srslte_sequence_free(&seq);
return SRSLTE_SUCCESS; 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 /** 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; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell)) { if (q != NULL) {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_refsignal_ul_t)); bzero(q, sizeof(srslte_refsignal_ul_t));
q->cell = cell;
// Allocate temporal buffer for computing signal argument // 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) { if (!q->tmp_arg) {
perror("malloc"); perror("malloc");
goto free_and_exit; 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); srslte_pucch_cfg_default(&q->pucch_cfg);
// Precompute n_prs // Precompute n_prs
if (generate_n_prs(q)) { if (generate_n_prs(q)) {
goto free_and_exit; return SRSLTE_ERROR;
} }
// Precompute group hopping values u. // Precompute group hopping values u.
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) { 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 // Precompute sequence hopping values v. Uses f_ss_pusch
if (generate_srslte_sequence_hopping_v(q)) { 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)) { 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: ret = SRSLTE_SUCCESS;
if (ret == SRSLTE_ERROR) {
srslte_refsignal_ul_free(q);
} }
return ret; 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, void srslte_refsignal_ul_set_cfg(srslte_refsignal_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg, srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pucch_cfg_t *pucch_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) 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 sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
for (uint32_t cs=0;cs<SRSLTE_NOF_CSHIFT;cs++) { 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]) { if (pregen->r[cs][sf_idx]) {
for (uint32_t n=0;n<=q->cell.nof_prb;n++) { for (uint32_t n=0;n<=q->cell.nof_prb;n++) {
if (srslte_dft_precoding_valid_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 (pregen->r[cs][sf_idx][n]) {
if (srslte_refsignal_dmrs_pusch_gen(q, n, sf_idx, cs, 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; return SRSLTE_ERROR;

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

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

@ -81,7 +81,12 @@ int main(int argc, char **argv) {
parse_args(argc,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"); fprintf(stderr, "Error initializing UL reference signal\n");
goto do_exit; goto do_exit;
} }

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

@ -27,7 +27,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <strings.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/common/sequence.h"
#include "srslte/phy/utils/vector.h" #include "srslte/phy/utils/vector.h"
@ -35,26 +36,71 @@
#define Nc 1600 #define Nc 1600
#define MAX_SEQ_LEN (128*1024)
/* /*
* Pseudo Random Sequence generation. * Pseudo Random Sequence generation.
* It follows the 3GPP Release 8 (LTE) 36.211 * It follows the 3GPP Release 8 (LTE) 36.211
* Section 7.2 * Section 7.2
*/ */
void srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t seed) { #ifdef static
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);
}
#else
int srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) {
int n; int n;
uint32_t *x1, *x2; 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) { if (!x1) {
perror("calloc"); perror("calloc");
return; return -1;
} }
x2 = calloc(Nc + q->len + 31, sizeof(uint32_t)); x2 = calloc(Nc + len + 31, sizeof(uint32_t));
if (!x2) { if (!x2) {
free(x1); free(x1);
perror("calloc"); perror("calloc");
return; return -1;
} }
for (n = 0; n < 31; n++) { for (n = 0; n < 31; n++) {
@ -62,45 +108,43 @@ void srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t seed) {
} }
x1[0] = 1; 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; x1[n + 31] = (x1[n + 3] + x1[n]) & 0x1;
x2[n + 31] = (x2[n + 3] + x2[n + 2] + +x2[n+1] + x2[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; q->c[n] = (x1[n + Nc] + x2[n + Nc]) & 0x1;
} }
free(x1); free(x1);
free(x2); free(x2);
return 0;
} }
#endif
int srslte_sequence_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) { int srslte_sequence_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) {
if (srslte_sequence_init(q, len)) { if (srslte_sequence_init(q, len)) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
q->len = len; q->cur_len = len;
srslte_sequence_set_LTE_pr(q, seed); srslte_sequence_set_LTE_pr(q, len, seed);
srslte_bit_pack_vector(q->c, q->c_bytes, len); srslte_bit_pack_vector(q->c, q->c_bytes, len);
for (int i=0;i<len;i++) { for (int i=0;i<len;i++) {
q->c_float[i] = (1-2*q->c[i]); q->c_float[i] = (1-2*q->c[i]);
q->c_short[i] = (int16_t) q->c_float[i]; q->c_short[i] = (int16_t) q->c_float[i];
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
int srslte_sequence_init(srslte_sequence_t *q, uint32_t len) { int srslte_sequence_init(srslte_sequence_t *q, uint32_t len) {
if (q->c && (q->len != len)) { if (q->c && len > q->max_len) {
free(q->c); srslte_sequence_free(q);
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) { if (!q->c) {
q->c = srslte_vec_malloc(len * sizeof(uint8_t)); q->c = srslte_vec_malloc(len * sizeof(uint8_t));
@ -119,7 +163,7 @@ int srslte_sequence_init(srslte_sequence_t *q, uint32_t len) {
if (!q->c_short) { if (!q->c_short) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
q->len = len; q->max_len = len;
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }

@ -29,6 +29,7 @@
#include <complex.h> #include <complex.h>
#include <fftw3.h> #include <fftw3.h>
#include <string.h> #include <string.h>
#include <srslte/srslte.h>
#include "srslte/phy/dft/dft.h" #include "srslte/phy/dft/dft.h"
#include "srslte/phy/utils/vector.h" #include "srslte/phy/utils/vector.h"
@ -46,11 +47,41 @@ int srslte_dft_plan(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_di
return 0; 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) { static void allocate(srslte_dft_plan_t *plan, int size_in, int size_out, int len) {
plan->in = fftwf_malloc(size_in*len); plan->in = fftwf_malloc(size_in*len);
plan->out = fftwf_malloc(size_out*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, 0U);
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) { 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); allocate(plan,sizeof(fftwf_complex),sizeof(fftwf_complex), dft_points);
int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD; int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD;
@ -59,6 +90,7 @@ int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_
return -1; return -1;
} }
plan->size = dft_points; plan->size = dft_points;
plan->init_size = plan->size;
plan->mode = SRSLTE_DFT_COMPLEX; plan->mode = SRSLTE_DFT_COMPLEX;
plan->dir = dir; plan->dir = dir;
plan->forward = (dir==SRSLTE_DFT_FORWARD)?true:false; plan->forward = (dir==SRSLTE_DFT_FORWARD)?true:false;
@ -70,6 +102,20 @@ int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_
return 0; 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, 0U);
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) { 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); allocate(plan,sizeof(float),sizeof(float), dft_points);
int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R; int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_R2HC : FFTW_HC2R;
@ -78,6 +124,7 @@ int srslte_dft_plan_r(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_
return -1; return -1;
} }
plan->size = dft_points; plan->size = dft_points;
plan->init_size = plan->size;
plan->mode = SRSLTE_REAL; plan->mode = SRSLTE_REAL;
plan->dir = dir; plan->dir = dir;
plan->forward = (dir==SRSLTE_DFT_FORWARD)?true:false; plan->forward = (dir==SRSLTE_DFT_FORWARD)?true:false;

@ -40,7 +40,8 @@
#include "srslte/phy/dft/dft_precoding.h" #include "srslte/phy/dft/dft_precoding.h"
/* Create DFT plans for transform precoding */ /* 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; int ret = SRSLTE_ERROR_INVALID_INPUTS;
bzero(q, sizeof(srslte_dft_precoding_t)); bzero(q, sizeof(srslte_dft_precoding_t));
@ -50,36 +51,39 @@ int srslte_dft_precoding_init(srslte_dft_precoding_t *q, uint32_t max_prb)
for (uint32_t i=1;i<=max_prb;i++) { for (uint32_t i=1;i<=max_prb;i++) {
if(srslte_dft_precoding_valid_prb(i)) { if(srslte_dft_precoding_valid_prb(i)) {
DEBUG("Initiating DFT precoding plan for %d PRBs\n", 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); fprintf(stderr, "Error: Creating DFT plan %d\n",i);
goto clean_exit; goto clean_exit;
} }
srslte_dft_plan_set_norm(&q->dft_plan[i], true); 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; q->max_prb = max_prb;
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} }
clean_exit: clean_exit:
if (ret == SRSLTE_ERROR) { if (ret == SRSLTE_ERROR) {
srslte_dft_precoding_free(q); srslte_dft_precoding_free(q);
} }
return ret; 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 */ /* Free DFT plans for transform precoding */
void srslte_dft_precoding_free(srslte_dft_precoding_t *q) void srslte_dft_precoding_free(srslte_dft_precoding_t *q)
{ {
for (uint32_t i=1;i<=q->max_prb;i++) { for (uint32_t i=1;i<=q->max_prb;i++) {
if(srslte_dft_precoding_valid_prb(i)) { if(srslte_dft_precoding_valid_prb(i)) {
srslte_dft_plan_free(&q->dft_plan[i]); srslte_dft_plan_free(&q->dft_plan[i]);
srslte_dft_plan_free(&q->idft_plan[i]);
} }
} }
bzero(q, sizeof(srslte_dft_precoding_t)); 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; 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 <stdlib.h>
#include <complex.h> #include <complex.h>
#include <math.h> #include <math.h>
#include <srslte/srslte.h>
#include "srslte/phy/common/phy_common.h" #include "srslte/phy/common/phy_common.h"
#include "srslte/phy/dft/dft.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; 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_mirror(&q->fft_plan, true);
srslte_dft_plan_set_dc(&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->nof_symbols = SRSLTE_CP_NSYMB(cp);
q->cp = cp; q->cp = cp;
q->freq_shift = false; q->freq_shift = false;
q->shift_buffer = NULL;
q->nof_re = nof_prb * SRSLTE_NRE; q->nof_re = nof_prb * SRSLTE_NRE;
q->nof_guards = ((symbol_sz - q->nof_re) / 2); q->nof_guards = ((symbol_sz - q->nof_re) / 2);
q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz); 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; 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) { void srslte_ofdm_free_(srslte_ofdm_t *q) {
srslte_dft_plan_free(&q->fft_plan); srslte_dft_plan_free(&q->fft_plan);
if (q->tmp) { if (q->tmp) {
@ -78,34 +110,69 @@ void srslte_ofdm_free_(srslte_ofdm_t *q) {
bzero(q, sizeof(srslte_ofdm_t)); 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(nof_prb); int symbol_sz = srslte_symbol_sz(max_prb);
if (symbol_sz < 0) { if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb); fprintf(stderr, "Error: Invalid nof_prb=%d\n", max_prb);
return -1; return -1;
} }
return srslte_ofdm_init_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_FORWARD); q->max_prb = max_prb;
return srslte_ofdm_init_(q, cp, symbol_sz, max_prb, SRSLTE_DFT_FORWARD);
} }
void srslte_ofdm_rx_free(srslte_ofdm_t *q) { int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) {
srslte_ofdm_free_(q); 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_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) { 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_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;
}
}
int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
uint32_t i; uint32_t i;
int ret; int ret;
if (nof_prb <= q->max_prb) {
int symbol_sz = srslte_symbol_sz(nof_prb); int symbol_sz = srslte_symbol_sz(nof_prb);
if (symbol_sz < 0) { if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb); fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb);
return -1; 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) { if (ret == SRSLTE_SUCCESS) {
srslte_dft_plan_set_norm(&q->fft_plan, false);
/* set now zeros at CP */ /* set now zeros at CP */
for (i=0;i<q->nof_symbols;i++) { for (i=0;i<q->nof_symbols;i++) {
bzero(q->tmp, q->nof_guards * sizeof(cf_t)); 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; 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. /* 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 * Caution: This function shall not be called during run-time
*/ */
int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q, float freq_shift) { 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; cf_t *ptr = q->shift_buffer;
for (uint32_t n=0;n<2;n++) { for (uint32_t n=0;n<2;n++) {
for (uint32_t i=0;i<q->nof_symbols;i++) { 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); srslte_dft_plan_set_dc(&q->fft_plan, false);
q->freq_shift = true; q->freq_shift = true;
q->freq_shift_f = freq_shift;
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }

@ -29,6 +29,7 @@
#include <complex.h> #include <complex.h>
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#include <srslte/phy/common/phy_common.h>
#define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb) #define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb)
@ -39,61 +40,55 @@
#define SRSLTE_ENB_RF_AMP 0.1 #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; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL)
srslte_cell_isvalid(&cell))
{ {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_enb_dl_t)); bzero(q, sizeof(srslte_enb_dl_t));
q->cell = cell;
q->cfi = 3; q->cfi = 3;
q->tx_amp = SRSLTE_ENB_RF_AMP; 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"); fprintf(stderr, "Error initiating FFT\n");
goto clean_exit; goto clean_exit;
} }
srslte_ofdm_set_normalize(&q->ifft, true); srslte_ofdm_set_normalize(&q->ifft, true);
if (srslte_regs_init(&q->regs, q->cell)) { if (srslte_pbch_init(&q->pbch)) {
fprintf(stderr, "Error initiating REGs\n");
goto clean_exit;
}
if (srslte_pbch_init(&q->pbch, q->cell)) {
fprintf(stderr, "Error creating PBCH object\n"); fprintf(stderr, "Error creating PBCH object\n");
goto clean_exit; goto clean_exit;
} }
if (srslte_pcfich_init(&q->pcfich, &q->regs, q->cell)) { if (srslte_pcfich_init(&q->pcfich)) {
fprintf(stderr, "Error creating PCFICH object\n"); fprintf(stderr, "Error creating PCFICH object\n");
goto clean_exit; goto clean_exit;
} }
if (srslte_phich_init(&q->phich, &q->regs, q->cell)) { if (srslte_phich_init(&q->phich)) {
fprintf(stderr, "Error creating PHICH object\n"); fprintf(stderr, "Error creating PHICH object\n");
goto clean_exit; goto clean_exit;
} }
if (srslte_pdcch_init(&q->pdcch, &q->regs, q->cell)) { if (srslte_pdcch_init(&q->pdcch, max_prb)) {
fprintf(stderr, "Error creating PDCCH object\n"); fprintf(stderr, "Error creating PDCCH object\n");
goto clean_exit; goto clean_exit;
} }
if (srslte_pdsch_init(&q->pdsch, q->cell)) { if (srslte_pdsch_init_enb(&q->pdsch, max_prb)) {
fprintf(stderr, "Error creating PDSCH object\n"); fprintf(stderr, "Error creating PDSCH object\n");
goto clean_exit; 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); fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
goto clean_exit; goto clean_exit;
} }
for (int i=0;i<q->cell.nof_ports;i++) { for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
q->sf_symbols[i] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); q->sf_symbols[i] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
if (!q->sf_symbols[i]) { if (!q->sf_symbols[i]) {
perror("malloc"); perror("malloc");
@ -102,15 +97,10 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, srslte_cell_t cell)
q->slot1_symbols[i] = &q->sf_symbols[i][CURRENT_SLOTLEN_RE]; q->slot1_symbols[i] = &q->sf_symbols[i][CURRENT_SLOTLEN_RE];
} }
/* 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; ret = SRSLTE_SUCCESS;
} else { } else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n", fprintf(stderr, "Invalid parameters\n");
cell.id, cell.nof_ports, cell.nof_prb);
} }
clean_exit: clean_exit:
@ -141,6 +131,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))
{
q->cfi = 3;
q->tx_amp = SRSLTE_ENB_RF_AMP;
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
if (q->cell.nof_prb) {
if (srslte_regs_init(&q->regs, q->cell)) {
fprintf(stderr, "Error initiating REGs\n");
return SRSLTE_ERROR;
}
}
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
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) void srslte_enb_dl_set_amp(srslte_enb_dl_t *q, float amp)
{ {
q->tx_amp = amp; q->tx_amp = amp;

@ -39,78 +39,54 @@
#define MAX_CANDIDATES 16 #define MAX_CANDIDATES 16
int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell, int srslte_enb_ul_init(srslte_enb_ul_t *q,
srslte_prach_cfg_t *prach_cfg, uint32_t max_prb)
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; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL)
srslte_cell_isvalid(&cell))
{ {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_enb_ul_t)); 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*), SRSLTE_SIRNTI); q->users = calloc(sizeof(srslte_enb_ul_user_t*), SRSLTE_SIRNTI);
if (!q->users) { if (!q->users) {
perror("malloc"); perror("malloc");
goto clean_exit; 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"); fprintf(stderr, "Error initiating FFT\n");
goto clean_exit; goto clean_exit;
} }
srslte_ofdm_set_normalize(&q->fft, false); srslte_ofdm_set_normalize(&q->fft, false);
srslte_ofdm_set_freq_shift(&q->fft, -0.5); 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"); fprintf(stderr, "Error creating PUCCH object\n");
goto clean_exit; 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"); fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit; 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.5, 0.5); srslte_pucch_set_threshold(&q->pucch, 0.5, 0.5);
if (srslte_chest_ul_init(&q->chest, cell)) { if (srslte_chest_ul_init(&q->chest, max_prb)) {
fprintf(stderr, "Error initiating channel estimator\n"); fprintf(stderr, "Error initiating channel estimator\n");
goto clean_exit; goto clean_exit;
} }
// Configure common PUCCH configuration q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
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));
if (!q->sf_symbols) { if (!q->sf_symbols) {
perror("malloc"); perror("malloc");
goto clean_exit; 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) { if (!q->ce) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
@ -119,8 +95,7 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q, srslte_cell_t cell,
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} else { } else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n", fprintf(stderr, "Invalid parameters\n");
cell.id, cell.nof_ports, cell.nof_prb);
} }
clean_exit: clean_exit:
@ -158,6 +133,70 @@ 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);
}
srslte_pucch_set_threshold(&q->pucch, 0.5, 0.5);
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) int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q, uint16_t rnti)
{ {
if (!q->users[rnti]) { if (!q->users[rnti]) {

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

@ -57,38 +57,28 @@ bool srslte_pcfich_exists(int nframe, int nslot) {
return true; return true;
} }
int srslte_pcfich_init(srslte_pcfich_t *q, srslte_regs_t *regs, srslte_cell_t cell) { int srslte_pcfich_init(srslte_pcfich_t *q) {
return srslte_pcfich_init_multi(q, regs, cell, 1); return srslte_pcfich_init_multi(q, 1);
} }
/** Initializes the pcfich channel receiver. /** Initializes the pcfich channel receiver.
* On error, returns -1 and frees the structrure * 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_multi(srslte_pcfich_t *q, uint32_t nof_rx_antennas) {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL)
regs != NULL &&
srslte_cell_isvalid(&cell))
{ {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_pcfich_t)); 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_rx_antennas = nof_rx_antennas;
q->nof_symbols = PCFICH_RE;
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) { if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
goto clean; 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 */ /* convert cfi bit tables to floats for demodulation */
for (int i=0;i<3;i++) { for (int i=0;i<3;i++) {
for (int j=0;j<PCFICH_CFI_LEN;j++) { for (int j=0;j<PCFICH_CFI_LEN;j++) {
@ -115,6 +105,28 @@ void srslte_pcfich_free(srslte_pcfich_t *q) {
bzero(q, sizeof(srslte_pcfich_t)); 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. /** 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. * Saves the CFI value in the cfi pointer and returns the distance.
*/ */

@ -61,29 +61,24 @@ float srslte_pdcch_coderate(uint32_t nof_bits, uint32_t l) {
} }
/** Initializes the PDCCH transmitter and receiver */ /** Initializes the PDCCH transmitter and receiver */
int srslte_pdcch_init(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell) { int srslte_pdcch_init(srslte_pdcch_t *q, uint32_t max_prb) {
return srslte_pdcch_init_multi(q, regs, cell, 1); return srslte_pdcch_init_multi(q, max_prb, 1);
} }
int srslte_pdcch_init_multi(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas) int srslte_pdcch_init_multi(srslte_pdcch_t *q, uint32_t max_prb, uint32_t nof_rx_antennas)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL)
regs != NULL &&
srslte_cell_isvalid(&cell))
{ {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_pdcch_t)); bzero(q, sizeof(srslte_pdcch_t));
q->cell = cell;
q->regs = regs;
q->nof_rx_antennas = nof_rx_antennas; q->nof_rx_antennas = nof_rx_antennas;
/* Allocate memory for the maximum number of PDCCH bits (CFI=3) */ /* 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", INFO("Init PDCCH: Max bits: %d\n", q->max_bits);
q->max_bits, q->cell.nof_ports);
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) { if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
goto clean; goto clean;
@ -92,14 +87,6 @@ int srslte_pdcch_init_multi(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_
goto clean; 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 }; int poly[3] = { 0x6D, 0x4F, 0x57 };
if (srslte_viterbi_init(&q->decoder, SRSLTE_VITERBI_37, poly, SRSLTE_DCI_MAX_BITS + 16, true)) { if (srslte_viterbi_init(&q->decoder, SRSLTE_VITERBI_37, poly, SRSLTE_DCI_MAX_BITS + 16, true)) {
goto clean; goto clean;
@ -187,6 +174,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 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) uint32_t nsubframe, uint32_t cfi, uint16_t rnti)
{ {

@ -33,6 +33,8 @@
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
#include <srslte/phy/phch/pdsch.h> #include <srslte/phy/phch/pdsch.h>
#include <srslte/phy/phch/pdsch_cfg.h>
#include <srslte/phy/phch/ra.h>
#include "prb_dl.h" #include "prb_dl.h"
#include "srslte/phy/phch/pdsch.h" #include "srslte/phy/phch/pdsch.h"
@ -203,31 +205,23 @@ 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); return srslte_pdsch_cp(q, sf_symbols, symbols, grant, lstart, subframe, false);
} }
int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell)
{
return srslte_pdsch_init_multi(q, cell, 1);
}
/** Initializes the PDCCH transmitter and receiver */ /** Initializes the PDCCH transmitter and receiver */
int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_rx_antennas) int pdsch_init_multi(srslte_pdsch_t *q, uint32_t max_prb, uint32_t nof_rx_antennas, bool is_ue)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
int i; int i;
if (q != NULL && if (q != NULL &&
srslte_cell_isvalid(&cell) &&
nof_rx_antennas <= SRSLTE_MAX_PORTS) nof_rx_antennas <= SRSLTE_MAX_PORTS)
{ {
bzero(q, sizeof(srslte_pdsch_t)); bzero(q, sizeof(srslte_pdsch_t));
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
q->cell = cell; q->max_re = max_prb * MAX_PDSCH_RE(q->cell.cp);
q->max_re = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp);
q->nof_rx_antennas = nof_rx_antennas; q->nof_rx_antennas = nof_rx_antennas;
INFO("Init PDSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports, INFO("Init PDSCH: %d PRBs, max_symbols: %d\n", max_prb, q->max_re);
q->cell.nof_prb, q->max_re);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
if (srslte_modem_table_lte(&q->mod[i], modulations[i])) { if (srslte_modem_table_lte(&q->mod[i], modulations[i])) {
@ -249,11 +243,12 @@ int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_
goto clean; goto clean;
} }
for (i = 0; i < q->cell.nof_ports; i++) { for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re); q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->x[i]) { if (!q->x[i]) {
goto clean; goto clean;
} }
if (is_ue) {
for (int j=0;j<q->nof_rx_antennas;j++) { for (int j=0;j<q->nof_rx_antennas;j++) {
q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re); q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->ce[i][j]) { if (!q->ce[i][j]) {
@ -261,6 +256,7 @@ int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_
} }
} }
} }
}
for (int j=0;j<q->nof_rx_antennas;j++) { for (int j=0;j<q->nof_rx_antennas;j++) {
q->symbols[j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re); q->symbols[j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->symbols[j]) { if (!q->symbols[j]) {
@ -268,12 +264,17 @@ int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_
} }
} }
q->users = calloc(sizeof(srslte_pdsch_user_t*), 1+SRSLTE_SIRNTI); q->is_ue = is_ue;
q->users = calloc(sizeof(srslte_pdsch_user_t*), is_ue?1:(1+SRSLTE_SIRNTI));
if (!q->users) { if (!q->users) {
perror("malloc"); perror("malloc");
goto clean; 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; ret = SRSLTE_SUCCESS;
} }
clean: clean:
@ -283,6 +284,27 @@ int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_
return ret; return ret;
} }
int srslte_pdsch_init_ue(srslte_pdsch_t *q, uint32_t max_prb)
{
return pdsch_init_multi(q, max_prb, 1, true);
}
int srslte_pdsch_init_enb(srslte_pdsch_t *q, uint32_t max_prb)
{
return pdsch_init_multi(q, max_prb, 1, false);
}
int srslte_pdsch_init_multi_ue(srslte_pdsch_t *q, uint32_t max_prb, uint32_t nof_rx_antennas)
{
return pdsch_init_multi(q, max_prb, nof_rx_antennas, true);
}
int srslte_pdsch_init_multi_enb(srslte_pdsch_t *q, uint32_t max_prb, uint32_t nof_rx_antennas)
{
return pdsch_init_multi(q, max_prb, nof_rx_antennas, false);
}
void srslte_pdsch_free(srslte_pdsch_t *q) { void srslte_pdsch_free(srslte_pdsch_t *q) {
int i; int i;
@ -292,7 +314,7 @@ void srslte_pdsch_free(srslte_pdsch_t *q) {
if (q->d) { if (q->d) {
free(q->d); free(q->d);
} }
for (i = 0; i < q->cell.nof_ports; i++) { for (i = 0; i < SRSLTE_MAX_PORTS; i++) {
if (q->x[i]) { if (q->x[i]) {
free(q->x[i]); free(q->x[i]);
} }
@ -308,13 +330,20 @@ void srslte_pdsch_free(srslte_pdsch_t *q) {
} }
} }
if (q->users) { if (q->users) {
if (q->is_ue) {
srslte_pdsch_free_rnti(q, 0);
} else {
for (uint16_t u=0;u<SRSLTE_SIRNTI;u++) { for (uint16_t u=0;u<SRSLTE_SIRNTI;u++) {
if (q->users[u]) { if (q->users[u]) {
srslte_pdsch_free_rnti(q, u); srslte_pdsch_free_rnti(q, u);
} }
} }
}
free(q->users); free(q->users);
} }
srslte_sequence_free(&q->tmp_seq);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
srslte_modem_table_free(&q->mod[i]); srslte_modem_table_free(&q->mod[i]);
} }
@ -325,6 +354,24 @@ void srslte_pdsch_free(srslte_pdsch_t *q) {
} }
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;
}
/* Configures the structure srslte_pdsch_cfg_t from the DL DCI allocation dci_msg. /* Configures the structure srslte_pdsch_cfg_t from the DL DCI allocation dci_msg.
* If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant * If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant
*/ */
@ -354,16 +401,18 @@ int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_g
*/ */
int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) { int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) {
uint32_t i; uint32_t i;
if (!q->users[rnti]) { uint32_t rnti_idx = q->is_ue?0:rnti;
q->users[rnti] = calloc(1, sizeof(srslte_pdsch_user_t));
if (q->users[rnti]) { if (!q->users[rnti_idx]) {
q->users[rnti_idx] = calloc(1, sizeof(srslte_pdsch_user_t));
if (q->users[rnti_idx]) {
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
if (srslte_sequence_pdsch(&q->users[rnti]->seq[i], rnti, 0, 2 * i, q->cell.id, if (srslte_sequence_pdsch(&q->users[rnti_idx]->seq[i], rnti, 0, 2 * i, q->cell.id,
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
} }
q->users[rnti]->sequence_generated = true; q->users[rnti_idx]->sequence_generated = true;
} }
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
@ -371,12 +420,13 @@ int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) {
void srslte_pdsch_free_rnti(srslte_pdsch_t* q, uint16_t rnti) 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 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]); free(q->users[rnti_idx]);
q->users[rnti] = NULL; q->users[rnti_idx] = NULL;
} }
} }
@ -395,6 +445,17 @@ int srslte_pdsch_decode(srslte_pdsch_t *q,
return srslte_pdsch_decode_multi(q, cfg, softbuffer, _sf_symbols, _ce, noise_estimate, rnti, data); return srslte_pdsch_decode_multi(q, cfg, softbuffer, _sf_symbols, _ce, noise_estimate, rnti, data);
} }
static srslte_sequence_t *get_user_sequence(srslte_pdsch_t *q, uint16_t rnti, uint32_t sf_idx, uint32_t len)
{
uint32_t rnti_idx = q->is_ue?0:rnti;
if (q->users[rnti_idx] && q->users[rnti_idx]->sequence_generated) {
return &q->users[rnti_idx]->seq[sf_idx];
} else {
srslte_sequence_pdsch(&q->tmp_seq, rnti, 0, 2 * sf_idx, q->cell.id, len);
return &q->tmp_seq;
}
}
/** Decodes the PDSCH from the received symbols /** Decodes the PDSCH from the received symbols
*/ */
int srslte_pdsch_decode_multi(srslte_pdsch_t *q, int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
@ -468,17 +529,11 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q,
*/ */
srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->e, cfg->nbits.nof_re); srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->e, cfg->nbits.nof_re);
/* descramble */ // Generate scrambling sequence if not pre-generated
if (q->users[rnti] && q->users[rnti]->sequence_generated) { srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits);
srslte_scrambling_s_offset(&q->users[rnti]->seq[cfg->sf_idx], q->e, 0, cfg->nbits.nof_bits);
} else { // Run scrambling
srslte_sequence_t seq; srslte_scrambling_s_offset(seq, q->e, 0, cfg->nbits.nof_bits);
if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
return SRSLTE_ERROR;
}
srslte_scrambling_s_offset(&seq, q->e, 0, cfg->nbits.nof_bits);
srslte_sequence_free(&seq);
}
if (SRSLTE_VERBOSE_ISDEBUG()) { if (SRSLTE_VERBOSE_ISDEBUG()) {
DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n",0); DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n",0);
@ -538,17 +593,10 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
/* scramble */ // Generate scrambling sequence if not pre-generated
if (q->users[rnti] && q->users[rnti]->sequence_generated) { srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits);
srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t*) q->e, cfg->nbits.nof_bits);
} else { srslte_scrambling_bytes(seq, (uint8_t*) q->e, cfg->nbits.nof_bits);
srslte_sequence_t seq;
if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
return SRSLTE_ERROR;
}
srslte_scrambling_bytes(&seq, (uint8_t*) q->e, cfg->nbits.nof_bits);
srslte_sequence_free(&seq);
}
srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e, q->d, cfg->nbits.nof_bits); srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e, q->d, cfg->nbits.nof_bits);

@ -32,6 +32,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/phy/phch/regs.h" #include "srslte/phy/phch/regs.h"
#include "srslte/phy/phch/phich.h" #include "srslte/phy/phch/phich.h"
@ -67,37 +68,27 @@ 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) int srslte_phich_init(srslte_phich_t *q)
{ {
return srslte_phich_init_multi(q, regs, cell, 1); return srslte_phich_init_multi(q, 1);
} }
/** Initializes the phich channel receiver */ /** 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_multi(srslte_phich_t *q, uint32_t nof_rx_antennas)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL)
regs != NULL &&
srslte_cell_isvalid(&cell))
{ {
bzero(q, sizeof(srslte_phich_t)); bzero(q, sizeof(srslte_phich_t));
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
q->cell = cell;
q->regs = regs;
q->nof_rx_antennas = nof_rx_antennas; q->nof_rx_antennas = nof_rx_antennas;
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_BPSK)) { if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_BPSK)) {
goto clean; 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; ret = SRSLTE_SUCCESS;
} }
clean: clean:
@ -114,9 +105,34 @@ void srslte_phich_free(srslte_phich_t *q) {
srslte_modem_table_free(&q->mod); srslte_modem_table_free(&q->mod);
bzero(q, sizeof(srslte_phich_t)); 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 */ /* 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, void srslte_phich_calc(srslte_phich_t *q, uint32_t n_prb_lowest, uint32_t n_dmrs,
uint32_t *ngroup, uint32_t *nseq) uint32_t *ngroup, uint32_t *nseq)

@ -26,6 +26,7 @@
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#include <srslte/srslte.h>
#include "srslte/phy/common/phy_common.h" #include "srslte/phy/common/phy_common.h"
#include "srslte/phy/phch/prach.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 // 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}; 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 // 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}; uint32_t prach_Ncs_restricted[15] = {15,18,22,26,32,38,46,55,68,82,100,128,158,202,237};
@ -328,7 +331,7 @@ 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) int srslte_prach_init_cfg(srslte_prach_t *p, srslte_prach_cfg_t *cfg, uint32_t nof_prb)
{ {
return srslte_prach_init(p, return srslte_prach_set_cell(p,
srslte_symbol_sz(nof_prb), srslte_symbol_sz(nof_prb),
cfg->config_idx, cfg->config_idx,
cfg->root_seq_idx, cfg->root_seq_idx,
@ -336,7 +339,69 @@ int srslte_prach_init_cfg(srslte_prach_t *p, srslte_prach_cfg_t *cfg, uint32_t n
cfg->zero_corr_zone); 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 N_ifft_ul,
uint32_t config_idx, uint32_t config_idx,
uint32_t root_seq_index, uint32_t root_seq_index,
@ -349,6 +414,11 @@ int srslte_prach_init(srslte_prach_t *p,
config_idx < 64 && config_idx < 64 &&
root_seq_index < MAX_ROOTS) 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); uint32_t preamble_format = srslte_prach_get_preamble_format(config_idx);
p->config_idx = config_idx; p->config_idx = config_idx;
p->f = preamble_format; p->f = preamble_format;
@ -368,7 +438,7 @@ int srslte_prach_init(srslte_prach_t *p,
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
}else{ }else{
p->N_zc = 839; p->N_zc = MAX_N_zc;
if(p->hs){ if(p->hs){
if (p->zczc < 15) { if (p->zczc < 15) {
p->N_cs = prach_Ncs_restricted[p->zczc]; p->N_cs = prach_Ncs_restricted[p->zczc];
@ -386,25 +456,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 // Set up ZC FFTS
p->zc_fft = (srslte_dft_plan_t*)srslte_vec_malloc(sizeof(srslte_dft_plan_t)); if (p->N_zc != MAX_N_zc) {
if(srslte_dft_plan(p->zc_fft, p->N_zc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){ if(srslte_dft_replan(&p->zc_fft, p->N_zc)){
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
srslte_dft_plan_set_mirror(p->zc_fft, false); if(srslte_dft_replan(&p->zc_ifft, p->N_zc)){
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)){
return SRSLTE_ERROR; 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 // Generate our 64 sequences
p->N_roots = 0; p->N_roots = 0;
@ -412,7 +472,7 @@ int srslte_prach_init(srslte_prach_t *p,
// Generate sequence FFTs // Generate sequence FFTs
for(int i=0;i<N_SEQS;i++){ 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 // Create our FFT objects and buffers
@ -433,31 +493,15 @@ int srslte_prach_init(srslte_prach_t *p,
p->deadzone = (uint32_t) ceil((float) samp_rate/((float) p->N_zc*subcarrier_spacing)); 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)); if(srslte_dft_replan(&p->ifft, p->N_ifft_prach)) {
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)) {
fprintf(stderr, "Error creating DFT plan\n"); fprintf(stderr, "Error creating DFT plan\n");
return -1; return -1;
} }
srslte_dft_plan_set_mirror(p->ifft, true); if(srslte_dft_replan(&p->fft, p->N_ifft_prach)){
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)){
fprintf(stderr, "Error creating DFT plan\n"); fprintf(stderr, "Error creating DFT plan\n");
return -1; 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_seq = prach_Tseq[p->f]*p->N_ifft_ul/2048;
p->N_cp = prach_Tcp[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; p->T_seq = prach_Tseq[p->f]*SRSLTE_LTE_TS;
@ -500,7 +544,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)); 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)); 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 // Copy CP into buffer
memcpy(signal, &p->ifft_out[p->N_ifft_prach-p->N_cp], p->N_cp*sizeof(cf_t)); memcpy(signal, &p->ifft_out[p->N_ifft_prach-p->N_cp], p->N_cp*sizeof(cf_t));
@ -552,7 +596,7 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
} }
// FFT incoming signal // FFT incoming signal
srslte_dft_run(p->fft, signal, p->signal_fft); srslte_dft_run(&p->fft, signal, p->signal_fft);
*n_indices = 0; *n_indices = 0;
@ -569,7 +613,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_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); srslte_vec_abs_square_cf(p->corr_spec, p->corr, p->N_zc);
@ -632,16 +676,12 @@ int srslte_prach_free(srslte_prach_t *p) {
free(p->prach_bins); free(p->prach_bins);
free(p->corr_spec); free(p->corr_spec);
free(p->corr); free(p->corr);
srslte_dft_plan_free(p->ifft); srslte_dft_plan_free(&p->ifft);
free(p->ifft);
free(p->ifft_in); free(p->ifft_in);
free(p->ifft_out); free(p->ifft_out);
srslte_dft_plan_free(p->fft); srslte_dft_plan_free(&p->fft);
free(p->fft); srslte_dft_plan_free(&p->zc_fft);
srslte_dft_plan_free(p->zc_fft); srslte_dft_plan_free(&p->zc_ifft);
free(p->zc_fft);
srslte_dft_plan_free(p->zc_ifft);
free(p->zc_ifft);
if (p->signal_fft) { if (p->signal_fft) {
free(p->signal_fft); free(p->signal_fft);

@ -417,43 +417,30 @@ void srslte_pucch_set_threshold(srslte_pucch_t *q, float format1, float format1a
} }
/** Initializes the PDCCH transmitter and receiver */ /** 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; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell)) { if (q != NULL) {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_pucch_t)); 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)) { if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
return SRSLTE_ERROR; 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); q->users = calloc(sizeof(srslte_pucch_user_t*), 1+SRSLTE_SIRNTI);
if (!q->users) { if (!q->users) {
perror("malloc"); perror("malloc");
return SRSLTE_ERROR; goto clean_exit;
} }
srslte_uci_cqi_pucch_init(&q->cqi); srslte_uci_cqi_pucch_init(&q->cqi);
q->z = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS);
q->z_tmp = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS);
q->ce = srslte_vec_malloc(sizeof(cf_t)*SRSLTE_PUCCH_MAX_SYMBOLS);
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} }
clean_exit:
if (ret == SRSLTE_ERROR) {
srslte_pucch_free(q);
}
return ret; return ret;
} }
@ -464,20 +451,36 @@ void srslte_pucch_free(srslte_pucch_t *q) {
} }
free(q->users); free(q->users);
} }
if (q->z) {
free(q->z); srslte_modem_table_free(&q->mod);
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 (q->z_tmp) {
free(q->z_tmp); if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) {
return SRSLTE_ERROR;
} }
if (q->ce) {
free(q->ce);
} }
srslte_modem_table_free(&q->mod); ret = SRSLTE_SUCCESS;
bzero(q, sizeof(srslte_pucch_t)); }
return ret;
} }
void srslte_pucch_clear_rnti(srslte_pucch_t *q, uint16_t rnti) { void srslte_pucch_clear_rnti(srslte_pucch_t *q, uint16_t rnti) {
if (q->users[rnti]) { if (q->users[rnti]) {
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
@ -496,6 +499,7 @@ int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t rnti) {
// Precompute scrambling sequence for pucch format 2 // 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)) { 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"); fprintf(stderr, "Error computing PUCCH Format 2 scrambling sequence\n");
srslte_pucch_clear_rnti(q, rnti);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
} }

@ -32,6 +32,8 @@
#include <stdbool.h> #include <stdbool.h>
#include <assert.h> #include <assert.h>
#include <math.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/ch_estimation/refsignal_ul.h"
#include "srslte/phy/phch/pusch.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 */ /** 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 ret = SRSLTE_ERROR_INVALID_INPUTS;
int i; int i;
if (q != NULL && if (q != NULL)
srslte_cell_isvalid(&cell))
{ {
bzero(q, sizeof(srslte_pusch_t)); bzero(q, sizeof(srslte_pusch_t));
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
q->max_re = max_prb * MAX_PUSCH_RE(SRSLTE_CP_NORM);
q->cell = cell; INFO("Init PUSCH: %d PRBs\n", max_prb);
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);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
if (srslte_modem_table_lte(&q->mod[i], modulations[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]); 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) { if (!q->users) {
perror("malloc"); perror("malloc");
goto clean; goto clean;
} }
/* Precompute sequence for type2 frequency hopping */ if (srslte_sequence_init(&q->tmp_seq, q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
if (srslte_sequence_LTE_pr(&q->seq_type2_fo, 210, q->cell.id)) {
fprintf(stderr, "Error initiating type2 frequency hopping sequence\n");
goto clean; goto clean;
} }
srslte_sch_init(&q->ul_sch); 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"); fprintf(stderr, "Error initiating DFT transform precoding\n");
goto clean; goto clean;
} }
@ -244,10 +242,12 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) {
goto clean; goto clean;
} }
if (!q->is_ue) {
q->ce = srslte_vec_malloc(sizeof(cf_t) * q->max_re); q->ce = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->ce) { if (!q->ce) {
goto clean; goto clean;
} }
}
q->z = srslte_vec_malloc(sizeof(cf_t) * q->max_re); q->z = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->z) { if (!q->z) {
goto clean; goto clean;
@ -262,6 +262,14 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) {
return ret; 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) { void srslte_pusch_free(srslte_pusch_t *q) {
int i; int i;
@ -284,13 +292,20 @@ void srslte_pusch_free(srslte_pusch_t *q) {
srslte_dft_precoding_free(&q->dft_precoding); srslte_dft_precoding_free(&q->dft_precoding);
if (q->users) { if (q->users) {
if (q->is_ue) {
srslte_pusch_clear_rnti(q, 0);
} else {
for (int rnti=0;rnti<SRSLTE_SIRNTI;rnti++) { for (int rnti=0;rnti<SRSLTE_SIRNTI;rnti++) {
srslte_pusch_clear_rnti(q, rnti); srslte_pusch_clear_rnti(q, rnti);
} }
}
free(q->users); free(q->users);
} }
srslte_sequence_free(&q->seq_type2_fo); srslte_sequence_free(&q->seq_type2_fo);
srslte_sequence_free(&q->tmp_seq);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
srslte_modem_table_free(&q->mod[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. /* 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 * If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant
*/ */
@ -392,28 +434,47 @@ int srslte_pusch_cfg(srslte_pusch_t *q,
int srslte_pusch_set_rnti(srslte_pusch_t *q, uint16_t rnti) { int srslte_pusch_set_rnti(srslte_pusch_t *q, uint16_t rnti) {
uint32_t i; uint32_t i;
if (!q->users[rnti]) { uint32_t rnti_idx = q->is_ue?0:rnti;
q->users[rnti] = malloc(sizeof(srslte_pusch_user_t));
if (q->users[rnti]) { if (!q->users[rnti_idx]) {
q->users[rnti_idx] = calloc(1, sizeof(srslte_pusch_user_t));
if (q->users[rnti_idx]) {
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
if (srslte_sequence_pusch(&q->users[rnti]->seq[i], rnti, 2 * i, q->cell.id, 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))) { q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
fprintf(stderr, "Error initializing PUSCH scrambling sequence\n");
srslte_pusch_clear_rnti(q, rnti);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
} }
q->users[rnti]->sequences_generated = true; q->users[rnti_idx]->sequence_generated = true;
} }
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
void srslte_pusch_clear_rnti(srslte_pusch_t *q, uint16_t rnti) { void srslte_pusch_clear_rnti(srslte_pusch_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 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_idx]);
q->users[rnti_idx] = NULL;
} }
free(q->users[rnti]); }
q->users[rnti] = NULL;
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;
if (q->users[rnti_idx] && q->users[rnti_idx]->sequence_generated) {
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 +506,11 @@ int srslte_pusch_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softb
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (q->users[rnti] && q->users[rnti]->sequences_generated) { // Generate scrambling sequence if not pre-generated
srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t*) q->q, cfg->nbits.nof_bits); srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits);
} else {
srslte_sequence_t seq; // Run scrambling
if (srslte_sequence_pusch(&seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { srslte_scrambling_bytes(seq, (uint8_t*) q->q, cfg->nbits.nof_bits);
return SRSLTE_ERROR;
}
srslte_scrambling_bytes(&seq, (uint8_t*) q->q, cfg->nbits.nof_bits);
srslte_sequence_free(&seq);
}
// Correct UCI placeholder/repetition bits // Correct UCI placeholder/repetition bits
uint8_t *d = q->q; uint8_t *d = q->q;
@ -528,22 +584,13 @@ int srslte_pusch_decode(srslte_pusch_t *q,
srslte_predecoding_single(q->d, q->ce, q->z, cfg->nbits.nof_re, noise_estimate); srslte_predecoding_single(q->d, q->ce, q->z, cfg->nbits.nof_re, noise_estimate);
// DFT predecoding // 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 // Soft demodulation
srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->q, cfg->nbits.nof_re); srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->q, cfg->nbits.nof_re);
srslte_sequence_t *seq = NULL; // Generate scrambling sequence if not pre-generated
srslte_sequence_t *seq = get_user_sequence(q, rnti, cfg->sf_idx, cfg->nbits.nof_bits);
// 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;
}
}
// Decode RI/HARQ bits before descrambling // Decode RI/HARQ bits before descrambling
if (srslte_ulsch_uci_decode_ri_ack(&q->ul_sch, cfg, softbuffer, q->q, seq->c, uci_data)) { if (srslte_ulsch_uci_decode_ri_ack(&q->ul_sch, cfg, softbuffer, q->q, seq->c, uci_data)) {
@ -554,10 +601,6 @@ int srslte_pusch_decode(srslte_pusch_t *q,
// Descrambling // Descrambling
srslte_scrambling_s_offset(seq, q->q, 0, cfg->nbits.nof_bits); 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); return srslte_ulsch_uci_decode(&q->ul_sch, cfg, softbuffer, q->q, q->g, data, uci_data);
} else { } else {
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;

@ -33,7 +33,6 @@
* 36.211 6.6.1 * 36.211 6.6.1
*/ */
int srslte_sequence_pbch(srslte_sequence_t *seq, srslte_cp_t cp, uint32_t cell_id) { 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); 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 * 36.211 6.7.1
*/ */
int srslte_sequence_pcfich(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_id) { 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); 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 * 36.211 6.9.1
*/ */
int srslte_sequence_phich(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_id) { 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); 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 * 36.211 6.8.2
*/ */
int srslte_sequence_pdcch(srslte_sequence_t *seq, uint32_t nslot, uint32_t cell_id, uint32_t len) { 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); 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 * 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) { 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); 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 * 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) { 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); 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 * 36.211 5.4.2
*/ */
int srslte_sequence_pucch(srslte_sequence_t *seq, uint16_t rnti, uint32_t nslot, uint32_t cell_id) { 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); 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; 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"); fprintf(stderr, "Error initializing equalizer\n");
return -1; return -1;
} }
@ -141,7 +145,11 @@ int base_init() {
return -1; 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"); fprintf(stderr, "Error initiating PBCH\n");
return -1; 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"); fprintf(stderr, "Error creating PBCH object\n");
exit(-1); 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"); fprintf(stderr, "Error initializing equalizer\n");
return -1; return -1;
} }
@ -157,7 +161,11 @@ int base_init() {
return -1; return -1;
} }
if (srslte_pcfich_init(&pcfich, &regs, cell)) { if (srslte_pcfich_init(&pcfich)) {
fprintf(stderr, "Error creating PBCH object\n");
return -1;
}
if (srslte_pcfich_set_cell(&pcfich, &regs, cell)) {
fprintf(stderr, "Error creating PBCH object\n"); fprintf(stderr, "Error creating PBCH object\n");
return -1; return -1;
} }

@ -124,7 +124,11 @@ int main(int argc, char **argv) {
exit(-1); exit(-1);
} }
if (srslte_pcfich_init(&pcfich, &regs, cell)) { if (srslte_pcfich_init(&pcfich)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
if (srslte_pcfich_set_cell(&pcfich, &regs, cell)) {
fprintf(stderr, "Error creating PBCH object\n"); fprintf(stderr, "Error creating PBCH object\n");
exit(-1); 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"); fprintf(stderr, "Error initializing equalizer\n");
return -1; return -1;
} }
@ -167,7 +171,11 @@ int base_init() {
fprintf(stderr, "Error setting CFI %d\n", cfi); fprintf(stderr, "Error setting CFI %d\n", cfi);
return -1; return -1;
} }
if (srslte_pdcch_init(&pdcch, &regs, cell)) { if (srslte_pdcch_init(&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"); fprintf(stderr, "Error creating PDCCH object\n");
exit(-1); exit(-1);
} }

@ -177,7 +177,11 @@ int main(int argc, char **argv) {
exit(-1); exit(-1);
} }
if (srslte_pdcch_init(&pdcch, &regs, cell)) { if (srslte_pdcch_init(&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"); fprintf(stderr, "Error creating PDCCH object\n");
exit(-1); exit(-1);
} }

@ -137,7 +137,11 @@ int base_init() {
exit(-1); exit(-1);
} }
if (srslte_ue_dl_init_multi(&ue_dl, cell, 1)) { if (srslte_ue_dl_init_multi(&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"); fprintf(stderr, "Error initializing UE DL\n");
return -1; return -1;
} }

@ -177,7 +177,11 @@ int main(int argc, char **argv) {
goto quit; goto quit;
} }
if (srslte_pdsch_init(&pdsch, cell)) { if (srslte_pdsch_init_ue(&pdsch, cell.nof_prb)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto quit;
}
if (srslte_pdsch_set_cell(&pdsch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n"); fprintf(stderr, "Error creating PDSCH object\n");
goto quit; goto quit;
} }
@ -202,7 +206,11 @@ int main(int argc, char **argv) {
#endif #endif
srslte_chest_dl_t chest; srslte_chest_dl_t chest;
if (srslte_chest_dl_init(&chest, cell)) { if (srslte_chest_dl_init(&chest, cell.nof_prb)) {
printf("Error initializing equalizer\n");
exit(-1);
}
if (srslte_chest_dl_set_cell(&chest, cell)) {
printf("Error initializing equalizer\n"); printf("Error initializing equalizer\n");
exit(-1); exit(-1);
} }

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

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

@ -85,7 +85,9 @@ int main(int argc, char **argv) {
cf_t preamble[MAX_LEN]; cf_t preamble[MAX_LEN];
memset(preamble, 0, sizeof(cf_t)*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, N_ifft_ul,
config_idx, config_idx,
root_seq_idx, root_seq_idx,

@ -90,7 +90,9 @@ int main(int argc, char **argv) {
cf_t preamble_sum[MAX_LEN]; cf_t preamble_sum[MAX_LEN];
memset(preamble_sum, 0, sizeof(cf_t)*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, N_ifft_ul,
preamble_format, preamble_format,
root_seq_idx, root_seq_idx,

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

@ -87,11 +87,19 @@ int main(int argc, char **argv) {
parse_args(argc,argv); parse_args(argc,argv);
if (srslte_pucch_init(&pucch, cell)) { if (srslte_pucch_init(&pucch)) {
fprintf(stderr, "Error creating PDSCH object\n"); fprintf(stderr, "Error creating PDSCH object\n");
exit(-1); 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"); fprintf(stderr, "Error creating PDSCH object\n");
exit(-1); exit(-1);
} }

@ -110,7 +110,8 @@ void parse_args(int argc, char **argv) {
} }
int main(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; uint8_t *data = NULL;
cf_t *sf_symbols = NULL; cf_t *sf_symbols = NULL;
cf_t *ce = NULL; cf_t *ce = NULL;
@ -145,8 +146,20 @@ int main(int argc, char **argv) {
ul_hopping.hopping_offset = 0; ul_hopping.hopping_offset = 0;
ul_hopping.hop_mode = SRSLTE_PUSCH_HOP_MODE_INTER_SF; ul_hopping.hop_mode = SRSLTE_PUSCH_HOP_MODE_INTER_SF;
if (srslte_pusch_init(&pusch, cell)) { if (srslte_pusch_init_ue(&pusch_tx, cell.nof_prb)) {
fprintf(stderr, "Error creating PDSCH object\n"); 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; goto quit;
} }
@ -159,13 +172,18 @@ int main(int argc, char **argv) {
uci_cfg.I_offset_ri = 2; uci_cfg.I_offset_ri = 2;
uci_cfg.I_offset_ack = 4; 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"); fprintf(stderr, "Error configuring PDSCH\n");
exit(-1); exit(-1);
} }
uint16_t rnti = 1234; 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_tx;
srslte_uci_data_t uci_data_rx; srslte_uci_data_t uci_data_rx;
@ -211,13 +229,13 @@ int main(int argc, char **argv) {
uint32_t ntrials = 100; 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"); fprintf(stderr, "Error encoding TB\n");
exit(-1); exit(-1);
} }
if (rv_idx > 0) { if (rv_idx > 0) {
cfg.rv = rv_idx; 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"); fprintf(stderr, "Error encoding TB\n");
exit(-1); exit(-1);
} }
@ -233,7 +251,7 @@ int main(int argc, char **argv) {
} }
gettimeofday(&t[1], NULL); 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); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);
if (r) { if (r) {
@ -265,7 +283,8 @@ int main(int argc, char **argv) {
} }
quit: quit:
srslte_pusch_free(&pusch); srslte_pusch_free(&pusch_tx);
srslte_pusch_free(&pusch_rx);
srslte_softbuffer_tx_free(&softbuffer_tx); srslte_softbuffer_tx_free(&softbuffer_tx);
if (sf_symbols) { if (sf_symbols) {

@ -28,6 +28,7 @@
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include <strings.h> #include <strings.h>
#include <srslte/srslte.h>
#include "srslte/phy/resampling/interp.h" #include "srslte/phy/resampling/interp.h"
#include "srslte/phy/utils/vector.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; return SRSLTE_ERROR;
} }
q->vector_len = vector_len; q->vector_len = vector_len;
q->max_vector_len = vector_len;
} }
return ret; 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) { void srslte_interp_linear_vector_free(srslte_interp_linsrslte_vec_t *q) {
if (q->diff_vec) { if (q->diff_vec) {
free(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->vector_len = vector_len;
q->M = M; q->M = M;
q->max_vector_len = vector_len;
q->max_M = M;
} }
return ret; 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, void srslte_interp_linear_offset(srslte_interp_lin_t *q, cf_t *input, cf_t *output,
uint32_t off_st, uint32_t off_end) uint32_t off_st, uint32_t off_end)
{ {

@ -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; srslte_ue_mib_sync_t ue_mib;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; 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"); fprintf(stderr, "Error initiating srslte_ue_mib_sync\n");
goto clean_exit; 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"); fprintf(stderr, "Error initiating UE cell detect\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (config->nof_valid_pss_frames) { if (config->nof_valid_pss_frames) {
srslte_ue_cellsearch_set_nof_valid_frames(&cs, 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" #include "srslte/phy/scrambling/scrambling.h"
void srslte_scrambling_f(srslte_sequence_t *s, float *data) { 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) { 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); srslte_vec_prod_fff(data, &s->c_float[offset], data, len);
} }
void srslte_scrambling_s(srslte_sequence_t *s, short *data) { 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) { 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); srslte_vec_prod_sss(data, &s->c_short[offset], data, len);
} }
void srslte_scrambling_c(srslte_sequence_t *s, cf_t *data) { 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) { 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); 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) { 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) { 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) { int init_sequence(srslte_sequence_t *seq, char *name) {
if (!strcmp(name, "PBCH")) { if (!strcmp(name, "PBCH")) {
bzero(seq, sizeof(srslte_sequence_t));
return srslte_sequence_pbch(seq, cp, cell_id); return srslte_sequence_pbch(seq, cp, cell_id);
} else if (!strcmp(name, "PDSCH")) { } else if (!strcmp(name, "PDSCH")) {
bzero(seq, sizeof(srslte_sequence_t));
return srslte_sequence_pdsch(seq, 1234, 0, 0, cell_id, nof_bits); return srslte_sequence_pdsch(seq, 1234, 0, 0, cell_id, nof_bits);
} else { } else {
fprintf(stderr, "Unsupported sequence name %s\n", name); fprintf(stderr, "Unsupported sequence name %s\n", name);
@ -109,18 +111,18 @@ int main(int argc, char **argv) {
} }
if (!do_floats) { if (!do_floats) {
input_b = malloc(sizeof(uint8_t) * seq.len); input_b = malloc(sizeof(uint8_t) * seq.cur_len);
if (!input_b) { if (!input_b) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);
} }
scrambled_b = malloc(sizeof(uint8_t) * seq.len); scrambled_b = malloc(sizeof(uint8_t) * seq.cur_len);
if (!scrambled_b) { if (!scrambled_b) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);
} }
for (i=0;i<seq.len;i++) { for (i=0;i<seq.cur_len;i++) {
input_b[i] = rand()%2; input_b[i] = rand()%2;
scrambled_b[i] = input_b[i]; scrambled_b[i] = input_b[i];
} }
@ -131,9 +133,9 @@ int main(int argc, char **argv) {
srslte_scrambling_b(&seq, scrambled_b); srslte_scrambling_b(&seq, scrambled_b);
get_time_interval(t); 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]) { if (scrambled_b[i] != input_b[i]) {
printf("Error in %d\n", i); printf("Error in %d\n", i);
exit(-1); exit(-1);
@ -142,18 +144,18 @@ int main(int argc, char **argv) {
free(input_b); free(input_b);
free(scrambled_b); free(scrambled_b);
} else { } else {
input_f = malloc(sizeof(float) * seq.len); input_f = malloc(sizeof(float) * seq.cur_len);
if (!input_f) { if (!input_f) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);
} }
scrambled_f = malloc(sizeof(float) * seq.len); scrambled_f = malloc(sizeof(float) * seq.cur_len);
if (!scrambled_f) { if (!scrambled_f) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);
} }
for (i=0;i<seq.len;i++) { for (i=0;i<seq.cur_len;i++) {
input_f[i] = 100*(rand()/RAND_MAX); input_f[i] = 100*(rand()/RAND_MAX);
scrambled_f[i] = input_f[i]; scrambled_f[i] = input_f[i];
} }
@ -164,9 +166,9 @@ int main(int argc, char **argv) {
srslte_scrambling_f(&seq, scrambled_f); srslte_scrambling_f(&seq, scrambled_f);
get_time_interval(t); 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]) { if (scrambled_f[i] != input_f[i]) {
printf("Error in %d\n", i); printf("Error in %d\n", i);
exit(-1); exit(-1);

@ -27,6 +27,7 @@
#include <strings.h> #include <strings.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
#include <srslte/srslte.h>
#include "srslte/phy/utils/cexptab.h" #include "srslte/phy/utils/cexptab.h"
#include "srslte/phy/sync/cfo.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->tol = SRSLTE_CFO_TOLERANCE;
h->last_freq = 0; h->last_freq = 0;
h->nsamples = nsamples; h->nsamples = nsamples;
h->max_samples = nsamples;
srslte_cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, h->nsamples); srslte_cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, h->nsamples);
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
@ -69,14 +71,14 @@ void srslte_cfo_set_tol(srslte_cfo_t *h, float tol) {
h->tol = tol; h->tol = tol;
} }
int srslte_cfo_realloc(srslte_cfo_t *h, uint32_t samples) { int srslte_cfo_resize(srslte_cfo_t *h, uint32_t samples) {
h->cur_cexp = realloc(h->cur_cexp, sizeof(cf_t) * samples); if (samples <= h->max_samples) {
if (!h->cur_cexp) {
perror("realloc");
return SRSLTE_ERROR;
}
srslte_cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, samples); srslte_cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, samples);
h->nsamples = 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; return SRSLTE_SUCCESS;
} }

@ -25,6 +25,7 @@
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <srslte/srslte.h>
#include "srslte/phy/sync/cp.h" #include "srslte/phy/sync/cp.h"
#include "srslte/phy/utils/vector.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) int srslte_cp_synch_init(srslte_cp_synch_t *q, uint32_t symbol_sz)
{ {
q->symbol_sz = symbol_sz; q->symbol_sz = symbol_sz;
q->max_symbol_sz = symbol_sz;
q->corr = srslte_vec_malloc(sizeof(cf_t) * q->symbol_sz); q->corr = srslte_vec_malloc(sizeof(cf_t) * q->symbol_sz);
if (!q->corr) { 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) 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) { if (max_offset > q->symbol_sz) {

@ -93,7 +93,9 @@ 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 * 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. * 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; int ret = SRSLTE_ERROR_INVALID_INPUTS;
@ -108,17 +110,19 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, uint32_t frame
q->N_id_2 = 10; q->N_id_2 = 10;
q->ema_alpha = 0.2; q->ema_alpha = 0.2;
q->max_fft_size = max_fft_size;
q->max_frame_size = max_frame_size;
q->decimate = decimate; q->decimate = decimate;
fft_size = fft_size/q->decimate; uint32_t fft_size = max_fft_size/q->decimate;
frame_size = frame_size/q->decimate; uint32_t frame_size = max_frame_size/q->decimate;
q->fft_size = fft_size; q->fft_size = fft_size;
q->frame_size = frame_size; q->frame_size = frame_size;
buffer_size = fft_size + frame_size + 1; buffer_size = fft_size + frame_size + 1;
if(q->decimate > 1) if(q->decimate > 1) {
{
int filter_order = 3; int filter_order = 3;
srslte_filt_decim_cc_init(&q->filter,q->decimate,filter_order); srslte_filt_decim_cc_init(&q->filter,q->decimate,filter_order);
q->filter.filter_output = srslte_vec_malloc((buffer_size) * sizeof(cf_t)); q->filter.filter_output = srslte_vec_malloc((buffer_size) * sizeof(cf_t));
@ -175,7 +179,6 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, uint32_t frame
goto clean_and_exit; goto clean_and_exit;
} }
bzero(&q->pss_signal_time[N_id_2][q->fft_size], q->frame_size * sizeof(cf_t)); bzero(&q->pss_signal_time[N_id_2][q->fft_size], q->frame_size * sizeof(cf_t));
} }
#ifdef CONVOLUTION_FFT #ifdef CONVOLUTION_FFT
@ -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) { void srslte_pss_synch_free(srslte_pss_synch_t *q) {
uint32_t i; 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); srslte_dft_plan_set_dc(&q->dftp_input, true);
q->fft_size = fft_size; q->fft_size = fft_size;
q->max_fft_size = fft_size;
generate_N_id_1_table(q->N_id_1_table); 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; 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 && if (q != NULL &&
fft_size <= 2048) fft_size <= 2048)
{ {
srslte_dft_plan_free(&q->dftp_input); if (fft_size > q->max_fft_size) {
if (srslte_dft_plan(&q->dftp_input, fft_size, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)) { 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); srslte_sss_synch_free(q);
return SRSLTE_ERROR; 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; q->fft_size = fft_size;
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }

@ -28,6 +28,7 @@
#include <strings.h> #include <strings.h>
#include <complex.h> #include <complex.h>
#include <math.h> #include <math.h>
#include <srslte/srslte.h>
#include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/debug.h"
#include "srslte/phy/common/phy_common.h" #include "srslte/phy/common/phy_common.h"
@ -36,7 +37,7 @@
#include "srslte/phy/sync/cfo.h" #include "srslte/phy/sync/cfo.h"
#define MEANPEAK_EMA_ALPHA 0.1 #define MEANPEAK_EMA_ALPHA 0.1
#define CFO_EMA_ALPHA 0.1 #define CFO_EMA_ALPHA 0.2
#define CP_EMA_ALPHA 0.1 #define CP_EMA_ALPHA 0.1
static bool fft_size_isvalid(uint32_t fft_size) { static bool fft_size_isvalid(uint32_t fft_size) {
@ -77,6 +78,7 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o
q->frame_size = frame_size; q->frame_size = frame_size;
q->max_offset = max_offset; q->max_offset = max_offset;
q->sss_alg = SSS_FULL; q->sss_alg = SSS_FULL;
q->max_frame_size = frame_size;
q->enable_cfo_corr = true; q->enable_cfo_corr = true;
if (srslte_cfo_init(&q->cfocorr, q->frame_size)) { if (srslte_cfo_init(&q->cfocorr, q->frame_size)) {
@ -91,8 +93,6 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o
// Set a CFO tolerance of approx 50 Hz // Set a CFO tolerance of approx 50 Hz
srslte_cfo_set_tol(&q->cfocorr, 50.0/(15000.0*q->fft_size)); 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)); srslte_cfo_set_tol(&q->cfocorr2, 50.0/(15000.0*q->fft_size));
for (int i=0;i<2;i++) { for (int i=0;i<2;i++) {
@ -114,7 +114,6 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o
if(!decimate) if(!decimate)
decimate = 1; decimate = 1;
if (srslte_pss_synch_init_fft_offset_decim(&q->pss, max_offset, fft_size,0,decimate)) { if (srslte_pss_synch_init_fft_offset_decim(&q->pss, max_offset, fft_size,0,decimate)) {
fprintf(stderr, "Error initializing PSS object\n"); fprintf(stderr, "Error initializing PSS object\n");
goto clean_exit; goto clean_exit;
@ -162,6 +161,77 @@ 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_cfo_set_tol(&q->cfocorr, 50.0/(15000.0*q->fft_size));
srslte_cfo_set_tol(&q->cfocorr2, 50.0/(15000.0*q->fft_size));
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_threshold(srslte_sync_t *q, float threshold) { void srslte_sync_set_threshold(srslte_sync_t *q, float threshold) {
q->threshold = threshold; q->threshold = threshold;
} }

@ -29,6 +29,7 @@
#include <strings.h> #include <strings.h>
#include <assert.h> #include <assert.h>
#include <unistd.h> #include <unistd.h>
#include <srslte/srslte.h>
#include "srslte/phy/ue/ue_cell_search.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.id = SRSLTE_CELL_ID_UNKNOWN;
cell.nof_prb = SRSLTE_CS_NOF_PRB; 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"); fprintf(stderr, "Error initiating ue_sync\n");
goto clean_exit; 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.id = SRSLTE_CELL_ID_UNKNOWN;
cell.nof_prb = SRSLTE_CS_NOF_PRB; 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"); fprintf(stderr, "Error initiating ue_sync\n");
goto clean_exit; goto clean_exit;
} }
@ -243,6 +253,7 @@ int srslte_ue_cellsearch_scan(srslte_ue_cellsearch_t * q,
int ret = 0; int ret = 0;
float max_peak_value = -1.0; float max_peak_value = -1.0;
uint32_t nof_detected_cells = 0; uint32_t nof_detected_cells = 0;
for (uint32_t N_id_2=0;N_id_2<3 && ret >= 0;N_id_2++) { 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]); ret = srslte_ue_cellsearch_scan_N_id_2(q, N_id_2, &found_cells[N_id_2]);
if (ret < 0) { if (ret < 0) {
@ -275,6 +286,10 @@ int srslte_ue_cellsearch_scan_N_id_2(srslte_ue_cellsearch_t * q,
{ {
ret = SRSLTE_SUCCESS; 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_set_N_id_2(&q->ue_sync, N_id_2);
srslte_ue_sync_reset(&q->ue_sync); srslte_ue_sync_reset(&q->ue_sync);
do { do {

@ -37,6 +37,7 @@
#define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp) #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 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)
static srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1}; // Only TM1 and TM2 are currently supported static srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1}; // Only TM1 and TM2 are currently supported
const uint32_t nof_ue_formats = 2; const uint32_t nof_ue_formats = 2;
@ -45,80 +46,74 @@ static srslte_dci_format_t common_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FO
const uint32_t nof_common_formats = 2; const uint32_t nof_common_formats = 2;
int srslte_ue_dl_init(srslte_ue_dl_t *q, int srslte_ue_dl_init(srslte_ue_dl_t *q,
srslte_cell_t cell) uint32_t max_prb)
{ {
return srslte_ue_dl_init_multi(q, cell, 1); return srslte_ue_dl_init_multi(q, max_prb, 1);
} }
int srslte_ue_dl_init_multi(srslte_ue_dl_t *q, int srslte_ue_dl_init_multi(srslte_ue_dl_t *q,
srslte_cell_t cell, uint32_t max_prb,
uint32_t nof_rx_antennas) uint32_t nof_rx_antennas)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL &&
nof_rx_antennas <= SRSLTE_MAX_PORTS && nof_rx_antennas <= SRSLTE_MAX_PORTS)
srslte_cell_isvalid(&cell))
{ {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_ue_dl_t)); bzero(q, sizeof(srslte_ue_dl_t));
q->cell = cell;
q->pkt_errors = 0; q->pkt_errors = 0;
q->pkts_total = 0; q->pkts_total = 0;
q->pending_ul_dci_rnti = 0; q->pending_ul_dci_rnti = 0;
q->sample_offset = 0; q->sample_offset = 0;
q->nof_rx_antennas = nof_rx_antennas; 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"); fprintf(stderr, "Error initiating FFT\n");
goto clean_exit; 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"); fprintf(stderr, "Error initiating channel estimator\n");
goto clean_exit; goto clean_exit;
} }
if (srslte_regs_init(&q->regs, q->cell)) { if (srslte_pcfich_init_multi(&q->pcfich, nof_rx_antennas)) {
fprintf(stderr, "Error initiating REGs\n");
goto clean_exit;
}
if (srslte_pcfich_init_multi(&q->pcfich, &q->regs, q->cell, nof_rx_antennas)) {
fprintf(stderr, "Error creating PCFICH object\n"); fprintf(stderr, "Error creating PCFICH object\n");
goto clean_exit; goto clean_exit;
} }
if (srslte_phich_init(&q->phich, &q->regs, q->cell)) { if (srslte_phich_init(&q->phich)) {
fprintf(stderr, "Error creating PHICH object\n"); fprintf(stderr, "Error creating PHICH object\n");
goto clean_exit; goto clean_exit;
} }
if (srslte_pdcch_init_multi(&q->pdcch, &q->regs, q->cell, nof_rx_antennas)) { if (srslte_pdcch_init_multi(&q->pdcch, max_prb, nof_rx_antennas)) {
fprintf(stderr, "Error creating PDCCH object\n"); fprintf(stderr, "Error creating PDCCH object\n");
goto clean_exit; goto clean_exit;
} }
if (srslte_pdsch_init_multi(&q->pdsch, q->cell, nof_rx_antennas)) { if (srslte_pdsch_init_multi_ue(&q->pdsch, max_prb, nof_rx_antennas)) {
fprintf(stderr, "Error creating PDSCH object\n"); fprintf(stderr, "Error creating PDSCH object\n");
goto clean_exit; goto clean_exit;
} }
if (srslte_softbuffer_rx_init(&q->softbuffer, q->cell.nof_prb)) { if (srslte_softbuffer_rx_init(&q->softbuffer, max_prb)) {
fprintf(stderr, "Error initiating soft buffer\n"); fprintf(stderr, "Error initiating soft buffer\n");
goto clean_exit; 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"); fprintf(stderr, "Error initiating SFO correct\n");
goto clean_exit; goto clean_exit;
} }
srslte_cfo_set_tol(&q->sfo_correct, 1e-5/q->fft.symbol_sz); srslte_cfo_set_tol(&q->sfo_correct, 1e-5/q->fft.symbol_sz);
for (int j=0;j<nof_rx_antennas;j++) { 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]) { if (!q->sf_symbols_m[j]) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
} }
for (uint32_t i=0;i<q->cell.nof_ports;i++) { for (uint32_t i=0;i<SRSLTE_MAX_PORTS;i++) {
q->ce_m[i][j] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); q->ce_m[i][j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t));
if (!q->ce_m[i][j]) { if (!q->ce_m[i][j]) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
@ -127,14 +122,13 @@ int srslte_ue_dl_init_multi(srslte_ue_dl_t *q,
} }
q->sf_symbols = q->sf_symbols_m[0]; 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]; q->ce[i] = q->ce_m[i][0];
} }
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} else { } else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n", fprintf(stderr, "Invalid parametres\n");
cell.id, cell.nof_ports, cell.nof_prb);
} }
clean_exit: clean_exit:
@ -159,7 +153,7 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) {
if (q->sf_symbols_m[j]) { if (q->sf_symbols_m[j]) {
free(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]) { if (q->ce_m[i][j]) {
free(q->ce_m[i][j]); free(q->ce_m[i][j]);
} }
@ -169,6 +163,67 @@ 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;
}
}
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 /* 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. * 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 * For the connection procedure, use srslte_pusch_encode_rnti() or srslte_pusch_decode_rnti() functions
@ -566,11 +621,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) { 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)); 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) { 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_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)); srslte_vec_save_file("pcfich_ce1", q->pcfich.ce[1], q->pcfich.nof_symbols*sizeof(cf_t));
@ -585,8 +640,9 @@ void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuf
srslte_vec_save_file("pdcch_llr", q->pdcch.llr, q->pdcch.nof_cce*72*sizeof(float)); srslte_vec_save_file("pdcch_llr", q->pdcch.llr, q->pdcch.nof_cce*72*sizeof(float));
srslte_vec_save_file("pdsch_symbols", q->pdsch.d, q->pdsch_cfg.nbits.nof_re*sizeof(cf_t)); srslte_vec_save_file("pdsch_symbols", q->pdsch.symbols[0], q->pdsch_cfg.nbits.nof_re*sizeof(cf_t));
srslte_vec_save_file("llr", q->pdsch.e, q->pdsch_cfg.nbits.nof_bits*sizeof(cf_t)); srslte_vec_save_file("pdsch_eq_symbols", q->pdsch.d, q->pdsch_cfg.nbits.nof_re*sizeof(cf_t));
srslte_vec_save_file("pdsch_llr", q->pdsch.e, q->pdsch_cfg.nbits.nof_bits*sizeof(cf_t));
int cb_len = q->pdsch_cfg.cb_segm.K1; int cb_len = q->pdsch_cfg.cb_segm.K1;
for (int i=0;i<q->pdsch_cfg.cb_segm.C;i++) { for (int i=0;i<q->pdsch_cfg.cb_segm.C;i++) {
char tmpstr[64]; char tmpstr[64];

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

@ -29,6 +29,7 @@
#include <strings.h> #include <strings.h>
#include <assert.h> #include <assert.h>
#include <unistd.h> #include <unistd.h>
#include <srslte/srslte.h>
#include "srslte/phy/ue/ue_sync.h" #include "srslte/phy/ue/ue_sync.h"
@ -122,29 +123,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, 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*), int (recv_callback)(void*, void*, uint32_t,srslte_timestamp_t*),
void *stream_handler) 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->recv_callback_single = recv_callback;
q->stream_single = stream_handler; q->stream_single = stream_handler;
return ret; return ret;
} }
int srslte_ue_sync_init_multi(srslte_ue_sync_t *q, 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*), int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t,srslte_timestamp_t*),
uint32_t nof_rx_antennas, uint32_t nof_rx_antennas,
void *stream_handler) 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, 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*), int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t,srslte_timestamp_t*),
uint32_t nof_rx_antennas, uint32_t nof_rx_antennas,
void *stream_handler, void *stream_handler,
@ -154,7 +158,6 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
if (q != NULL && if (q != NULL &&
stream_handler != NULL && stream_handler != NULL &&
srslte_nofprb_isvalid(cell.nof_prb) &&
nof_rx_antennas <= SRSLTE_MAX_PORTS && nof_rx_antennas <= SRSLTE_MAX_PORTS &&
recv_callback != NULL) recv_callback != NULL)
{ {
@ -165,8 +168,7 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
q->stream = stream_handler; q->stream = stream_handler;
q->recv_callback = recv_callback; q->recv_callback = recv_callback;
q->nof_rx_antennas = nof_rx_antennas; q->nof_rx_antennas = nof_rx_antennas;
q->cell = cell; q->fft_size = srslte_symbol_sz(max_prb);
q->fft_size = srslte_symbol_sz(q->cell.nof_prb);
q->sf_len = SRSLTE_SF_LEN(q->fft_size); q->sf_len = SRSLTE_SF_LEN(q->fft_size);
q->file_mode = false; q->file_mode = false;
q->correct_cfo = true; q->correct_cfo = true;
@ -174,34 +176,31 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
q->sample_offset_correct_period = DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD; q->sample_offset_correct_period = DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD;
q->sfo_ema = DEFAULT_SFO_EMA_COEFF; 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 */ /* If the cell is unkown, we search PSS/SSS in 5 ms */
q->nof_recv_sf = 5; q->nof_recv_sf = 5;
q->decode_sss_on_track = true;
} else { } else {
/* If the cell is known, we work on a 1ms basis */ /* If the cell is known, we work on a 1ms basis */
q->nof_recv_sf = 1; q->nof_recv_sf = 1;
q->decode_sss_on_track = true;
} }
q->frame_len = q->nof_recv_sf*q->sf_len; 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; q->decimate = 1;
} }
if(srslte_sync_init_decim(&q->sfind, q->frame_len, q->frame_len, q->fft_size,q->decimate)) { 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"); fprintf(stderr, "Error initiating sync find\n");
goto clean_exit; 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)) { if(srslte_sync_init(&q->strack, q->frame_len, TRACK_FRAME_SIZE, q->fft_size)) {
fprintf(stderr, "Error initiating sync track\n"); fprintf(stderr, "Error initiating sync track\n");
goto clean_exit; goto clean_exit;
@ -213,6 +212,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 (cell.id == 1000) {
/* If the cell id is unknown, enable CP detection on find */ /* If the cell id is unknown, enable CP detection on find */
// FIXME: CP detection not working very well. Not supporting Extended CP right now // FIXME: CP detection not working very well. Not supporting Extended CP right now
@ -258,29 +341,9 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} }
clean_exit:
if (ret == SRSLTE_ERROR) {
srslte_ue_sync_free(q);
}
return ret; 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) { 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)); memcpy(timestamp, &q->last_timestamp, sizeof(srslte_timestamp_t));
@ -642,7 +705,7 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE
} }
if (q->correct_cfo) { if (q->correct_cfo) {
for (int i=0;i<q->nof_rx_antennas;i++) { 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],
input_buffer[i], input_buffer[i],
-srslte_sync_get_cfo(&q->strack) / q->fft_size); -srslte_sync_get_cfo(&q->strack) / q->fft_size);

@ -36,22 +36,20 @@
#define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp) #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 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))
int srslte_ue_ul_init(srslte_ue_ul_t *q, int srslte_ue_ul_init(srslte_ue_ul_t *q,
srslte_cell_t cell) uint32_t max_prb)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL)
srslte_cell_isvalid(&cell))
{ {
ret = SRSLTE_ERROR; ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_ue_ul_t)); bzero(q, sizeof(srslte_ue_ul_t));
q->cell = cell; if (srslte_ofdm_tx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) {
if (srslte_ofdm_tx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating FFT\n"); fprintf(stderr, "Error initiating FFT\n");
goto clean_exit; goto clean_exit;
} }
@ -60,41 +58,41 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
q->normalize_en = false; 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"); fprintf(stderr, "Error creating CFO object\n");
goto clean_exit; goto clean_exit;
} }
srslte_cfo_set_tol(&q->cfo, 0); srslte_cfo_set_tol(&q->cfo, 0);
if (srslte_pusch_init(&q->pusch, q->cell)) { if (srslte_pusch_init_ue(&q->pusch, max_prb)) {
fprintf(stderr, "Error creating PUSCH object\n"); fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit; goto clean_exit;
} }
if (srslte_pucch_init(&q->pucch, q->cell)) { if (srslte_pucch_init(&q->pucch)) {
fprintf(stderr, "Error creating PUSCH object\n"); fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit; 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"); fprintf(stderr, "Error initiating soft buffer\n");
goto clean_exit; 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"); fprintf(stderr, "Error initiating srslte_refsignal_ul\n");
goto clean_exit; 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) { if (!q->sf_symbols) {
perror("malloc"); perror("malloc");
goto clean_exit; 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) { if (!q->refsignal) {
perror("malloc"); perror("malloc");
goto clean_exit; 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) { if (!q->srs_signal) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
@ -102,8 +100,7 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
q->signals_pregenerated = false; q->signals_pregenerated = false;
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} else { } else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n", fprintf(stderr, "Invalid parameters\n");
cell.id, cell.nof_ports, cell.nof_prb);
} }
clean_exit: clean_exit:
@ -115,7 +112,7 @@ clean_exit:
void srslte_ue_ul_free(srslte_ue_ul_t *q) { void srslte_ue_ul_free(srslte_ue_ul_t *q) {
if (q) { if (q) {
srslte_ofdm_rx_free(&q->fft); srslte_ofdm_tx_free(&q->fft);
srslte_pusch_free(&q->pusch); srslte_pusch_free(&q->pusch);
srslte_pucch_free(&q->pucch); srslte_pucch_free(&q->pucch);
srslte_softbuffer_tx_free(&q->softbuffer); srslte_softbuffer_tx_free(&q->softbuffer);
@ -140,6 +137,48 @@ 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_cfo_set_tol(&q->cfo, 50.0/(15000.0*srslte_symbol_sz(q->cell.nof_prb)));
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(srslte_ue_ul_t *q, float cur_cfo) { void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q, float cur_cfo) {
q->current_cfo = cur_cfo; q->current_cfo = cur_cfo;
} }
@ -154,7 +193,7 @@ void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q, bool enabled)
q->normalize_en = 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. * 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 * For the connection procedure, use srslte_pusch_encode_rnti() or srslte_pusch_decode_rnti() functions
*/ */

@ -27,6 +27,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <srslte/srslte.h>
#include "srslte/phy/dft/dft.h" #include "srslte/phy/dft/dft.h"
#include "srslte/phy/utils/vector.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) { 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->input_len = input_len;
q->filter_len = filter_len; q->filter_len = filter_len;
q->output_len = input_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->input_fft = srslte_vec_malloc(sizeof(cf_t)*q->output_len);
q->filter_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); q->output_fft = srslte_vec_malloc(sizeof(cf_t)*q->output_len);
if (!q->input_fft || !q->filter_fft || !q->output_fft) { if (!q->input_fft || !q->filter_fft || !q->output_fft) {
return SRSLTE_ERROR; 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; 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) { void srslte_conv_fft_cc_free(srslte_conv_fft_cc_t *q) {
if (q->input_fft) { if (q->input_fft) {
free(q->input_fft); free(q->input_fft);

@ -44,11 +44,10 @@ gw::gw()
:if_up(false) :if_up(false)
{} {}
void gw::init(srsue::pdcp_interface_gw *pdcp_, srsue::rrc_interface_gw *rrc_, srsue::ue_interface *ue_, log *gw_log_) void gw::init(srsue::pdcp_interface_gw *pdcp_, srsue::ue_interface *ue_, log *gw_log_)
{ {
pool = byte_buffer_pool::get_instance(); pool = byte_buffer_pool::get_instance();
pdcp = pdcp_; pdcp = pdcp_;
rrc = rrc_;
ue = ue_; ue = ue_;
gw_log = gw_log_; gw_log = gw_log_;
run_enable = true; run_enable = true;
@ -249,11 +248,6 @@ void gw::run_thread()
{ {
gw_log->info_hex(pdu->msg, pdu->N_bytes, "TX PDU"); gw_log->info_hex(pdu->msg, pdu->N_bytes, "TX PDU");
while(run_enable && (!rrc->is_connected() || !rrc->have_drb())) {
rrc->connect();
usleep(1000);
}
if (!run_enable) { if (!run_enable) {
break; break;
} }

@ -93,12 +93,17 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_)
fprintf(stderr, "Error allocating memory\n"); fprintf(stderr, "Error allocating memory\n");
return; return;
} }
if (srslte_enb_dl_init(&enb_dl, phy->cell)) { if (srslte_enb_dl_init(&enb_dl, phy->cell.nof_prb)) {
fprintf(stderr, "Error initiating ENB DL\n"); fprintf(stderr, "Error initiating ENB DL\n");
return; return;
} }
if (srslte_enb_dl_set_cell(&enb_dl, phy->cell)) {
fprintf(stderr, "Error initiating ENB DL\n");
return;
}
srslte_enb_ul_init(&enb_ul, phy->cell.nof_prb);
if (srslte_enb_ul_init(&enb_ul, if (srslte_enb_ul_set_cell(&enb_ul,
phy->cell, phy->cell,
NULL, NULL,
&phy->pusch_cfg, &phy->pusch_cfg,

@ -163,7 +163,6 @@ private:
// pointer to MAC PCAP object // pointer to MAC PCAP object
srslte::mac_pcap* pcap; srslte::mac_pcap* pcap;
bool signals_pregenerated;
bool is_first_ul_grant; bool is_first_ul_grant;

@ -45,6 +45,7 @@ class phch_recv : public thread
{ {
public: public:
phch_recv(); phch_recv();
~phch_recv();
void init(srslte::radio_multi* radio_handler, mac_interface_phy *mac,rrc_interface_phy *rrc, void init(srslte::radio_multi* radio_handler, mac_interface_phy *mac,rrc_interface_phy *rrc,
prach *prach_buffer, srslte::thread_pool *_workers_pool, prach *prach_buffer, srslte::thread_pool *_workers_pool,
phch_common *_worker_com, srslte::log* _log_h, uint32_t nof_rx_antennas, uint32_t prio, int sync_cpu_affinity = -1); phch_common *_worker_com, srslte::log* _log_h, uint32_t nof_rx_antennas, uint32_t prio, int sync_cpu_affinity = -1);
@ -55,6 +56,7 @@ public:
void set_earfcn(std::vector<uint32_t> earfcn); void set_earfcn(std::vector<uint32_t> earfcn);
bool stop_sync();
void cell_search_start(); void cell_search_start();
void cell_search_next(); void cell_search_next();
bool cell_select(uint32_t earfcn, srslte_cell_t cell); bool cell_select(uint32_t earfcn, srslte_cell_t cell);
@ -75,6 +77,14 @@ private:
void set_ue_sync_opts(srslte_ue_sync_t *q); void set_ue_sync_opts(srslte_ue_sync_t *q);
void run_thread(); void run_thread();
void set_sampling_rate();
bool set_frequency();
void cell_search_inc();
bool init_cell();
void free_cell();
bool running; bool running;
srslte::radio_multi *radio_h; srslte::radio_multi *radio_h;
@ -85,9 +95,14 @@ private:
phch_common *worker_com; phch_common *worker_com;
prach *prach_buffer; prach *prach_buffer;
// Structures for Cell Camp
srslte_ue_sync_t ue_sync; srslte_ue_sync_t ue_sync;
srslte_ue_mib_t ue_mib; srslte_ue_mib_t ue_mib;
// Structures for Cell Search
srslte_ue_cellsearch_t cs;
srslte_ue_mib_sync_t ue_mib_sync;
uint32_t nof_rx_antennas; uint32_t nof_rx_antennas;
cf_t *sf_buffer[SRSLTE_MAX_PORTS]; cf_t *sf_buffer[SRSLTE_MAX_PORTS];
@ -99,6 +114,8 @@ private:
IDLE, CELL_SEARCH, CELL_MEASURE, CELL_SELECT, CELL_CAMP IDLE, CELL_SEARCH, CELL_MEASURE, CELL_SELECT, CELL_CAMP
} phy_state; } phy_state;
bool is_in_idle;
enum { enum {
SRATE_NONE=0, SRATE_FIND, SRATE_CAMP SRATE_NONE=0, SRATE_FIND, SRATE_CAMP
} srate_mode; } srate_mode;
@ -108,7 +125,6 @@ private:
bool is_sfn_synched; bool is_sfn_synched;
bool started; bool started;
float time_adv_sec; float time_adv_sec;
bool radio_is_streaming;
uint32_t tti; uint32_t tti;
bool do_agc; bool do_agc;
@ -117,8 +133,10 @@ private:
uint32_t nof_tx_mutex; uint32_t nof_tx_mutex;
uint32_t tx_mutex_cnt; uint32_t tx_mutex_cnt;
uint32_t current_earfcn;
uint32_t sync_sfn_cnt; uint32_t sync_sfn_cnt;
const static uint32_t SYNC_SFN_TIMEOUT = 5000; const static uint32_t SYNC_SFN_TIMEOUT = 100;
float ul_dl_factor; float ul_dl_factor;
int cur_earfcn_index; int cur_earfcn_index;
bool cell_search_in_progress; bool cell_search_in_progress;
@ -132,8 +150,7 @@ private:
int cell_sync_sfn(); int cell_sync_sfn();
int cell_meas_rsrp(); int cell_meas_rsrp();
bool cell_search(int force_N_id_2 = -1); bool cell_search(int force_N_id_2 = -1);
bool init_cell(); bool set_cell();
void free_cell();
}; };
} // namespace srsue } // namespace srsue

@ -42,10 +42,12 @@ class phch_worker : public srslte::thread_pool::worker
public: public:
phch_worker(); phch_worker();
~phch_worker();
void reset(); void reset();
void set_common(phch_common *phy); void set_common(phch_common *phy);
bool init_cell(srslte_cell_t cell); bool init(uint32_t max_prb);
void free_cell();
bool set_cell(srslte_cell_t cell);
/* Functions used by main PHY thread */ /* Functions used by main PHY thread */
cf_t* get_buffer(uint32_t antenna_idx); cf_t* get_buffer(uint32_t antenna_idx);
@ -105,6 +107,7 @@ private:
/* Common objects */ /* Common objects */
phch_common *phy; phch_common *phy;
srslte_cell_t cell; srslte_cell_t cell;
bool mem_initiated;
bool cell_initiated; bool cell_initiated;
cf_t *signal_buffer[SRSLTE_MAX_PORTS]; cf_t *signal_buffer[SRSLTE_MAX_PORTS];
uint32_t tti; uint32_t tti;

@ -46,6 +46,7 @@ typedef _Complex float cf_t;
class phy class phy
: public phy_interface_mac : public phy_interface_mac
, public phy_interface_rrc , public phy_interface_rrc
, public thread
{ {
public: public:
phy(); phy();
@ -57,6 +58,9 @@ public:
void stop(); void stop();
void wait_initialize();
bool is_initiated();
void set_agc_enable(bool enabled); void set_agc_enable(bool enabled);
void get_metrics(phy_metrics_t &m); void get_metrics(phy_metrics_t &m);
@ -84,6 +88,7 @@ public:
/********** MAC INTERFACE ********************/ /********** MAC INTERFACE ********************/
/* Functions to synchronize with a cell */ /* Functions to synchronize with a cell */
bool sync_status(); // this is also RRC interface bool sync_status(); // this is also RRC interface
bool sync_stop();
/* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */ /* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */
void set_crnti(uint16_t rnti); void set_crnti(uint16_t rnti);
@ -131,6 +136,9 @@ public:
private: private:
void run_thread();
bool initiated;
uint32_t nof_workers; uint32_t nof_workers;
const static int MAX_WORKERS = 4; const static int MAX_WORKERS = 4;
@ -141,6 +149,8 @@ private:
srslte::radio_multi *radio_handler; srslte::radio_multi *radio_handler;
srslte::log *log_h; srslte::log *log_h;
srsue::mac_interface_phy *mac;
srsue::rrc_interface_phy *rrc;
srslte::thread_pool workers_pool; srslte::thread_pool workers_pool;
std::vector<phch_worker> workers; std::vector<phch_worker> workers;

@ -45,14 +45,15 @@ namespace srsue {
args = NULL; args = NULL;
config = NULL; config = NULL;
initiated = false;
signal_buffer = NULL; signal_buffer = NULL;
transmitted_tti = 0; transmitted_tti = 0;
target_power_dbm = 0; target_power_dbm = 0;
mem_initiated = false;
cell_initiated = false;
} }
void init(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config, phy_args_t *args, srslte::log *log_h); ~prach();
bool init_cell(srslte_cell_t cell); void init(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *config, uint32_t max_prb, phy_args_t *args, srslte::log *log_h);
void free_cell(); bool set_cell(srslte_cell_t cell);
bool prepare_to_send(uint32_t preamble_idx, int allowed_subframe = -1, float target_power_dbm = -1); bool prepare_to_send(uint32_t preamble_idx, int allowed_subframe = -1, float target_power_dbm = -1);
bool is_ready_to_send(uint32_t current_tti); bool is_ready_to_send(uint32_t current_tti);
int tx_tti(); int tx_tti();
@ -70,7 +71,8 @@ namespace srsue {
srslte::log *log_h; srslte::log *log_h;
int preamble_idx; int preamble_idx;
int allowed_subframe; int allowed_subframe;
bool initiated; bool mem_initiated;
bool cell_initiated;
uint32_t len; uint32_t len;
cf_t *buffer[64]; cf_t *buffer[64];
srslte_prach_t prach_obj; srslte_prach_t prach_obj;

@ -175,6 +175,7 @@ private:
srsue::usim usim; srsue::usim usim;
srslte::logger_file logger; srslte::logger_file logger;
//srslte::logger_stdout logger;
srslte::log_filter rf_log; srslte::log_filter rf_log;
srslte::log_filter phy_log; srslte::log_filter phy_log;
srslte::log_filter mac_log; srslte::log_filter mac_log;

@ -89,8 +89,6 @@ public:
void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code); void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code);
void cell_selected();
// UE interface // UE interface
void attach_request(); void attach_request();

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

Loading…
Cancel
Save