Merge branch 'mobility' into next

master
Ismael Gomez 7 years ago
commit d0fb17c088

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

@ -241,15 +241,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(&ue_dl, cell, 1)) { if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n");
return -1;
}
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
return -1;
}
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
fprintf(stderr, "Error initiating UE downlink processing module\n"); 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;
} }
@ -264,7 +276,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);
} }

@ -292,7 +292,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);
} }
@ -302,7 +306,11 @@ void base_init() {
exit(-1); exit(-1);
} }
if (srslte_pcfich_init(&pcfich, &regs, cell)) { if (srslte_pcfich_init(&pcfich, 1)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
if (srslte_pcfich_set_cell(&pcfich, &regs, cell)) {
fprintf(stderr, "Error creating PBCH object\n"); fprintf(stderr, "Error creating PBCH object\n");
exit(-1); exit(-1);
} }
@ -312,13 +320,20 @@ void base_init() {
exit(-1); exit(-1);
} }
if (srslte_pdcch_init_tx(&pdcch, &regs, cell)) { if (srslte_pdcch_init_enb(&pdcch, cell.nof_prb)) {
fprintf(stderr, "Error creating PDCCH object\n");
exit(-1);
}
if (srslte_pdcch_set_cell(&pdcch, &regs, cell)) {
fprintf(stderr, "Error creating PDCCH object\n"); fprintf(stderr, "Error creating PDCCH object\n");
exit(-1); exit(-1);
} }
bzero(&pdsch, sizeof(srslte_pdsch_t)); if (srslte_pdsch_init_enb(&pdsch, cell.nof_prb)) {
if (srslte_pdsch_init_tx(&pdsch, cell)) { 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);
} }
@ -660,7 +675,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);
} }

@ -475,19 +475,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(&ue_dl, cell, prog_args.rf_nof_rx_ant)) { // This is the User RNTI if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, prog_args.rf_nof_rx_ant)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1);
}
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
fprintf(stderr, "Error initiating UE downlink processing module\n"); fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1); exit(-1);
} }
@ -566,6 +585,10 @@ int main(int argc, char **argv) {
/* If a new line is detected set verbose level to Debug */ /* If a new line is detected set verbose level to Debug */
if (fgets(input, sizeof(input), stdin)) { if (fgets(input, sizeof(input), stdin)) {
srslte_verbose = SRSLTE_VERBOSE_DEBUG; srslte_verbose = SRSLTE_VERBOSE_DEBUG;
ue_dl.pkt_errors = 0;
ue_dl.pkts_total = 0;
ue_dl.nof_detected = 0;
nof_trials = 0;
} }
} }
@ -760,10 +783,12 @@ int main(int argc, char **argv) {
if (sfn == 1024) { if (sfn == 1024) {
sfn = 0; sfn = 0;
PRINT_LINE_ADVANCE_CURSOR(); PRINT_LINE_ADVANCE_CURSOR();
/*
ue_dl.pkt_errors = 0; ue_dl.pkt_errors = 0;
ue_dl.pkts_total = 0; ue_dl.pkts_total = 0;
ue_dl.nof_detected = 0; ue_dl.nof_detected = 0;
nof_trials = 0; nof_trials = 0;
*/
} }
} }

@ -165,7 +165,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, nof_rx_antennas, (void*) &rf)) { if (srslte_ue_sync_init_multi(&ue_sync, cell.nof_prb, cell.id==1000, srslte_rf_recv_wrapper, nof_rx_antennas, (void*) &rf)) {
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n"); fprintf(stderr, "Error initiating ue_sync\n");
exit(-1); exit(-1);
} }

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

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

@ -92,10 +92,13 @@ typedef struct {
SRSLTE_API int srslte_chest_dl_init(srslte_chest_dl_t *q, SRSLTE_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,7 +53,10 @@ 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,
srslte_cell_t cell); uint32_t max_prb);
SRSLTE_API int srslte_refsignal_cs_set_cell(srslte_refsignal_cs_t * q,
srslte_cell_t cell);
SRSLTE_API void srslte_refsignal_cs_free(srslte_refsignal_cs_t *q); SRSLTE_API void srslte_refsignal_cs_free(srslte_refsignal_cs_t *q);

@ -94,7 +94,10 @@ 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,
srslte_cell_t cell); uint32_t max_prb);
SRSLTE_API int srslte_refsignal_ul_set_cell(srslte_refsignal_ul_t *q,
srslte_cell_t cell);
SRSLTE_API void srslte_refsignal_ul_free(srslte_refsignal_ul_t *q); 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
@ -88,6 +89,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,12 +45,18 @@ 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); uint32_t max_prb,
bool is_tx);
SRSLTE_API int srslte_dft_precoding_init_tx(srslte_dft_precoding_t *q,
uint32_t max_prb);
SRSLTE_API int srslte_dft_precoding_init_rx(srslte_dft_precoding_t *q,
uint32_t max_prb);
SRSLTE_API void srslte_dft_precoding_free(srslte_dft_precoding_t *q); 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,18 +57,27 @@ 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 nof_prb); uint32_t max_prb);
SRSLTE_API int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q,
srslte_cp_t cp,
uint32_t nof_prb);
SRSLTE_API int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q,
srslte_cp_t cp,
uint32_t nof_prb);
SRSLTE_API void srslte_ofdm_rx_free(srslte_ofdm_t *q); 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);
@ -154,9 +157,11 @@ SRSLTE_API int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q,
srslte_ra_dl_grant_t *grant, srslte_ra_dl_grant_t *grant,
srslte_softbuffer_tx_t *softbuffer[SRSLTE_MAX_CODEWORDS], srslte_softbuffer_tx_t *softbuffer[SRSLTE_MAX_CODEWORDS],
uint16_t rnti, uint16_t rnti,
uint32_t rv_idx, int rv_idx[SRSLTE_MAX_CODEWORDS],
uint32_t sf_idx, uint32_t sf_idx,
uint8_t *data[SRSLTE_MAX_CODEWORDS]); uint8_t *data[SRSLTE_MAX_CODEWORDS],
srslte_mimo_type_t mimo_type,
uint32_t pmi);
SRSLTE_API int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q, SRSLTE_API int srslte_enb_dl_put_pdcch_dl(srslte_enb_dl_t *q,
srslte_ra_dl_dci_t *grant, srslte_ra_dl_dci_t *grant,

@ -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,
srslte_cell_t cell, uint32_t max_prb);
srslte_prach_cfg_t* prach_cfg,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pusch_hopping_cfg_t *hopping_cfg,
srslte_pucch_cfg_t *pucch_cfg);
SRSLTE_API void srslte_enb_ul_free(srslte_enb_ul_t *q); SRSLTE_API void srslte_enb_ul_free(srslte_enb_ul_t *q);
SRSLTE_API int srslte_enb_ul_set_cell(srslte_enb_ul_t *q,
srslte_cell_t cell,
srslte_prach_cfg_t* prach_cfg,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pusch_hopping_cfg_t *hopping_cfg,
srslte_pucch_cfg_t *pucch_cfg);
SRSLTE_API 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],

@ -79,13 +79,11 @@ 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, uint32_t nof_rx_antennas);
srslte_cell_t cell);
SRSLTE_API int srslte_pcfich_init_multi(srslte_pcfich_t *q, SRSLTE_API int srslte_pcfich_set_cell(srslte_pcfich_t *q,
srslte_regs_t *regs, srslte_regs_t *regs,
srslte_cell_t cell, srslte_cell_t cell);
uint32_t nof_rx_antennas);
SRSLTE_API void srslte_pcfich_free(srslte_pcfich_t *q); SRSLTE_API void srslte_pcfich_free(srslte_pcfich_t *q);

@ -64,6 +64,7 @@ typedef struct SRSLTE_API {
uint32_t nof_cce; uint32_t nof_cce;
uint32_t max_bits; uint32_t max_bits;
uint32_t nof_rx_antennas; uint32_t nof_rx_antennas;
bool is_ue;
srslte_regs_t *regs; srslte_regs_t *regs;
@ -84,29 +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_ue(srslte_pdcch_t *q,
srslte_regs_t *regs, uint32_t max_prb,
srslte_cell_t cell); uint32_t nof_rx_antennas);
SRSLTE_API int srslte_pdcch_init_tx(srslte_pdcch_t *q, SRSLTE_API int srslte_pdcch_init_enb(srslte_pdcch_t *q,
srslte_regs_t *regs, uint32_t max_prb);
srslte_cell_t cell);
SRSLTE_API int srslte_pdcch_set_cell(srslte_pdcch_t *q,
SRSLTE_API int srslte_pdcch_init_rx(srslte_pdcch_t *q, srslte_regs_t *regs,
srslte_regs_t *regs, srslte_cell_t cell);
srslte_cell_t cell,
uint32_t nof_rx_antennas);
SRSLTE_API int srslte_pdcch_init_multi(srslte_pdcch_t *q,
srslte_regs_t *regs,
srslte_cell_t cell,
uint32_t nof_rx_antennas);
SRSLTE_API int srslte_pdcch_init_txrx(srslte_pdcch_t *q,
srslte_regs_t *regs,
srslte_cell_t cell,
uint32_t nof_rx_antennas,
bool isReceiver);
SRSLTE_API void srslte_pdcch_free(srslte_pdcch_t *q); SRSLTE_API void srslte_pdcch_free(srslte_pdcch_t *q);

@ -49,6 +49,7 @@
typedef struct { typedef struct {
srslte_sequence_t seq[SRSLTE_MAX_CODEWORDS][SRSLTE_NSUBFRAMES_X_FRAME]; srslte_sequence_t seq[SRSLTE_MAX_CODEWORDS][SRSLTE_NSUBFRAMES_X_FRAME];
uint32_t cell_id;
bool sequence_generated; bool sequence_generated;
} srslte_pdsch_user_t; } srslte_pdsch_user_t;
@ -60,6 +61,9 @@ typedef struct SRSLTE_API {
uint32_t max_re; uint32_t max_re;
uint16_t ue_rnti;
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]; /* Channel estimation (Rx only) */ cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; /* Channel estimation (Rx only) */
@ -74,19 +78,25 @@ typedef struct SRSLTE_API {
// This is to generate the scrambling seq for multiple CRNTIs // 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_tx(srslte_pdsch_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_pdsch_init_rx(srslte_pdsch_t *q, SRSLTE_API int srslte_pdsch_init_ue(srslte_pdsch_t *q,
srslte_cell_t cell, uint32_t max_prb,
uint32_t nof_antennas); uint32_t nof_rx_antennas);
SRSLTE_API int srslte_pdsch_init_enb(srslte_pdsch_t *q,
uint32_t max_prb);
SRSLTE_API void srslte_pdsch_free(srslte_pdsch_t *q); SRSLTE_API 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);

@ -86,16 +86,14 @@ 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, uint32_t nof_rx_antennas);
srslte_cell_t cell);
SRSLTE_API int srslte_phich_init_multi(srslte_phich_t *q,
srslte_regs_t *regs,
srslte_cell_t cell,
uint32_t nof_rx_antennas);
SRSLTE_API void srslte_phich_free(srslte_phich_t *q); SRSLTE_API 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,11 +133,14 @@ 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 N_ifft_ul, uint32_t max_N_ifft_ul);
uint32_t config_idx,
uint32_t root_seq_index, SRSLTE_API int srslte_prach_set_cell(srslte_prach_t *p,
bool high_speed_flag, uint32_t N_ifft_ul,
uint32_t zero_corr_zone_config); uint32_t config_idx,
uint32_t root_seq_index,
bool high_speed_flag,
uint32_t zero_corr_zone_config);
SRSLTE_API int srslte_prach_init_cfg(srslte_prach_t* p, SRSLTE_API int srslte_prach_init_cfg(srslte_prach_t* p,
srslte_prach_cfg_t* cfg, srslte_prach_cfg_t* cfg,

@ -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,
@ -115,11 +115,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,16 @@ 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; uint32_t cell_id;
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;
uint16_t ue_rnti;
uint32_t max_re; uint32_t max_re;
srslte_dft_precoding_t dft_precoding; srslte_dft_precoding_t dft_precoding;
@ -96,11 +99,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,
@ -114,7 +123,7 @@ SRSLTE_API int srslte_pusch_cfg(srslte_pusch_t *q,
SRSLTE_API int srslte_pusch_set_rnti(srslte_pusch_t *q, SRSLTE_API int srslte_pusch_set_rnti(srslte_pusch_t *q,
uint16_t rnti); uint16_t rnti);
SRSLTE_API void srslte_pusch_clear_rnti(srslte_pusch_t *q, SRSLTE_API void srslte_pusch_free_rnti(srslte_pusch_t *q,
uint16_t rnti); uint16_t rnti);
SRSLTE_API int srslte_pusch_encode(srslte_pusch_t *q, SRSLTE_API int srslte_pusch_encode(srslte_pusch_t *q,

@ -68,6 +68,7 @@ SRSLTE_API void srslte_interp_linear_f(float *input,
typedef struct { 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,8 +59,8 @@ 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,
float tol); float tol);

@ -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);

@ -75,6 +75,8 @@ typedef struct SRSLTE_API {
uint32_t frame_size; uint32_t frame_size;
uint32_t max_offset; uint32_t max_offset;
bool enable_cfo_corr; bool enable_cfo_corr;
bool mean_cfo2_isunset;
bool mean_cfo_isunset;
float mean_cfo; float mean_cfo;
float mean_cfo2; float mean_cfo2;
int cfo_i; int cfo_i;
@ -85,6 +87,7 @@ typedef struct SRSLTE_API {
uint32_t cp_len; uint32_t cp_len;
srslte_cfo_t cfocorr; srslte_cfo_t cfocorr;
srslte_cfo_t cfocorr2; srslte_cfo_t cfocorr2;
float current_cfo_tol;
sss_alg_t sss_alg; sss_alg_t sss_alg;
bool detect_cp; bool detect_cp;
bool sss_en; bool sss_en;
@ -97,6 +100,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 +126,11 @@ SRSLTE_API int srslte_sync_init_decim(srslte_sync_t *q,
SRSLTE_API void srslte_sync_free(srslte_sync_t *q); SRSLTE_API 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 */
@ -138,6 +148,9 @@ SRSLTE_API srslte_cp_t srslte_sync_detect_cp(srslte_sync_t *q,
SRSLTE_API void srslte_sync_set_threshold(srslte_sync_t *q, SRSLTE_API void srslte_sync_set_threshold(srslte_sync_t *q,
float threshold); float threshold);
SRSLTE_API void srslte_sync_set_cfo_tol(srslte_sync_t *q,
float tol);
/* Gets the subframe idx (0 or 5) */ /* Gets the subframe idx (0 or 5) */
SRSLTE_API uint32_t srslte_sync_get_sf_idx(srslte_sync_t *q); SRSLTE_API uint32_t srslte_sync_get_sf_idx(srslte_sync_t *q);

@ -119,11 +119,14 @@ typedef struct SRSLTE_API {
/* This function shall be called just after the initial synchronization */ /* 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,
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[SRSLTE_MAX_PORTS], cf_t *input[SRSLTE_MAX_PORTS],
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,22 +127,25 @@ 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,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*), bool search_cell,
uint32_t nof_rx_antennas, int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*),
void *stream_handler, uint32_t nof_rx_antennas,
int decimate); void *stream_handler,
int decimate);
SRSLTE_API int srslte_ue_sync_init_file(srslte_ue_sync_t *q, SRSLTE_API int srslte_ue_sync_init_file(srslte_ue_sync_t *q,
uint32_t nof_prb, uint32_t nof_prb,
@ -157,6 +162,9 @@ SRSLTE_API int srslte_ue_sync_init_file_multi(srslte_ue_sync_t *q,
SRSLTE_API void srslte_ue_sync_free(srslte_ue_sync_t *q); SRSLTE_API 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);
@ -173,6 +181,9 @@ SRSLTE_API int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q,
SRSLTE_API int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, SRSLTE_API int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q,
cf_t *input_buffer[SRSLTE_MAX_PORTS]); cf_t *input_buffer[SRSLTE_MAX_PORTS]);
SRSLTE_API void srslte_ue_sync_set_cfo_tol(srslte_ue_sync_t *q,
float tol);
SRSLTE_API void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, SRSLTE_API void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q,
float cfo); float cfo);

@ -76,6 +76,7 @@ typedef struct SRSLTE_API {
bool normalize_en; bool normalize_en;
bool cfo_en; bool cfo_en;
float current_cfo_tol;
float current_cfo; float current_cfo;
srslte_pucch_format_t last_pucch_format; srslte_pucch_format_t last_pucch_format;
@ -107,10 +108,16 @@ typedef struct SRSLTE_API {
/* This function shall be called just after the initial synchronization */ /* 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_tol(srslte_ue_ul_t *q,
float tol);
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);

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

@ -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_, uint32_t lcid_); void init(srsue::pdcp_interface_gw *pdcp_, srsue::ue_interface *ue_, log *gw_log_, uint32_t lcid_);
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;
@ -75,6 +74,8 @@ private:
bool if_up; bool if_up;
uint32_t lcid; uint32_t lcid;
uint32_t current_ip_addr;
long ul_tput_bytes; long ul_tput_bytes;
long dl_tput_bytes; long dl_tput_bytes;
struct timeval metrics_time[3]; struct timeval metrics_time[3];

@ -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,9 @@
#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_SYM (max_prb*SRSLTE_NRE)
#define MAX_REFS_SF (max_prb*SRSLTE_NRE*2) // 2 reference symbols per subframe
/** 3GPP LTE Downlink channel estimator and equalizer. /** 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 +57,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_SYM)) {
fprintf(stderr, "Error initializing vector interpolator\n"); fprintf(stderr, "Error initializing vector interpolator\n");
goto clean_exit; goto clean_exit;
} }
@ -107,6 +109,11 @@ int srslte_chest_ul_init(srslte_chest_ul_t *q, srslte_cell_t cell)
q->dmrs_signal_configured = false; 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 +127,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 +152,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_SYM)) {
fprintf(stderr, "Error initializing vector interpolator\n");
return SRSLTE_ERROR;
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
void srslte_chest_ul_set_cfg(srslte_chest_ul_t *q, 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,74 +143,55 @@ 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)) { return SRSLTE_ERROR;
goto free_and_exit; }
}
if (SRSLTE_CP_ISNORM(cell.cp)) { if (SRSLTE_CP_ISNORM(cell.cp)) {
N_cp = 1; N_cp = 1;
} else { } else {
N_cp = 0; N_cp = 0;
} }
q->cell = cell; for (ns=0;ns<SRSLTE_NSLOTS_X_FRAME;ns++) {
for (p=0;p<2;p++) {
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(2*p)/2;
for (l = 0; l < nsymbols; l++) {
/* Compute sequence init value */
uint32_t lp = srslte_refsignal_cs_nsymbol(l, cell.cp, 2*p);
c_init = 1024 * (7 * (ns + 1) + lp + 1) * (2 * cell.id + 1)
+ 2 * cell.id + N_cp;
for (p=0;p<2;p++) { /* generate sequence for this symbol and slot */
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) { srslte_sequence_set_LTE_pr(&seq, 2*2*SRSLTE_MAX_PRB, c_init);
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++) { /* Compute signal */
for (p=0;p<2;p++) { for (i = 0; i < 2*q->cell.nof_prb; i++) {
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(2*p)/2; mp = i + SRSLTE_MAX_PRB - cell.nof_prb;
for (l = 0; l < nsymbols; l++) { /* save signal */
/* Compute sequence init value */ q->pilots[p][ns/2][SRSLTE_REFSIGNAL_PILOT_IDX(i,(ns%2)*nsymbols+l,q->cell)] =
uint32_t lp = srslte_refsignal_cs_nsymbol(l, cell.cp, 2*p); (1 - 2 * (float) seq.c[2 * mp]) / sqrt(2) +
c_init = 1024 * (7 * (ns + 1) + lp + 1) * (2 * cell.id + 1) _Complex_I * (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2);
+ 2 * cell.id + N_cp; }
/* generate sequence for this symbol and slot */
srslte_sequence_set_LTE_pr(&seq, c_init);
/* Compute signal */
for (i = 0; i < 2*q->cell.nof_prb; i++) {
mp = i + SRSLTE_MAX_PRB - cell.nof_prb;
/* save signal */
q->pilots[p][ns/2][SRSLTE_REFSIGNAL_PILOT_IDX(i,(ns%2)*nsymbols+l,q->cell)] =
(1 - 2 * (float) seq.c[2 * mp]) / 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; ret = SRSLTE_SUCCESS;
} }
free_and_exit:
if (ret == SRSLTE_ERROR) {
srslte_sequence_free(&seq);
srslte_refsignal_cs_free(q);
}
return ret; return ret;
} }
/** 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,46 +171,24 @@ 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;
} }
srslte_pucch_cfg_default(&q->pucch_cfg);
// Precompute n_prs
if (generate_n_prs(q)) {
goto free_and_exit;
}
// Precompute group hopping values u.
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
goto free_and_exit;
}
// Precompute sequence hopping values v. Uses f_ss_pusch
if (generate_srslte_sequence_hopping_v(q)) {
goto free_and_exit;
}
if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) {
goto free_and_exit;
}
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} }
free_and_exit: free_and_exit:
@ -226,6 +205,45 @@ void srslte_refsignal_ul_free(srslte_refsignal_ul_t * q) {
bzero(q, sizeof(srslte_refsignal_ul_t)); bzero(q, sizeof(srslte_refsignal_ul_t));
} }
/** Initializes srslte_refsignal_ul_t object according to 3GPP 36.211 5.5
*
*/
int srslte_refsignal_ul_set_cell(srslte_refsignal_ul_t * q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell)) {
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
srslte_pucch_cfg_default(&q->pucch_cfg);
// Precompute n_prs
if (generate_n_prs(q)) {
return SRSLTE_ERROR;
}
// Precompute group hopping values u.
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
return SRSLTE_ERROR;
}
// Precompute sequence hopping values v. Uses f_ss_pusch
if (generate_srslte_sequence_hopping_v(q)) {
return SRSLTE_ERROR;
}
if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) {
return SRSLTE_ERROR;
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
void srslte_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;
} }

@ -235,7 +235,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;
@ -257,7 +257,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,75 @@
#define Nc 1600 #define Nc 1600
#define MAX_SEQ_LEN (128*1024)
#define static_memory
/* /*
* 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_memory
static uint8_t x1[Nc+MAX_SEQ_LEN+31];
static uint8_t x2[Nc+MAX_SEQ_LEN+31];
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) {
int n;
if (len > q->max_len) {
fprintf(stderr, "Error generating pseudo-random sequence: len %d exceeds maximum len %d\n",
len, MAX_SEQ_LEN);
return -1;
}
if (len > q->max_len) {
fprintf(stderr, "Error generating pseudo-random sequence: len %d is greater than allocated len %d\n",
len, q->max_len);
return -1;
}
pthread_mutex_lock(&mutex);
for (n = 0; n < 31; n++) {
x2[n] = (seed >> n) & 0x1;
}
x1[0] = 1;
for (n = 0; n < Nc + len; n++) {
x1[n + 31] = (x1[n + 3] + x1[n]) & 0x1;
x2[n + 31] = (x2[n + 3] + x2[n + 2] + x2[n+1] + x2[n]) & 0x1;
}
for (n = 0; n < len; n++) {
q->c[n] = (x1[n + Nc] + x2[n + Nc]) & 0x1;
}
pthread_mutex_unlock(&mutex);
return 0;
}
#else
int srslte_sequence_set_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) {
int n; 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,25 +112,29 @@ 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]);
@ -90,17 +144,8 @@ int srslte_sequence_LTE_pr(srslte_sequence_t *q, uint32_t len, uint32_t seed) {
} }
int srslte_sequence_init(srslte_sequence_t *q, uint32_t len) { 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 +164,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"
@ -38,14 +39,27 @@
#define FFTW_WISDOM_FILE ".fftw_wisdom" #define FFTW_WISDOM_FILE ".fftw_wisdom"
#ifdef FFTW_WISDOM_FILE
#define FFTW_TYPE FFTW_MEASURE
#else
#define FFTW_TYPE 0
#endif
void srslte_dft_load() { void srslte_dft_load() {
#ifdef FFTW_WISDOM_FILE
fftwf_import_wisdom_from_filename(FFTW_WISDOM_FILE); fftwf_import_wisdom_from_filename(FFTW_WISDOM_FILE);
#else
printf("Warning: FFTW Wisdom file not defined\n");
#endif
} }
void srslte_dft_exit() { void srslte_dft_exit() {
#ifdef FFTW_WISDOM_FILE
if (!fftwf_export_wisdom_to_filename(FFTW_WISDOM_FILE)) { if (!fftwf_export_wisdom_to_filename(FFTW_WISDOM_FILE)) {
fprintf(stderr, "Error saving FFTW wisdom to file %s\n", FFTW_WISDOM_FILE); fprintf(stderr, "Error saving FFTW wisdom to file %s\n", FFTW_WISDOM_FILE);
} }
#endif
} }
int srslte_dft_plan(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir, int srslte_dft_plan(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir,
@ -58,19 +72,50 @@ int srslte_dft_plan(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_di
return 0; 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, FFTW_TYPE);
if (!plan->p) {
return -1;
}
plan->size = new_dft_points;
return 0;
}
int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) { 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;
plan->p = fftwf_plan_dft_1d(dft_points, plan->in, plan->out, sign, FFTW_MEASURE); plan->p = fftwf_plan_dft_1d(dft_points, plan->in, plan->out, sign, FFTW_TYPE);
if (!plan->p) { if (!plan->p) {
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;
@ -82,14 +127,29 @@ 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, FFTW_TYPE);
if (!plan->p) {
return -1;
}
plan->size = new_dft_points;
return 0;
}
int srslte_dft_plan_r(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) { 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;
plan->p = fftwf_plan_r2r_1d(dft_points, plan->in, plan->out, sign, FFTW_MEASURE); plan->p = fftwf_plan_r2r_1d(dft_points, plan->in, plan->out, sign, FFTW_TYPE);
if (!plan->p) { if (!plan->p) {
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));
@ -98,7 +102,7 @@ bool srslte_dft_precoding_valid_prb(uint32_t nof_prb) {
} }
int srslte_dft_precoding(srslte_dft_precoding_t *q, cf_t *input, cf_t *output, int srslte_dft_precoding(srslte_dft_precoding_t *q, cf_t *input, cf_t *output,
uint32_t nof_prb, uint32_t nof_symbols) uint32_t nof_prb, uint32_t nof_symbols)
{ {
if (!srslte_dft_precoding_valid_prb(nof_prb) && nof_prb <= q->max_prb) { if (!srslte_dft_precoding_valid_prb(nof_prb) && nof_prb <= q->max_prb) {
@ -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,30 +110,28 @@ 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) {
srslte_ofdm_free_(q);
} }
int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) { int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) {
uint32_t i; uint32_t i;
int ret; int ret;
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;
} }
q->max_prb = max_prb;
ret = srslte_ofdm_init_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_BACKWARD); ret = srslte_ofdm_init_(q, cp, symbol_sz, max_prb, SRSLTE_DFT_BACKWARD);
if (ret == SRSLTE_SUCCESS) { if (ret == SRSLTE_SUCCESS) {
srslte_dft_plan_set_norm(&q->fft_plan, false); srslte_dft_plan_set_norm(&q->fft_plan, false);
@ -115,16 +145,57 @@ int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
return ret; return ret;
} }
int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
if (nof_prb <= q->max_prb) {
int symbol_sz = srslte_symbol_sz(nof_prb);
if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb);
return -1;
}
return srslte_ofdm_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;
int ret;
if (nof_prb <= q->max_prb) {
int symbol_sz = srslte_symbol_sz(nof_prb);
if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb);
return -1;
}
ret = srslte_ofdm_replan_(q, cp, symbol_sz, nof_prb);
if (ret == SRSLTE_SUCCESS) {
/* 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;
} 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.
* Freq_shift is relative to inter-carrier spacing. * Freq_shift is relative to inter-carrier spacing.
* 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,8 @@
#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>
#include <srslte/srslte.h>
#define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb) #define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb)
@ -39,78 +41,67 @@
#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, 0)) {
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, 0)) {
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_enb(&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_tx(&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(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t));
if (!q->sf_symbols[i]) { if (!q->sf_symbols[i]) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
} }
q->slot1_symbols[i] = &q->sf_symbols[i][CURRENT_SLOTLEN_RE]; q->slot1_symbols[i] = &q->sf_symbols[i][SRSLTE_SLOT_LEN_RE(max_prb, SRSLTE_CP_NORM)];
} }
/* Generate PSS/SSS signals */
srslte_pss_generate(q->pss_signal, cell.id%3);
srslte_sss_generate(q->sss_signal0, q->sss_signal5, cell.id);
ret = SRSLTE_SUCCESS; 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:
@ -125,6 +116,7 @@ void srslte_enb_dl_free(srslte_enb_dl_t *q)
if (q) { if (q) {
srslte_ofdm_tx_free(&q->ifft); srslte_ofdm_tx_free(&q->ifft);
srslte_regs_free(&q->regs); srslte_regs_free(&q->regs);
srslte_pbch_free(&q->pbch);
srslte_pcfich_free(&q->pcfich); srslte_pcfich_free(&q->pcfich);
srslte_phich_free(&q->phich); srslte_phich_free(&q->phich);
srslte_pdcch_free(&q->pdcch); srslte_pdcch_free(&q->pdcch);
@ -141,6 +133,71 @@ void srslte_enb_dl_free(srslte_enb_dl_t *q)
} }
} }
int srslte_enb_dl_set_cell(srslte_enb_dl_t *q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
srslte_enb_dl_set_cfi(q, 3);
q->tx_amp = SRSLTE_ENB_RF_AMP;
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
if (q->cell.nof_prb != 0) {
srslte_regs_free(&q->regs);
}
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
if (srslte_regs_init(&q->regs, q->cell)) {
fprintf(stderr, "Error resizing REGs\n");
return SRSLTE_ERROR;
}
if (srslte_ofdm_rx_set_prb(&q->ifft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating FFT\n");
return SRSLTE_ERROR;
}
if (srslte_pbch_set_cell(&q->pbch, q->cell)) {
fprintf(stderr, "Error creating PBCH object\n");
return SRSLTE_ERROR;
}
if (srslte_pcfich_set_cell(&q->pcfich, &q->regs, q->cell)) {
fprintf(stderr, "Error creating PCFICH object\n");
return SRSLTE_ERROR;
}
if (srslte_phich_set_cell(&q->phich, &q->regs, q->cell)) {
fprintf(stderr, "Error creating PHICH object\n");
return SRSLTE_ERROR;
}
if (srslte_pdcch_set_cell(&q->pdcch, &q->regs, q->cell)) {
fprintf(stderr, "Error creating PDCCH object\n");
return SRSLTE_ERROR;
}
if (srslte_pdsch_set_cell(&q->pdsch, q->cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
return SRSLTE_ERROR;
}
if (srslte_refsignal_cs_set_cell(&q->csr_signal, q->cell)) {
fprintf(stderr, "Error initializing CSR signal (%d)\n",ret);
return SRSLTE_ERROR;
}
/* Generate PSS/SSS signals */
srslte_pss_generate(q->pss_signal, cell.id%3);
srslte_sss_generate(q->sss_signal0, q->sss_signal5, cell.id);
}
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
}
return ret;
}
void srslte_enb_dl_set_amp(srslte_enb_dl_t *q, float amp) void srslte_enb_dl_set_amp(srslte_enb_dl_t *q, float amp)
{ {
q->tx_amp = amp; q->tx_amp = amp;
@ -263,11 +320,11 @@ int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t *q, srslte_ra_ul_dci_t *grant,
} }
int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, srslte_ra_dl_grant_t *grant, srslte_softbuffer_tx_t *softbuffer[SRSLTE_MAX_CODEWORDS], int srslte_enb_dl_put_pdsch(srslte_enb_dl_t *q, srslte_ra_dl_grant_t *grant, srslte_softbuffer_tx_t *softbuffer[SRSLTE_MAX_CODEWORDS],
uint16_t rnti, uint32_t rv_idx, uint32_t sf_idx, uint16_t rnti, int rv_idx[SRSLTE_MAX_CODEWORDS], uint32_t sf_idx,
uint8_t *data[SRSLTE_MAX_CODEWORDS]) uint8_t *data[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type, uint32_t pmi)
{ {
/* Configure pdsch_cfg parameters */ /* Configure pdsch_cfg parameters */
if (srslte_pdsch_cfg(&q->pdsch_cfg, q->cell, grant, q->cfi, sf_idx, rv_idx)) { if (srslte_pdsch_cfg_mimo(&q->pdsch_cfg, q->cell, grant, q->cfi, sf_idx, rv_idx, mimo_type, pmi)) {
fprintf(stderr, "Error configuring PDSCH\n"); fprintf(stderr, "Error configuring PDSCH\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }

@ -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*), (1+SRSLTE_SIRNTI)); q->users = calloc(sizeof(srslte_enb_ul_user_t*), (1+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.8); srslte_pucch_set_threshold(&q->pucch, 0.8);
if (srslte_chest_ul_init(&q->chest, cell)) { if (srslte_chest_ul_init(&q->chest, max_prb)) {
fprintf(stderr, "Error initiating channel estimator\n"); 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:
@ -135,7 +110,7 @@ void srslte_enb_ul_free(srslte_enb_ul_t *q)
if (q) { if (q) {
if (q->users) { if (q->users) {
for (int i=0;i<SRSLTE_SIRNTI;i++) { for (int i=0;i<=SRSLTE_SIRNTI;i++) {
if (q->users[i]) { if (q->users[i]) {
free(q->users[i]); free(q->users[i]);
} }
@ -158,6 +133,68 @@ void srslte_enb_ul_free(srslte_enb_ul_t *q)
} }
} }
int srslte_enb_ul_set_cell(srslte_enb_ul_t *q, srslte_cell_t cell,
srslte_prach_cfg_t *prach_cfg,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pusch_hopping_cfg_t *hopping_cfg,
srslte_pucch_cfg_t *pucch_cfg)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
if (hopping_cfg) {
memcpy(&q->hopping_cfg, hopping_cfg, sizeof(srslte_pusch_hopping_cfg_t));
}
if (srslte_ofdm_rx_set_prb(&q->fft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating FFT\n");
return SRSLTE_ERROR;
}
if (srslte_pucch_set_cell(&q->pucch, q->cell)) {
fprintf(stderr, "Error creating PUCCH object\n");
return SRSLTE_ERROR;
}
if (srslte_pusch_set_cell(&q->pusch, q->cell)) {
fprintf(stderr, "Error creating PUSCH object\n");
return SRSLTE_ERROR;
}
if (prach_cfg) {
if (srslte_prach_init_cfg(&q->prach, prach_cfg, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating PRACH\n");
return SRSLTE_ERROR;
}
srslte_prach_set_detect_factor(&q->prach, 60);
}
if (srslte_chest_ul_set_cell(&q->chest, cell)) {
fprintf(stderr, "Error initiating channel estimator\n");
return SRSLTE_ERROR;
}
// Configure common PUCCH configuration
srslte_pucch_set_cfg(&q->pucch, pucch_cfg, pusch_cfg->group_hopping_en);
// SRS is a dedicated configuration
srslte_chest_ul_set_cfg(&q->chest, pusch_cfg, pucch_cfg, NULL);
ret = SRSLTE_SUCCESS;
}
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
}
return ret;
}
int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q, uint16_t rnti) int srslte_enb_ul_add_rnti(srslte_enb_ul_t *q, uint16_t rnti)
{ {
if (!q->users[rnti]) { if (!q->users[rnti]) {
@ -183,7 +220,7 @@ void srslte_enb_ul_rem_rnti(srslte_enb_ul_t *q, uint16_t rnti)
if (q->users[rnti]) { if (q->users[rnti]) {
free(q->users[rnti]); free(q->users[rnti]);
q->users[rnti] = NULL; q->users[rnti] = NULL;
srslte_pusch_clear_rnti(&q->pusch, rnti); srslte_pusch_free_rnti(&q->pusch, rnti);
} }
} }

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

@ -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,36 @@ 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 +489,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);
@ -486,7 +500,7 @@ int srslte_pbch_decode(srslte_pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[SRS
srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, q->nof_symbols, noise_estimate); srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, q->nof_symbols, noise_estimate);
} else { } else {
srslte_predecoding_diversity(q->symbols[0], q->ce, x, nant, srslte_predecoding_diversity(q->symbols[0], q->ce, x, nant,
q->nof_symbols); q->nof_symbols);
srslte_layerdemap_diversity(x, q->d, nant, q->nof_symbols / nant); srslte_layerdemap_diversity(x, q->d, nant, q->nof_symbols / nant);
} }
@ -577,7 +591,7 @@ int srslte_pbch_encode(srslte_pbch_t *q, uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_
if (q->cell.nof_ports > 1) { if (q->cell.nof_ports > 1) {
srslte_layermap_diversity(q->d, x, q->cell.nof_ports, q->nof_symbols); srslte_layermap_diversity(q->d, x, q->cell.nof_ports, q->nof_symbols);
srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports, srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports,
q->nof_symbols / q->cell.nof_ports); q->nof_symbols / q->cell.nof_ports);
} else { } else {
memcpy(q->symbols[0], q->d, q->nof_symbols * sizeof(cf_t)); memcpy(q->symbols[0], q->d, q->nof_symbols * sizeof(cf_t));
} }

@ -57,38 +57,24 @@ 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) {
return srslte_pcfich_init_multi(q, regs, cell, 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(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 +101,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,41 +61,20 @@ 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) { static int pdcch_init(srslte_pdcch_t *q, uint32_t max_prb, uint32_t nof_rx_antennas, bool is_ue)
return srslte_pdcch_init_multi(q, regs, cell, 1);
}
int srslte_pdcch_init_tx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell) {
return srslte_pdcch_init_txrx(q, regs, cell, 1, false);
}
int srslte_pdcch_init_rx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas) {
return srslte_pdcch_init_txrx(q, regs, cell, nof_rx_antennas, true);
}
int srslte_pdcch_init_multi(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas) {
return srslte_pdcch_init_txrx(q, regs, cell, nof_rx_antennas, true);
}
int srslte_pdcch_init_txrx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas, bool isReceiver)
{ {
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;
q->is_ue = is_ue;
/* 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;
@ -104,14 +83,6 @@ int srslte_pdcch_init_txrx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t
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;
@ -134,29 +105,23 @@ int srslte_pdcch_init_txrx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t
goto clean; goto clean;
} }
if (isReceiver) {
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
for (int j = 0; j < q->nof_rx_antennas; j++) {
q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->ce[i][j]) {
goto clean;
}
}
}
}
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) { for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2); q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->x[i]) { if (!q->x[i]) {
goto clean; goto clean;
} }
} q->symbols[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->symbols[i]) {
for (int j = 0; j < ((isReceiver) ? q->nof_rx_antennas : cell.nof_ports); j++) {
q->symbols[j] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->symbols[j]) {
goto clean; goto clean;
} }
if (q->is_ue) {
for (int j = 0; j < q->nof_rx_antennas; j++) {
q->ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->ce[i][j]) {
goto clean;
}
}
}
} }
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
@ -168,6 +133,14 @@ int srslte_pdcch_init_txrx(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t
return ret; return ret;
} }
int srslte_pdcch_init_enb(srslte_pdcch_t *q, uint32_t max_prb) {
return pdcch_init(q, max_prb, 0, false);
}
int srslte_pdcch_init_ue(srslte_pdcch_t *q, uint32_t max_prb, uint32_t nof_rx_antennas) {
return pdcch_init(q, max_prb, nof_rx_antennas, true);
}
void srslte_pdcch_free(srslte_pdcch_t *q) { void srslte_pdcch_free(srslte_pdcch_t *q) {
if (q->e) { if (q->e) {
@ -180,18 +153,18 @@ void srslte_pdcch_free(srslte_pdcch_t *q) {
free(q->d); free(q->d);
} }
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) { for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
for (int j=0;j<q->nof_rx_antennas;j++) {
if (q->ce[i][j]) {
free(q->ce[i][j]);
}
}
if (q->x[i]) { if (q->x[i]) {
free(q->x[i]); free(q->x[i]);
} }
} if (q->symbols[i]) {
for (int j=0;j<q->nof_rx_antennas;j++) { free(q->symbols[i]);
if (q->symbols[j]) { }
free(q->symbols[j]); if (q->is_ue) {
for (int j=0;j<q->nof_rx_antennas;j++) {
if (q->ce[i][j]) {
free(q->ce[i][j]);
}
}
} }
} }
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
@ -205,6 +178,39 @@ void srslte_pdcch_free(srslte_pdcch_t *q) {
} }
int srslte_pdcch_set_cell(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
regs != NULL &&
srslte_cell_isvalid(&cell))
{
q->regs = regs;
/* Allocate memory for the maximum number of PDCCH bits (CFI=3) */
q->max_bits = (srslte_regs_pdcch_nregs(q->regs, 3) / 9) * 72;
INFO("PDCCH: Cell config PCI=%d, %d ports.\n",
q->cell.id, q->cell.nof_ports);
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
// we need to pregenerate the sequence for the maximum number of bits, which is 8 times
// the maximum number of REGs (for CFI=3)
if (srslte_sequence_pdcch(&q->seq[i], 2 * i, q->cell.id, 8*srslte_regs_pdcch_nregs(q->regs, 3))) {
return SRSLTE_ERROR;
}
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
uint32_t srslte_pdcch_ue_locations(srslte_pdcch_t *q, srslte_dci_location_t *c, uint32_t max_candidates, uint32_t 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)
{ {

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

@ -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,22 @@ void srslte_phich_reset(srslte_phich_t *q, cf_t *slot_symbols[SRSLTE_MAX_PORTS])
} }
} }
int srslte_phich_init(srslte_phich_t *q, srslte_regs_t *regs, srslte_cell_t cell)
{
return srslte_phich_init_multi(q, regs, cell, 1);
}
/** Initializes the phich channel receiver */ /** Initializes the phich channel receiver */
int srslte_phich_init_multi(srslte_phich_t *q, srslte_regs_t *regs, srslte_cell_t cell, uint32_t nof_rx_antennas) int srslte_phich_init(srslte_phich_t *q, uint32_t nof_rx_antennas)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; 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 +100,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,10 @@ int srslte_prach_gen_seqs(srslte_prach_t *p)
int srslte_prach_init_cfg(srslte_prach_t *p, srslte_prach_cfg_t *cfg, uint32_t nof_prb) int srslte_prach_init_cfg(srslte_prach_t *p, srslte_prach_cfg_t *cfg, uint32_t nof_prb)
{ {
return srslte_prach_init(p, if (srslte_prach_init(p, srslte_symbol_sz(nof_prb))) {
return -1;
}
return srslte_prach_set_cell(p,
srslte_symbol_sz(nof_prb), srslte_symbol_sz(nof_prb),
cfg->config_idx, cfg->config_idx,
cfg->root_seq_idx, cfg->root_seq_idx,
@ -336,12 +342,74 @@ 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)
uint32_t N_ifft_ul, {
uint32_t config_idx, int ret = SRSLTE_ERROR;
uint32_t root_seq_index, if(p != NULL &&
bool high_speed_flag, max_N_ifft_ul < 2049)
uint32_t zero_corr_zone_config) {
bzero(p, sizeof(srslte_prach_t));
p->max_N_ifft_ul = max_N_ifft_ul;
// Set up containers
p->prach_bins = srslte_vec_malloc(sizeof(cf_t)*MAX_N_zc);
p->corr_spec = srslte_vec_malloc(sizeof(cf_t)*MAX_N_zc);
p->corr = srslte_vec_malloc(sizeof(float)*MAX_N_zc);
// Set up ZC FFTS
if(srslte_dft_plan(&p->zc_fft, MAX_N_zc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){
return SRSLTE_ERROR;
}
srslte_dft_plan_set_mirror(&p->zc_fft, false);
srslte_dft_plan_set_norm(&p->zc_fft, true);
if(srslte_dft_plan(&p->zc_ifft, MAX_N_zc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)){
return SRSLTE_ERROR;
}
srslte_dft_plan_set_mirror(&p->zc_ifft, false);
srslte_dft_plan_set_norm(&p->zc_ifft, false);
uint32_t fft_size_alloc = max_N_ifft_ul * DELTA_F/DELTA_F_RA;
p->ifft_in = (cf_t*)srslte_vec_malloc(fft_size_alloc*sizeof(cf_t));
p->ifft_out = (cf_t*)srslte_vec_malloc(fft_size_alloc*sizeof(cf_t));
if(srslte_dft_plan(&p->ifft, fft_size_alloc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) {
fprintf(stderr, "Error creating DFT plan\n");
return -1;
}
srslte_dft_plan_set_mirror(&p->ifft, true);
srslte_dft_plan_set_norm(&p->ifft, true);
if(srslte_dft_plan(&p->fft, fft_size_alloc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){
fprintf(stderr, "Error creating DFT plan\n");
return -1;
}
p->signal_fft = srslte_vec_malloc(sizeof(cf_t)*fft_size_alloc);
if (!p->signal_fft) {
fprintf(stderr, "Error allocating memory\n");
return -1;
}
srslte_dft_plan_set_mirror(&p->fft, true);
srslte_dft_plan_set_norm(&p->fft, false);
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid parameters\n");
}
return ret;
}
int srslte_prach_set_cell(srslte_prach_t *p,
uint32_t N_ifft_ul,
uint32_t config_idx,
uint32_t root_seq_index,
bool high_speed_flag,
uint32_t zero_corr_zone_config)
{ {
int ret = SRSLTE_ERROR; int ret = SRSLTE_ERROR;
if(p != NULL && if(p != NULL &&
@ -349,6 +417,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 +441,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 +459,15 @@ int srslte_prach_init(srslte_prach_t *p,
} }
} }
// Set up containers
p->prach_bins = srslte_vec_malloc(sizeof(cf_t)*p->N_zc);
p->corr_spec = srslte_vec_malloc(sizeof(cf_t)*p->N_zc);
p->corr = srslte_vec_malloc(sizeof(float)*p->N_zc);
// Set up ZC FFTS // 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); return SRSLTE_ERROR;
}
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;
} }
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 +475,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 +496,15 @@ int srslte_prach_init(srslte_prach_t *p,
p->deadzone = (uint32_t) ceil((float) samp_rate/((float) p->N_zc*subcarrier_spacing)); p->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 +547,7 @@ int srslte_prach_gen(srslte_prach_t *p,
memcpy(&p->ifft_in[begin], p->dft_seqs[seq_index], p->N_zc * sizeof(cf_t)); 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 +599,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 +616,7 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
srslte_vec_prod_conj_ccc(p->prach_bins, root_spec, p->corr_spec, p->N_zc); srslte_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 +679,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);

@ -416,33 +416,20 @@ void srslte_pucch_set_threshold(srslte_pucch_t *q, float format1_threshold) {
} }
/** 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);
@ -455,12 +442,16 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} }
clean_exit:
if (ret == SRSLTE_ERROR) {
srslte_pucch_free(q);
}
return ret; return ret;
} }
void srslte_pucch_free(srslte_pucch_t *q) { void srslte_pucch_free(srslte_pucch_t *q) {
if (q->users) { if (q->users) {
for (int rnti=0;rnti<SRSLTE_SIRNTI;rnti++) { for (int rnti=0;rnti<=SRSLTE_SIRNTI;rnti++) {
srslte_pucch_clear_rnti(q, rnti); srslte_pucch_clear_rnti(q, rnti);
} }
free(q->users); free(q->users);
@ -480,6 +471,31 @@ void srslte_pucch_free(srslte_pucch_t *q) {
bzero(q, sizeof(srslte_pucch_t)); bzero(q, sizeof(srslte_pucch_t));
} }
int srslte_pucch_set_cell(srslte_pucch_t *q, srslte_cell_t cell) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell)) {
srslte_pucch_cfg_default(&q->pucch_cfg);
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
// Precompute group hopping values u.
if (srslte_group_hopping_f_gh(q->f_gh, q->cell.id)) {
return SRSLTE_ERROR;
}
if (srslte_pucch_n_cs_cell(q->cell, q->n_cs_cell)) {
return SRSLTE_ERROR;
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
}
void srslte_pucch_clear_rnti(srslte_pucch_t *q, uint16_t rnti) { 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++) {
@ -498,6 +514,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,9 +242,11 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) {
goto clean; goto clean;
} }
q->ce = srslte_vec_malloc(sizeof(cf_t) * q->max_re); if (!q->is_ue) {
if (!q->ce) { q->ce = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
goto clean; if (!q->ce) {
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) {
@ -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) {
for (int rnti=0;rnti<SRSLTE_SIRNTI;rnti++) { if (q->is_ue) {
srslte_pusch_clear_rnti(q, rnti); srslte_pusch_free_rnti(q, 0);
} else {
for (int rnti=0;rnti<=SRSLTE_SIRNTI;rnti++) {
srslte_pusch_free_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,62 @@ 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] = calloc(1, sizeof(srslte_pusch_user_t));
if (q->users[rnti]) { if (!q->users[rnti_idx] || q->is_ue) {
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { if (!q->users[rnti_idx]) {
if (srslte_sequence_pusch(&q->users[rnti]->seq[i], rnti, 2 * i, q->cell.id, q->users[rnti_idx] = calloc(1, sizeof(srslte_pusch_user_t));
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { if (!q->users[rnti_idx]) {
return SRSLTE_ERROR; perror("calloc");
} return -1;
} }
q->users[rnti]->sequences_generated = true;
} }
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
if (srslte_sequence_pusch(&q->users[rnti_idx]->seq[i], rnti, 2 * i, q->cell.id,
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM)))
{
fprintf(stderr, "Error initializing PUSCH scrambling sequence\n");
srslte_pusch_free_rnti(q, rnti);
return SRSLTE_ERROR;
}
}
q->ue_rnti = rnti;
q->users[rnti_idx]->cell_id = q->cell.id;
q->users[rnti_idx]->sequence_generated = true;
} else {
fprintf(stderr, "Error generating PUSCH sequence: rnti=0x%x already generated\n", rnti);
} }
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
void srslte_pusch_clear_rnti(srslte_pusch_t *q, uint16_t rnti) { void srslte_pusch_free_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]); free(q->users[rnti_idx]);
q->users[rnti] = NULL; q->users[rnti_idx] = NULL;
q->ue_rnti = 0;
}
}
static srslte_sequence_t *get_user_sequence(srslte_pusch_t *q, uint16_t rnti, uint32_t sf_idx, uint32_t len)
{
uint32_t rnti_idx = q->is_ue?0:rnti;
// The scrambling sequence is pregenerated for all RNTIs in the eNodeB but only for C-RNTI in the UE
if (q->users[rnti_idx] && q->users[rnti_idx]->sequence_generated &&
q->users[rnti_idx]->cell_id == q->cell.id &&
q->ue_rnti == rnti &&
((rnti >= SRSLTE_CRNTI_START && rnti < SRSLTE_CRNTI_END) || !q->is_ue))
{
return &q->users[rnti_idx]->seq[sf_idx];
} else {
srslte_sequence_pusch(&q->tmp_seq, rnti, 2 * sf_idx, q->cell.id, len);
return &q->tmp_seq;
} }
} }
@ -445,16 +521,11 @@ int srslte_pusch_encode(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_softb
return SRSLTE_ERROR; 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 +599,13 @@ int srslte_pusch_decode(srslte_pusch_t *q,
srslte_predecoding_single(q->d, q->ce, q->z, cfg->nbits.nof_re, noise_estimate); 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 +616,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, 1)) {
fprintf(stderr, "Error creating PBCH object\n");
return -1;
}
if (srslte_pcfich_set_cell(&pcfich, &regs, cell)) {
fprintf(stderr, "Error creating PBCH object\n"); 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, 1)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
if (srslte_pcfich_set_cell(&pcfich, &regs, cell)) {
fprintf(stderr, "Error creating PBCH object\n"); 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_ue(&pdcch, cell.nof_prb, 1)) {
fprintf(stderr, "Error creating PDCCH object\n");
exit(-1);
}
if (srslte_pdcch_set_cell(&pdcch, &regs, cell)) {
fprintf(stderr, "Error creating PDCCH object\n"); fprintf(stderr, "Error creating PDCCH object\n");
exit(-1); exit(-1);
} }

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

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

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

@ -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, 1)) {
fprintf(stderr, "Error creating PBCH object\n");
return -1;
}
if (srslte_phich_set_cell(&phich, &regs, cell)) {
fprintf(stderr, "Error creating PBCH object\n"); 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, 1)) {
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,12 +85,14 @@ 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);
N_ifft_ul,
config_idx, srslte_prach_set_cell( p,
root_seq_idx, N_ifft_ul,
high_speed_flag, config_idx,
zero_corr_zone); root_seq_idx,
high_speed_flag,
zero_corr_zone);
uint32_t seq_index = 0; uint32_t seq_index = 0;
uint32_t frequency_offset = 0; uint32_t frequency_offset = 0;

@ -90,12 +90,14 @@ 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);
N_ifft_ul,
preamble_format, srslte_prach_set_cell( p,
root_seq_idx, N_ifft_ul,
high_speed_flag, preamble_format,
zero_corr_zone); root_seq_idx,
high_speed_flag,
zero_corr_zone);
uint32_t seq_index = 0; uint32_t seq_index = 0;
uint32_t frequency_offset = 0; uint32_t frequency_offset = 0;

@ -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;
@ -212,13 +230,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);
} }
@ -234,7 +252,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) {
@ -274,7 +292,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"
@ -108,11 +109,23 @@ int srslte_interp_linear_vector_init(srslte_interp_linsrslte_vec_t *q, uint32_t
perror("malloc"); perror("malloc");
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)
{ {

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

@ -103,7 +103,12 @@ int rf_mib_decoder(srslte_rf_t *rf, uint32_t nof_rx_antennas,cell_search_cfg_t *
srslte_ue_mib_sync_t ue_mib; 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) { srslte_cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, samples);
perror("realloc"); h->nsamples = samples;
} else {
fprintf(stderr, "Error in cfo_resize(): nof_samples must be lower than initialized\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
srslte_cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, samples);
h->nsamples = samples;
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) {

@ -30,6 +30,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <complex.h> #include <complex.h>
#include <math.h> #include <math.h>
#include <srslte/phy/sync/pss.h>
#include "srslte/phy/sync/pss.h" #include "srslte/phy/sync/pss.h"
#include "srslte/phy/dft/dft.h" #include "srslte/phy/dft/dft.h"
@ -93,8 +94,10 @@ int srslte_pss_synch_init_fft_offset(srslte_pss_synch_t *q, uint32_t frame_size,
* It correlates a signal of frame_size samples with the PSS sequence in the frequency * 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;
if (q != NULL) { if (q != NULL) {
@ -108,17 +111,19 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, uint32_t frame
q->N_id_2 = 10; q->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,21 +180,19 @@ 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
for(N_id_2 = 0; N_id_2<3; N_id_2++) for(N_id_2=0; N_id_2<3; N_id_2++)
q->pss_signal_freq_full[N_id_2] = srslte_vec_malloc(buffer_size * sizeof(cf_t)); q->pss_signal_freq_full[N_id_2] = srslte_vec_malloc(buffer_size * sizeof(cf_t));
if (srslte_conv_fft_cc_init(&q->conv_fft, frame_size, fft_size)) { if (srslte_conv_fft_cc_init(&q->conv_fft, frame_size, fft_size)) {
fprintf(stderr, "Error initiating convolution FFT\n"); fprintf(stderr, "Error initiating convolution FFT\n");
goto clean_and_exit; goto clean_and_exit;
} }
for(int i =0; i< 3; i++) for(int i=0; i<3; i++) {
{ srslte_dft_run_c(&q->conv_fft.filter_plan, q->pss_signal_time[i], q->pss_signal_freq_full[i]);
srslte_dft_run_c(&q->conv_fft.filter_plan, q->pss_signal_time[i], q->pss_signal_freq_full[i]);
} }
#endif #endif
@ -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,8 @@
#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/sync/sync.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"
@ -39,6 +41,8 @@
#define CFO_EMA_ALPHA 0.1 #define CFO_EMA_ALPHA 0.1
#define CP_EMA_ALPHA 0.1 #define CP_EMA_ALPHA 0.1
#define DEFAULT_CFO_TOL 50.0 // Hz
static bool fft_size_isvalid(uint32_t fft_size) { static bool fft_size_isvalid(uint32_t fft_size) {
if (fft_size >= SRSLTE_SYNC_FFT_SZ_MIN && fft_size <= SRSLTE_SYNC_FFT_SZ_MAX && (fft_size%64) == 0) { if (fft_size >= SRSLTE_SYNC_FFT_SZ_MIN && fft_size <= SRSLTE_SYNC_FFT_SZ_MAX && (fft_size%64) == 0) {
return true; return true;
@ -77,6 +81,9 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o
q->frame_size = frame_size; q->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->mean_cfo_isunset = true;
q->mean_cfo2_isunset = true;
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)) {
@ -89,11 +96,8 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o
goto clean_exit; goto clean_exit;
} }
// Set a CFO tolerance of approx 50 Hz // Set default CFO tolerance
srslte_cfo_set_tol(&q->cfocorr, 50.0/(15000.0*q->fft_size)); srslte_sync_set_cfo_tol(q, DEFAULT_CFO_TOL);
// Set a CFO tolerance of approx 50 Hz
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++) {
q->cfo_i_corr[i] = srslte_vec_malloc(sizeof(cf_t)*q->frame_size); q->cfo_i_corr[i] = srslte_vec_malloc(sizeof(cf_t)*q->frame_size);
@ -111,11 +115,11 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o
srslte_sync_set_cp(q, SRSLTE_CP_NORM); srslte_sync_set_cp(q, SRSLTE_CP_NORM);
q->decimate = decimate; q->decimate = decimate;
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 +166,80 @@ void srslte_sync_free(srslte_sync_t *q) {
} }
} }
int srslte_sync_resize(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offset, uint32_t fft_size) {
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
frame_size <= 307200 &&
fft_size_isvalid(fft_size))
{
ret = SRSLTE_ERROR;
if (frame_size > q->max_frame_size) {
fprintf(stderr, "Error in sync_resize(): frame_size must be lower than initialized\n");
return SRSLTE_ERROR;
}
q->detect_cp = true;
q->sss_en = true;
q->mean_cfo = 0;
q->mean_cfo2 = 0;
q->N_id_2 = 1000;
q->N_id_1 = 1000;
q->cfo_i = 0;
q->find_cfo_i = false;
q->find_cfo_i_initiated = false;
q->cfo_ema_alpha = CFO_EMA_ALPHA;
q->fft_size = fft_size;
q->frame_size = frame_size;
q->max_offset = max_offset;
q->sss_alg = SSS_FULL;
q->enable_cfo_corr = true;
if (srslte_pss_synch_resize(&q->pss, max_offset, fft_size, 0)) {
fprintf(stderr, "Error resizing PSS object\n");
return SRSLTE_ERROR;
}
if (srslte_sss_synch_resize(&q->sss, fft_size)) {
fprintf(stderr, "Error resizing SSS object\n");
return SRSLTE_ERROR;
}
if (srslte_cp_synch_resize(&q->cp_synch, fft_size)) {
fprintf(stderr, "Error resizing CFO\n");
return SRSLTE_ERROR;
}
if (srslte_cfo_resize(&q->cfocorr, q->frame_size)) {
fprintf(stderr, "Error resizing CFO\n");
return SRSLTE_ERROR;
}
if (srslte_cfo_resize(&q->cfocorr2, q->frame_size)) {
fprintf(stderr, "Error resizing CFO\n");
return SRSLTE_ERROR;
}
// Update CFO tolerance
srslte_sync_set_cfo_tol(q, q->current_cfo_tol);
DEBUG("SYNC init with frame_size=%d, max_offset=%d and fft_size=%d\n", frame_size, max_offset, fft_size);
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid parameters frame_size: %d, fft_size: %d\n", frame_size, fft_size);
}
return ret;
}
void srslte_sync_set_cfo_tol(srslte_sync_t *q, float tol) {
q->current_cfo_tol = tol;
srslte_cfo_set_tol(&q->cfocorr, tol/(15000.0*q->fft_size));
srslte_cfo_set_tol(&q->cfocorr2, tol/(15000.0*q->fft_size));
}
void srslte_sync_set_threshold(srslte_sync_t *q, float threshold) { void srslte_sync_set_threshold(srslte_sync_t *q, float threshold) {
q->threshold = threshold; q->threshold = threshold;
} }
@ -217,7 +295,10 @@ float srslte_sync_get_cfo(srslte_sync_t *q) {
} }
void srslte_sync_set_cfo(srslte_sync_t *q, float cfo) { void srslte_sync_set_cfo(srslte_sync_t *q, float cfo) {
q->mean_cfo = cfo; q->mean_cfo = cfo;
q->mean_cfo2 = cfo;
q->mean_cfo2_isunset = false;
q->mean_cfo_isunset = false;
} }
void srslte_sync_set_cfo_i(srslte_sync_t *q, int cfo_i) { void srslte_sync_set_cfo_i(srslte_sync_t *q, int cfo_i) {
@ -447,8 +528,13 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t
if (q->enable_cfo_corr) { if (q->enable_cfo_corr) {
float cfo = cfo_estimate(q, input); float cfo = cfo_estimate(q, input);
/* compute exponential moving average CFO */ if (q->mean_cfo_isunset) {
q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, q->cfo_ema_alpha); q->mean_cfo = cfo;
q->mean_cfo_isunset = false;
} else {
/* compute exponential moving average CFO */
q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, q->cfo_ema_alpha);
}
/* Correct CFO with the averaged CFO estimation */ /* Correct CFO with the averaged CFO estimation */
srslte_cfo_correct(&q->cfocorr2, input, q->temp, -q->mean_cfo / q->fft_size); srslte_cfo_correct(&q->cfocorr2, input, q->temp, -q->mean_cfo / q->fft_size);
@ -504,7 +590,12 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t
if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) { if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) {
float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]); float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]);
q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha); if (q->mean_cfo2_isunset) {
q->mean_cfo2 = cfo2;
q->mean_cfo2_isunset = true;
} else {
q->mean_cfo2 = SRSLTE_VEC_EMA(cfo2, q->mean_cfo2, q->cfo_ema_alpha);
}
ret = SRSLTE_SYNC_FOUND; ret = SRSLTE_SYNC_FOUND;
} else { } else {
@ -526,7 +617,7 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t
} }
void srslte_sync_reset(srslte_sync_t *q) { void srslte_sync_reset(srslte_sync_t *q) {
q->M_ext_avg = 0; q->M_ext_avg = 0;
q->M_norm_avg = 0; q->M_norm_avg = 0;
srslte_pss_synch_reset(&q->pss); srslte_pss_synch_reset(&q->pss);
} }

@ -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 {

@ -27,6 +27,7 @@
#include "srslte/phy/ue/ue_dl.h" #include "srslte/phy/ue/ue_dl.h"
#include <string.h> #include <string.h>
#include <srslte/srslte.h>
#define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb) #define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb)
@ -35,6 +36,7 @@
#define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp) #define CURRENT_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)
const static srslte_dci_format_t ue_dci_formats[8][2] = { const static srslte_dci_format_t ue_dci_formats[8][2] = {
/* Mode 1 */ {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1}, /* Mode 1 */ {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1},
@ -51,57 +53,50 @@ static srslte_dci_format_t common_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FO
const uint32_t nof_common_formats = 2; 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,
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(&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, nof_rx_antennas)) {
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_ue(&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_rx(&q->pdsch, q->cell, nof_rx_antennas)) { if (srslte_pdsch_init_ue(&q->pdsch, max_prb, nof_rx_antennas)) {
fprintf(stderr, "Error creating PDSCH object\n"); fprintf(stderr, "Error creating PDSCH object\n");
goto clean_exit; goto clean_exit;
} }
for (int i = 0; i < SRSLTE_MAX_TB; i++) { for (int i = 0; i < SRSLTE_MAX_TB; i++) {
q->softbuffers[i] = srslte_vec_malloc(sizeof(srslte_softbuffer_rx_t)); q->softbuffers[i] = srslte_vec_malloc(sizeof(srslte_softbuffer_rx_t));
if (!q->softbuffers[i]) { if (!q->softbuffers[i]) {
@ -109,25 +104,25 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
goto clean_exit; goto clean_exit;
} }
if (srslte_softbuffer_rx_init(q->softbuffers[i], q->cell.nof_prb)) { if (srslte_softbuffer_rx_init(q->softbuffers[i], max_prb)) {
fprintf(stderr, "Error initiating soft buffer\n"); 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-5f/q->fft.symbol_sz); srslte_cfo_set_tol(&q->sfo_correct, 1e-5f/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;
@ -136,14 +131,13 @@ int srslte_ue_dl_init(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:
@ -173,7 +167,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]);
} }
@ -183,11 +177,74 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) {
} }
} }
int srslte_ue_dl_set_cell(srslte_ue_dl_t *q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
q->pkt_errors = 0;
q->pkts_total = 0;
q->pending_ul_dci_rnti = 0;
q->sample_offset = 0;
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
if (q->cell.nof_prb != 0) {
srslte_regs_free(&q->regs);
}
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
if (srslte_regs_init(&q->regs, q->cell)) {
fprintf(stderr, "Error resizing REGs\n");
return SRSLTE_ERROR;
}
if (srslte_cfo_resize(&q->sfo_correct, q->cell.nof_prb*SRSLTE_NRE)) {
fprintf(stderr, "Error resizing SFO correct\n");
return SRSLTE_ERROR;
}
srslte_cfo_set_tol(&q->sfo_correct, 1e-5/q->fft.symbol_sz);
if (srslte_ofdm_rx_set_prb(&q->fft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error resizing FFT\n");
return SRSLTE_ERROR;
}
if (srslte_chest_dl_set_cell(&q->chest, q->cell)) {
fprintf(stderr, "Error resizing channel estimator\n");
return SRSLTE_ERROR;
}
if (srslte_pcfich_set_cell(&q->pcfich, &q->regs, q->cell)) {
fprintf(stderr, "Error resizing PCFICH object\n");
return SRSLTE_ERROR;
}
if (srslte_phich_set_cell(&q->phich, &q->regs, q->cell)) {
fprintf(stderr, "Error resizing PHICH object\n");
return SRSLTE_ERROR;
}
if (srslte_pdcch_set_cell(&q->pdcch, &q->regs, q->cell)) {
fprintf(stderr, "Error resizing PDCCH object\n");
return SRSLTE_ERROR;
}
if (srslte_pdsch_set_cell(&q->pdsch, q->cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
return SRSLTE_ERROR;
}
q->current_rnti = 0;
}
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
}
return ret;
}
/* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while /* 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
*/ */
void srslte_ue_dl_set_rnti(srslte_ue_dl_t *q, uint16_t rnti) { void srslte_ue_dl_set_rnti(srslte_ue_dl_t *q, uint16_t rnti) {
srslte_pdsch_set_rnti(&q->pdsch, rnti); srslte_pdsch_set_rnti(&q->pdsch, rnti);
// Compute UE-specific and Common search space for this RNTI // Compute UE-specific and Common search space for this RNTI
@ -739,11 +796,11 @@ bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_pr
} }
void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuffer, uint32_t tti, uint32_t rv_idx, uint16_t rnti, uint32_t cfi) { 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));

@ -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)
{ {
@ -142,7 +169,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 +188,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 +211,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 +222,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 +261,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"
@ -128,39 +129,41 @@ 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,
int (recv_callback)(void*, void*, uint32_t,srslte_timestamp_t*), bool search_cell,
void *stream_handler) int (recv_callback)(void*, void*, uint32_t,srslte_timestamp_t*),
void *stream_handler)
{ {
int ret = srslte_ue_sync_init_multi(q, cell, recv_callback_multi_to_single, 1, (void*) q); int ret = srslte_ue_sync_init_multi(q, max_prb, search_cell, recv_callback_multi_to_single, 1, (void*) q);
q->recv_callback_single = recv_callback; q->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,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t,srslte_timestamp_t*), bool search_cell,
uint32_t nof_rx_antennas, int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t,srslte_timestamp_t*),
void *stream_handler, uint32_t nof_rx_antennas,
int decimate) void *stream_handler,
int decimate)
{ {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
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)
{ {
@ -171,8 +174,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;
@ -180,34 +182,31 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
q->sample_offset_correct_period = DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD; q->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;
@ -219,6 +218,90 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
} }
} }
ret = SRSLTE_SUCCESS;
}
clean_exit:
if (ret == SRSLTE_ERROR) {
srslte_ue_sync_free(q);
}
return ret;
}
uint32_t srslte_ue_sync_sf_len(srslte_ue_sync_t *q) {
return q->frame_len;
}
void srslte_ue_sync_free(srslte_ue_sync_t *q) {
if (q->do_agc) {
srslte_agc_free(&q->agc);
}
if (!q->file_mode) {
srslte_sync_free(&q->sfind);
srslte_sync_free(&q->strack);
} else {
srslte_filesource_free(&q->file_source);
}
bzero(q, sizeof(srslte_ue_sync_t));
}
int srslte_ue_sync_set_cell(srslte_ue_sync_t *q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_nofprb_isvalid(cell.nof_prb))
{
ret = SRSLTE_ERROR;
if (cell.nof_prb > q->max_prb) {
fprintf(stderr, "Error in ue_sync_set_cell(): cell.nof_prb must be lower than initialized\n");
return SRSLTE_ERROR;
}
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
q->fft_size = srslte_symbol_sz(q->cell.nof_prb);
q->sf_len = SRSLTE_SF_LEN(q->fft_size);
q->agc_period = 0;
if (cell.id == 1000) {
/* If the cell is unkown, we search PSS/SSS in 5 ms */
q->nof_recv_sf = 5;
q->decode_sss_on_track = true;
} else {
/* If the cell is known, we work on a 1ms basis */
q->nof_recv_sf = 1;
q->decode_sss_on_track = true;
}
q->frame_len = q->nof_recv_sf*q->sf_len;
if(q->fft_size < 700 && q->decimate) {
q->decimate = 1;
}
if(srslte_sync_resize(&q->sfind, q->frame_len, q->frame_len, q->fft_size)) {
fprintf(stderr, "Error initiating sync find\n");
return SRSLTE_ERROR;
}
if (cell.id == 1000) {
if(srslte_sync_resize(&q->strack, q->frame_len, TRACK_FRAME_SIZE, q->fft_size)) {
fprintf(stderr, "Error initiating sync track\n");
return SRSLTE_ERROR;
}
} else {
if(srslte_sync_resize(&q->strack, q->frame_len, SRSLTE_CP_LEN_NORM(1,q->fft_size), q->fft_size)) {
fprintf(stderr, "Error initiating sync track\n");
return SRSLTE_ERROR;
}
}
if (cell.id == 1000) { if (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
@ -264,29 +347,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));
@ -317,6 +380,8 @@ void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, float cfo) {
srslte_sync_set_cfo(&q->strack, cfo/15000); srslte_sync_set_cfo(&q->strack, cfo/15000);
} }
void srslte_ue_sync_set_cfo_tol(srslte_ue_sync_t *q, float cfo_tol) {}
float srslte_ue_sync_get_sfo(srslte_ue_sync_t *q) { float srslte_ue_sync_get_sfo(srslte_ue_sync_t *q) {
return q->mean_sfo/5e-3; return q->mean_sfo/5e-3;
} }
@ -649,7 +714,7 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE
} }
if (q->correct_cfo) { 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,22 @@
#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))
#define DEFAULT_CFO_TOL 50.0 // Hz
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 +60,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_ue_ul_set_cfo_tol(q, DEFAULT_CFO_TOL);
if (srslte_pusch_init(&q->pusch, q->cell)) { if (srslte_pusch_init_ue(&q->pusch, max_prb)) {
fprintf(stderr, "Error creating PUSCH object\n"); 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 +102,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 +114,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 +139,54 @@ void srslte_ue_ul_free(srslte_ue_ul_t *q) {
} }
} }
int srslte_ue_ul_set_cell(srslte_ue_ul_t *q,
srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell))
{
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
if (srslte_ofdm_tx_set_prb(&q->fft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error resizing FFT\n");
return SRSLTE_ERROR;
}
if (srslte_cfo_resize(&q->cfo, SRSLTE_SF_LEN_PRB(q->cell.nof_prb))) {
fprintf(stderr, "Error resizing CFO object\n");
return SRSLTE_ERROR;
}
srslte_ue_ul_set_cfo_tol(q, q->current_cfo_tol);
if (srslte_pusch_set_cell(&q->pusch, q->cell)) {
fprintf(stderr, "Error resizing PUSCH object\n");
return SRSLTE_ERROR;
}
if (srslte_pucch_set_cell(&q->pucch, q->cell)) {
fprintf(stderr, "Error resizing PUSCH object\n");
return SRSLTE_ERROR;
}
if (srslte_refsignal_ul_set_cell(&q->signals, q->cell)) {
fprintf(stderr, "Error resizing srslte_refsignal_ul\n");
return SRSLTE_ERROR;
}
q->signals_pregenerated = false;
}
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
}
return ret;
}
void srslte_ue_ul_set_cfo_tol(srslte_ue_ul_t *q, float tol) {
q->current_cfo_tol = tol;
srslte_cfo_set_tol(&q->cfo, tol/(15000.0*srslte_symbol_sz(q->cell.nof_prb)));
}
void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q, float cur_cfo) { 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 +201,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
*/ */

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

@ -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);

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

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

@ -42,13 +42,14 @@ namespace srslte {
gw::gw() gw::gw()
:if_up(false) :if_up(false)
{} {
current_ip_addr = 0;
}
void gw::init(srsue::pdcp_interface_gw *pdcp_, srsue::rrc_interface_gw *rrc_, srsue::ue_interface *ue_, log *gw_log_, uint32_t lcid_) void gw::init(srsue::pdcp_interface_gw *pdcp_, srsue::ue_interface *ue_, log *gw_log_, uint32_t lcid_)
{ {
pool = byte_buffer_pool::get_instance(); pool = byte_buffer_pool::get_instance();
pdcp = pdcp_; pdcp = pdcp_;
rrc = rrc_;
ue = ue_; ue = ue_;
gw_log = gw_log_; gw_log = gw_log_;
lcid = lcid_; lcid = lcid_;
@ -78,6 +79,8 @@ void gw::stop()
thread_cancel(); thread_cancel();
} }
wait_thread_finish(); wait_thread_finish();
current_ip_addr = 0;
} }
// TODO: tear down TUN device? // TODO: tear down TUN device?
@ -127,38 +130,42 @@ void gw::write_pdu(uint32_t lcid, byte_buffer_t *pdu)
*******************************************************************************/ *******************************************************************************/
error_t gw::setup_if_addr(uint32_t ip_addr, char *err_str) error_t gw::setup_if_addr(uint32_t ip_addr, char *err_str)
{ {
if(!if_up) if (ip_addr != current_ip_addr) {
{ if(!if_up)
{
if(init_if(err_str)) if(init_if(err_str))
{ {
gw_log->error("init_if failed\n"); gw_log->error("init_if failed\n");
return(ERROR_CANT_START); return(ERROR_CANT_START);
} }
} }
// Setup the IP address // Setup the IP address
sock = socket(AF_INET, SOCK_DGRAM, 0); sock = socket(AF_INET, SOCK_DGRAM, 0);
ifr.ifr_addr.sa_family = AF_INET; ifr.ifr_addr.sa_family = AF_INET;
((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = htonl(ip_addr); ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr = htonl(ip_addr);
if(0 > ioctl(sock, SIOCSIFADDR, &ifr)) if(0 > ioctl(sock, SIOCSIFADDR, &ifr))
{ {
err_str = strerror(errno); err_str = strerror(errno);
gw_log->debug("Failed to set socket address: %s\n", err_str); gw_log->debug("Failed to set socket address: %s\n", err_str);
close(tun_fd); close(tun_fd);
return(ERROR_CANT_START); return(ERROR_CANT_START);
} }
ifr.ifr_netmask.sa_family = AF_INET; ifr.ifr_netmask.sa_family = AF_INET;
((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0"); ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0");
if(0 > ioctl(sock, SIOCSIFNETMASK, &ifr)) if(0 > ioctl(sock, SIOCSIFNETMASK, &ifr))
{ {
err_str = strerror(errno); err_str = strerror(errno);
gw_log->debug("Failed to set socket netmask: %s\n", err_str); gw_log->debug("Failed to set socket netmask: %s\n", err_str);
close(tun_fd); close(tun_fd);
return(ERROR_CANT_START); return(ERROR_CANT_START);
} }
current_ip_addr = ip_addr;
// Setup a thread to receive packets from the TUN device // Setup a thread to receive packets from the TUN device
start(GW_THREAD_PRIO); start(GW_THREAD_PRIO);
}
return(ERROR_NONE); return(ERROR_NONE);
} }
@ -250,11 +257,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->rrc_connected() || !rrc->have_drb())) {
rrc->rrc_connect();
usleep(1000);
}
if (!run_enable) { if (!run_enable) {
break; break;
} }

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

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

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

Loading…
Cancel
Save