Merge branch 'next_novolk' of https://github.com/softwareradiosystems/srsLTE into next_novolk

This commit is contained in:
Xavier Arteaga 2017-09-25 13:23:50 +02:00
commit 0c52c5651d
145 changed files with 5377 additions and 3218 deletions

View File

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

View File

@ -16,6 +16,7 @@ FIND_LIBRARY(
HINTS $ENV{UHD_DIR}/lib
PATHS /usr/local/lib
/usr/lib
/usr/lib/x86_64-linux-gnu
/usr/local/lib64
/usr/local/lib32
)

View File

@ -241,19 +241,31 @@ int main(int argc, char **argv) {
srslte_rf_stop_rx_stream(&rf);
srslte_rf_flush_buffer(&rf);
if (srslte_ue_sync_init_multi(&ue_sync, cell, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
if (srslte_ue_sync_init_multi(&ue_sync, cell.nof_prb, cell.id==1000, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
fprintf(stderr, "Error initiating ue_sync\n");
return -1;
}
if (srslte_ue_dl_init(&ue_dl, cell, 1)) {
if (srslte_ue_sync_set_cell(&ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n");
return -1;
}
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
return -1;
}
if (srslte_ue_mib_init(&ue_mib, cell)) {
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
return -1;
}
if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
return -1;
}
if (srslte_ue_mib_set_cell(&ue_mib, cell)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
return -1;
}
/* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */
srslte_ue_dl_set_rnti(&ue_dl, SRSLTE_SIRNTI);
@ -264,11 +276,15 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error initiating FFT\n");
return -1;
}
if (srslte_chest_dl_init(&chest, cell)) {
if (srslte_chest_dl_init(&chest, cell.nof_prb)) {
fprintf(stderr, "Error initiating channel estimator\n");
return -1;
}
if (srslte_chest_dl_set_cell(&chest, cell)) {
fprintf(stderr, "Error initiating channel estimator\n");
return -1;
}
int sf_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);
cf_t *sf_symbols = srslte_vec_malloc(sf_re * sizeof(cf_t));

View File

@ -188,6 +188,18 @@ int main(int argc, char **argv) {
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
signal(SIGINT, sig_int_handler);
if (srslte_ue_cellsearch_init_multi(&cs, cell_detect_config.max_frames_pss, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
fprintf(stderr, "Error initiating UE cell detect\n");
exit(-1);
}
if (cell_detect_config.max_frames_pss) {
srslte_ue_cellsearch_set_nof_valid_frames(&cs, cell_detect_config.nof_valid_pss_frames);
}
if (cell_detect_config.init_agc) {
srslte_ue_sync_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_wrapper, cell_detect_config.init_agc);
}
for (freq=0;freq<nof_freqs && !go_exit;freq++) {
/* set rf_freq */
@ -203,18 +215,6 @@ int main(int argc, char **argv) {
}
bzero(found_cells, 3*sizeof(srslte_ue_cellsearch_result_t));
if (srslte_ue_cellsearch_init_multi(&cs, cell_detect_config.max_frames_pss, srslte_rf_recv_wrapper, 1, (void*) &rf)) {
fprintf(stderr, "Error initiating UE cell detect\n");
exit(-1);
}
if (cell_detect_config.max_frames_pss) {
srslte_ue_cellsearch_set_nof_valid_frames(&cs, cell_detect_config.nof_valid_pss_frames);
}
if (cell_detect_config.init_agc) {
srslte_ue_sync_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_wrapper, cell_detect_config.init_agc);
}
INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ/1000000);
srslte_rf_set_rx_srate(&rf, SRSLTE_CS_SAMP_FREQ);
@ -222,7 +222,6 @@ int main(int argc, char **argv) {
srslte_rf_start_rx_stream(&rf);
n = srslte_ue_cellsearch_scan(&cs, found_cells, NULL);
srslte_ue_cellsearch_free(&cs);
if (n < 0) {
fprintf(stderr, "Error searching cell\n");
exit(-1);
@ -254,7 +253,7 @@ int main(int argc, char **argv) {
}
}
}
printf("\n\nFound %d cells\n", n_found_cells);
for (int i=0;i<n_found_cells;i++) {
printf("Found CELL %.1f MHz, EARFCN=%d, PHYID=%d, %d PRB, %d ports, PSS power=%.1f dBm\n",
@ -268,7 +267,8 @@ int main(int argc, char **argv) {
}
printf("\nBye\n");
srslte_ue_cellsearch_free(&cs);
srslte_rf_close(&rf);
exit(0);
}

View File

@ -292,7 +292,11 @@ void base_init() {
exit(-1);
}
srslte_ofdm_set_normalize(&ifft, true);
if (srslte_pbch_init(&pbch, cell)) {
if (srslte_pbch_init(&pbch)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
if (srslte_pbch_set_cell(&pbch, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
@ -302,7 +306,11 @@ void base_init() {
exit(-1);
}
if (srslte_pcfich_init(&pcfich, &regs, cell)) {
if (srslte_pcfich_init(&pcfich, 1)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
if (srslte_pcfich_set_cell(&pcfich, &regs, cell)) {
fprintf(stderr, "Error creating PBCH object\n");
exit(-1);
}
@ -312,13 +320,20 @@ void base_init() {
exit(-1);
}
if (srslte_pdcch_init_tx(&pdcch, &regs, cell)) {
if (srslte_pdcch_init_enb(&pdcch, cell.nof_prb)) {
fprintf(stderr, "Error creating PDCCH object\n");
exit(-1);
}
if (srslte_pdcch_set_cell(&pdcch, &regs, cell)) {
fprintf(stderr, "Error creating PDCCH object\n");
exit(-1);
}
bzero(&pdsch, sizeof(srslte_pdsch_t));
if (srslte_pdsch_init_tx(&pdsch, cell)) {
if (srslte_pdsch_init_enb(&pdsch, cell.nof_prb)) {
fprintf(stderr, "Error creating PDSCH object\n");
exit(-1);
}
if (srslte_pdsch_set_cell(&pdsch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
exit(-1);
}
@ -660,7 +675,11 @@ int main(int argc, char **argv) {
srslte_sss_generate(sss_signal0, sss_signal5, cell.id);
/* Generate CRS signals */
if (srslte_chest_dl_init(&est, cell)) {
if (srslte_chest_dl_init(&est, cell.nof_prb)) {
fprintf(stderr, "Error initializing equalizer\n");
exit(-1);
}
if (srslte_chest_dl_set_cell(&est, cell)) {
fprintf(stderr, "Error initializing equalizer\n");
exit(-1);
}
@ -774,9 +793,11 @@ int main(int argc, char **argv) {
}
} else {
INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.mcs[0].tbs + pdsch_cfg.grant.mcs[1].tbs);
for (uint32_t tb = 0; tb < pdsch_cfg.grant.nof_tb; tb++) {
for (i = 0; i < pdsch_cfg.grant.mcs[tb].tbs / 8; i++) {
data[tb][i] = (uint8_t) rand();
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
if (pdsch_cfg.grant.tb_en[tb]) {
for (i = 0; i < pdsch_cfg.grant.mcs[tb].tbs / 8; i++) {
data[tb][i] = (uint8_t) rand();
}
}
}
/* Uncomment this to transmit on sf 0 and 5 only */
@ -832,10 +853,12 @@ int main(int argc, char **argv) {
}
if (net_port > 0 && net_packet_ready) {
if (null_file_sink) {
for (uint32_t tb = 0; tb < pdsch_cfg.grant.nof_tb; tb++) {
srslte_bit_pack_vector(data[tb], data_tmp, pdsch_cfg.grant.mcs[tb].tbs);
if (srslte_netsink_write(&net_sink, data_tmp, 1 + (pdsch_cfg.grant.mcs[tb].tbs - 1) / 8) < 0) {
fprintf(stderr, "Error sending data through UDP socket\n");
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
if (pdsch_cfg.grant.tb_en[tb]) {
srslte_bit_pack_vector(data[tb], data_tmp, pdsch_cfg.grant.mcs[tb].tbs);
if (srslte_netsink_write(&net_sink, data_tmp, 1 + (pdsch_cfg.grant.mcs[tb].tbs - 1) / 8) < 0) {
fprintf(stderr, "Error sending data through UDP socket\n");
}
}
}
}

View File

@ -475,23 +475,42 @@ int main(int argc, char **argv) {
//ue_sync.decimate = prog_args.decimate;
}
}
if (srslte_ue_sync_init_multi_decim(&ue_sync, cell, srslte_rf_recv_wrapper, prog_args.rf_nof_rx_ant, (void*) &rf,decimate)) {
if (srslte_ue_sync_init_multi_decim(&ue_sync,
cell.nof_prb,
cell.id==1000,
srslte_rf_recv_wrapper,
prog_args.rf_nof_rx_ant,
(void*) &rf,decimate))
{
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
if (srslte_ue_sync_set_cell(&ue_sync, cell))
{
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
#endif
}
if (srslte_ue_mib_init(&ue_mib, cell)) {
if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1);
}
}
if (srslte_ue_mib_set_cell(&ue_mib, cell)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1);
}
if (srslte_ue_dl_init(&ue_dl, cell, prog_args.rf_nof_rx_ant)) { // This is the User RNTI
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, prog_args.rf_nof_rx_ant)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1);
}
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1);
}
for (int i=0;i<prog_args.rf_nof_rx_ant;i++) {
sf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
@ -518,7 +537,7 @@ int main(int argc, char **argv) {
// Variables for measurements
uint32_t nframes=0;
uint32_t ri = 0, pmi = 0;
uint8_t ri = 0, pmi = 0;
float rsrp0=0.0, rsrp1=0.0, rsrq=0.0, noise=0.0, enodebrate = 0.0, uerate = 0.0,
sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS], cn = 0.0;
bool decode_pdsch = false;
@ -566,6 +585,10 @@ int main(int argc, char **argv) {
/* If a new line is detected set verbose level to Debug */
if (fgets(input, sizeof(input), stdin)) {
srslte_verbose = SRSLTE_VERBOSE_DEBUG;
ue_dl.pkt_errors = 0;
ue_dl.pkts_total = 0;
ue_dl.nof_detected = 0;
nof_trials = 0;
}
}
@ -641,9 +664,10 @@ int main(int argc, char **argv) {
/* Send data if socket active */
if (prog_args.net_port > 0) {
// FIXME: UDP Data transmission does not work
for (uint32_t tb = 0; tb < ue_dl.pdsch_cfg.grant.nof_tb; tb++) {
srslte_netsink_write(&net_sink, data[tb], 1 + (ue_dl.pdsch_cfg.grant.mcs[tb].tbs - 1) / 8);
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
if (ue_dl.pdsch_cfg.grant.tb_en[tb]) {
srslte_netsink_write(&net_sink, data[tb], 1 + (ue_dl.pdsch_cfg.grant.mcs[tb].tbs - 1) / 8);
}
}
}
@ -704,7 +728,7 @@ int main(int argc, char **argv) {
/* Print basic Parameters */
PRINT_LINE(" nof layers: %d", ue_dl.pdsch_cfg.nof_layers);
PRINT_LINE("nof codewords: %d", ue_dl.pdsch_cfg.grant.nof_tb);
PRINT_LINE("nof codewords: %d", SRSLTE_RA_DL_GRANT_NOF_TB(&ue_dl.pdsch_cfg.grant));
PRINT_LINE(" CFO: %+5.2f kHz", srslte_ue_sync_get_cfo(&ue_sync) / 1000);
PRINT_LINE(" SNR: %+5.1f dB | %+5.1f dB", 10 * log10(rsrp0 / noise), 10 * log10(rsrp1 / noise));
PRINT_LINE(" Rb: %6.2f / %6.2f Mbps (net/maximum)", uerate, enodebrate);
@ -759,10 +783,12 @@ int main(int argc, char **argv) {
if (sfn == 1024) {
sfn = 0;
PRINT_LINE_ADVANCE_CURSOR();
/*
ue_dl.pkt_errors = 0;
ue_dl.pkts_total = 0;
ue_dl.nof_detected = 0;
nof_trials = 0;
nof_trials = 0;
*/
}
}

View File

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

View File

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

View File

@ -102,6 +102,15 @@ public:
virtual void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu) = 0;
virtual uint32_t get_ul_count() = 0;
virtual bool get_s_tmsi(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi) = 0;
virtual void plmn_found(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id, uint16_t tracking_area_code) = 0;
};
// NAS interface for UE
class nas_interface_ue
{
public:
virtual void attach_request() = 0;
virtual void deattach_request() = 0;
};
// RRC interface for MAC
@ -123,6 +132,7 @@ class rrc_interface_phy
public:
virtual void in_sync() = 0;
virtual void out_of_sync() = 0;
virtual void cell_found(uint32_t earfcn, srslte_cell_t phy_cell, float rsrp) = 0;
};
// RRC interface for NAS
@ -133,18 +143,11 @@ public:
virtual uint16_t get_mcc() = 0;
virtual uint16_t get_mnc() = 0;
virtual void enable_capabilities() = 0;
virtual void plmn_search() = 0;
virtual void plmn_select(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) = 0;
virtual std::string get_rb_name(uint32_t lcid) = 0;
};
// RRC interface for GW
class rrc_interface_gw
{
public:
virtual bool rrc_connected() = 0;
virtual void rrc_connect() = 0;
virtual bool have_drb() = 0;
};
// RRC interface for PDCP
class rrc_interface_pdcp
{
@ -281,6 +284,8 @@ public:
bool last_ndi[SRSLTE_MAX_CODEWORDS];
uint32_t n_bytes[SRSLTE_MAX_CODEWORDS];
int rv[SRSLTE_MAX_CODEWORDS];
bool tb_en[SRSLTE_MAX_CODEWORDS];
bool tb_cw_swap;
uint16_t rnti;
bool is_from_rar;
bool is_sps_release;
@ -421,8 +426,8 @@ typedef struct {
int worker_cpu_mask;
int sync_cpu_affinity;
uint32_t nof_rx_ant;
std::string equalizer_mode;
uint32_t nof_rx_ant;
std::string equalizer_mode;
int cqi_max;
int cqi_fixed;
float snr_ema_coeff;
@ -442,9 +447,8 @@ class phy_interface_mac_common
{
public:
/* Start synchronization with strongest cell in the current carrier frequency */
virtual void sync_start() = 0;
virtual void sync_stop() = 0;
virtual bool sync_status() = 0;
/* Sets a C-RNTI allowing the PHY to pregenerate signals if necessary */
virtual void set_crnti(uint16_t rnti) = 0;
@ -511,9 +515,15 @@ public:
virtual void set_config_common(phy_cfg_common_t *common) = 0;
virtual void set_config_tdd(LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd) = 0;
virtual void set_config_64qam_en(bool enable) = 0;
/* Cell search and selection procedures */
virtual void cell_search_start() = 0;
virtual void cell_search_next() = 0;
virtual bool cell_select(uint32_t earfcn, srslte_cell_t cell) = 0;
virtual bool sync_stop() = 0;
/* Is the PHY downlink synchronized? */
virtual bool status_is_sync() = 0;
virtual bool sync_status() = 0;
/* Configure UL using parameters written with set_param() */
virtual void configure_ul_params(bool pregen_disabled = false) = 0;

View File

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

View File

@ -77,9 +77,13 @@ typedef struct {
SRSLTE_API int srslte_chest_ul_init(srslte_chest_ul_t *q,
srslte_cell_t cell);
uint32_t max_prb);
SRSLTE_API void srslte_chest_ul_free(srslte_chest_ul_t *q);
SRSLTE_API int srslte_chest_ul_set_cell(srslte_chest_ul_t *q,
srslte_cell_t cell);
SRSLTE_API void srslte_chest_ul_free(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,

View File

@ -53,7 +53,10 @@ typedef struct SRSLTE_API {
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);

View File

@ -94,7 +94,10 @@ typedef struct {
} srslte_refsignal_srs_pregen_t;
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);
@ -115,9 +118,13 @@ SRSLTE_API uint32_t srslte_refsignal_dmrs_pucch_symbol(uint32_t m,
SRSLTE_API bool srslte_refsignal_dmrs_pusch_cfg_isvalid(srslte_refsignal_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *cfg,
uint32_t nof_prb);
uint32_t nof_prb);
SRSLTE_API int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q,
SRSLTE_API int srslte_refsignal_dmrs_pusch_pregen_init(srslte_refsignal_ul_t *q,
srslte_refsignal_ul_dmrs_pregen_t *pregen,
uint32_t max_prb);
SRSLTE_API int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q,
srslte_refsignal_ul_dmrs_pregen_t *pregen);
SRSLTE_API void srslte_refsignal_dmrs_pusch_pregen_free(srslte_refsignal_ul_t *q,

View File

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

View File

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

View File

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

View File

@ -47,6 +47,7 @@
/* This is common for both directions */
typedef struct SRSLTE_API{
srslte_dft_plan_t fft_plan;
uint32_t max_prb;
uint32_t nof_symbols;
uint32_t symbol_sz;
uint32_t nof_guards;
@ -56,18 +57,27 @@ typedef struct SRSLTE_API{
cf_t *tmp; // for removing zero padding
bool freq_shift;
float freq_shift_f;
cf_t *shift_buffer;
}srslte_ofdm_t;
SRSLTE_API int srslte_ofdm_init_(srslte_ofdm_t *q,
srslte_cp_t cp,
int symbol_sz,
int nof_prb,
int max_prb,
srslte_dft_dir_t dir);
SRSLTE_API int srslte_ofdm_rx_init(srslte_ofdm_t *q,
srslte_cp_t cp_type,
uint32_t 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);

View File

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

View File

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

View File

@ -41,11 +41,14 @@
#include "srslte/phy/common/phy_common.h"
#define SRSLTE_CQI_MAX_BITS 64
#define SRSLTE_DIF_CQI_MAX_BITS 3
#define SRSLTE_PMI_MAX_BITS 4
typedef struct {
bool configured;
uint32_t pmi_idx;
uint32_t ri_idx;
bool ri_idx_present;
bool simul_cqi_ack;
bool format_is_subband;
uint32_t subband_size;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -104,10 +104,12 @@ typedef struct SRSLTE_API {
uint32_t nof_prb;
uint32_t Qm[SRSLTE_MAX_CODEWORDS];
srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS];
uint32_t nof_tb;
bool tb_en[SRSLTE_MAX_CODEWORDS];
uint32_t pinfo;
} srslte_ra_dl_grant_t;
#define SRSLTE_RA_DL_GRANT_NOF_TB(G) ((((G)->tb_en[0])?1:0)+(((G)->tb_en[1])?1:0))
/** Unpacked DCI message for DL grant */
typedef struct SRSLTE_API {

View File

@ -64,6 +64,10 @@ typedef struct SRSLTE_API {
typedef struct SRSLTE_API {
uint8_t uci_cqi[SRSLTE_CQI_MAX_BITS];
uint32_t uci_cqi_len;
uint8_t uci_dif_cqi[SRSLTE_DIF_CQI_MAX_BITS];
uint32_t uci_dif_cqi_len;
uint8_t uci_pmi[SRSLTE_PMI_MAX_BITS];
uint8_t uci_pmi_len;
uint8_t uci_ri; // Only 1-bit supported for RI
uint32_t uci_ri_len;
uint8_t uci_ack; // 1st codeword bit for HARQ-ACK
@ -119,8 +123,9 @@ SRSLTE_API int srslte_uci_decode_cqi_pusch(srslte_uci_cqi_pusch_t *q,
bool *cqi_ack);
SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg,
uint8_t data,
uint32_t O_cqi,
uint8_t acks[2],
uint32_t nof_acks,
uint32_t O_cqi,
float beta,
uint32_t H_prime_total,
srslte_uci_bit_t *ri_bits);
@ -132,7 +137,8 @@ SRSLTE_API int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg,
uint32_t H_prime_total,
uint32_t O_cqi,
srslte_uci_bit_t *ack_bits,
uint8_t *data);
uint8_t acks[2],
uint32_t nof_acks);
SRSLTE_API int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
uint8_t data,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -119,13 +119,16 @@ typedef struct SRSLTE_API {
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_dl_init(srslte_ue_dl_t *q,
srslte_cell_t cell,
uint32_t max_prb,
uint32_t nof_rx_antennas);
SRSLTE_API void srslte_ue_dl_free(srslte_ue_dl_t *q);
SRSLTE_API int srslte_ue_dl_set_cell(srslte_ue_dl_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q,
cf_t *input[SRSLTE_MAX_PORTS],
cf_t *input[SRSLTE_MAX_PORTS],
uint32_t sf_idx,
uint32_t *cfi);
@ -182,12 +185,12 @@ SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q,
bool acks[SRSLTE_MAX_CODEWORDS]);
SRSLTE_API int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q,
uint32_t *ri,
uint32_t *pmi,
uint8_t *ri,
uint8_t *pmi,
float *current_sinr);
SRSLTE_API int srslte_ue_dl_ri_select(srslte_ue_dl_t *q,
uint32_t *ri,
uint8_t *ri,
float *cn);
SRSLTE_API bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q,

View File

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

View File

@ -69,6 +69,8 @@ typedef enum SRSLTE_API { SF_FIND, SF_TRACK} srslte_ue_sync_state_t;
typedef struct SRSLTE_API {
srslte_sync_t sfind;
srslte_sync_t strack;
uint32_t max_prb;
srslte_agc_t agc;
bool do_agc;
@ -125,22 +127,25 @@ typedef struct SRSLTE_API {
} srslte_ue_sync_t;
SRSLTE_API int srslte_ue_sync_init(srslte_ue_sync_t *q,
srslte_cell_t cell,
uint32_t max_prb,
bool search_cell,
int (recv_callback)(void*, void*, uint32_t, srslte_timestamp_t*),
void *stream_handler);
SRSLTE_API int srslte_ue_sync_init_multi(srslte_ue_sync_t *q,
srslte_cell_t cell,
SRSLTE_API int srslte_ue_sync_init_multi(srslte_ue_sync_t *q,
uint32_t max_prb,
bool search_cell,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*),
uint32_t nof_rx_antennas,
void *stream_handler);
SRSLTE_API int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
srslte_cell_t cell,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*),
uint32_t nof_rx_antennas,
void *stream_handler,
int decimate);
SRSLTE_API int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
uint32_t max_prb,
bool search_cell,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t, srslte_timestamp_t*),
uint32_t nof_rx_antennas,
void *stream_handler,
int decimate);
SRSLTE_API int srslte_ue_sync_init_file(srslte_ue_sync_t *q,
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 int srslte_ue_sync_set_cell(srslte_ue_sync_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_ue_sync_start_agc(srslte_ue_sync_t *q,
double (set_gain_callback)(void*, double),
float init_gain_value);
@ -173,6 +181,9 @@ SRSLTE_API int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q,
SRSLTE_API int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q,
cf_t *input_buffer[SRSLTE_MAX_PORTS]);
SRSLTE_API void srslte_ue_sync_set_cfo_tol(srslte_ue_sync_t *q,
float tol);
SRSLTE_API void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q,
float cfo);

View File

@ -75,7 +75,8 @@ typedef struct SRSLTE_API {
bool normalize_en;
bool cfo_en;
float current_cfo_tol;
float current_cfo;
srslte_pucch_format_t last_pucch_format;
@ -106,15 +107,21 @@ typedef struct SRSLTE_API {
/* This function shall be called just after the initial synchronization */
SRSLTE_API int srslte_ue_ul_init(srslte_ue_ul_t *q,
srslte_cell_t cell);
SRSLTE_API int srslte_ue_ul_init(srslte_ue_ul_t *q,
uint32_t max_prb);
SRSLTE_API void srslte_ue_ul_free(srslte_ue_ul_t *q);
SRSLTE_API void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q,
SRSLTE_API int srslte_ue_ul_set_cell(srslte_ue_ul_t *q,
srslte_cell_t cell);
SRSLTE_API void srslte_ue_ul_set_cfo_tol(srslte_ue_ul_t *q,
float tol);
SRSLTE_API void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q,
float cur_cfo);
SRSLTE_API void srslte_ue_ul_set_cfo_enable(srslte_ue_ul_t *q,
SRSLTE_API void srslte_ue_ul_set_cfo_enable(srslte_ue_ul_t *q,
bool enabled);
SRSLTE_API void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -99,10 +99,39 @@ inline uint32_t srslte_refsignal_cs_nsymbol(uint32_t l, srslte_cp_t cp, uint32_t
}
/** Allocates and precomputes the Cell-Specific Reference (CSR) signal for
/** Allocates memory for the 20 slots in a subframe
*/
int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL)
{
ret = SRSLTE_ERROR;
for (int p=0;p<2;p++) {
for (int i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
q->pilots[p][i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(max_prb, 2*p));
if (!q->pilots[p][i]) {
perror("malloc");
goto free_and_exit;
}
}
}
ret = SRSLTE_SUCCESS;
}
free_and_exit:
if (ret == SRSLTE_ERROR) {
srslte_refsignal_cs_free(q);
}
return ret;
}
/** Allocates and precomputes the Cell-Specific Reference (CSR) signal for
* the 20 slots in a subframe
*/
int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell)
int srslte_refsignal_cs_set_cell(srslte_refsignal_cs_t * q, srslte_cell_t cell)
{
uint32_t c_init;
@ -112,76 +141,57 @@ int srslte_refsignal_cs_init(srslte_refsignal_cs_t * q, srslte_cell_t cell)
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
srslte_cell_isvalid(&cell))
{
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_refsignal_cs_t));
bzero(&seq, sizeof(srslte_sequence_t));
if (srslte_sequence_init(&seq, 2 * 2 * SRSLTE_MAX_PRB)) {
goto free_and_exit;
}
if (SRSLTE_CP_ISNORM(cell.cp)) {
N_cp = 1;
} else {
N_cp = 0;
}
q->cell = cell;
for (p=0;p<2;p++) {
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
q->pilots[p][i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, 2*p));
if (!q->pilots[p][i]) {
perror("malloc");
goto free_and_exit;
}
}
}
for (ns=0;ns<SRSLTE_NSLOTS_X_FRAME;ns++) {
for (p=0;p<2;p++) {
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(2*p)/2;
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;
/* 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);
}
}
if (cell.id != q->cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
bzero(&seq, sizeof(srslte_sequence_t));
if (srslte_sequence_init(&seq, 2*2*SRSLTE_MAX_PRB)) {
return SRSLTE_ERROR;
}
if (SRSLTE_CP_ISNORM(cell.cp)) {
N_cp = 1;
} else {
N_cp = 0;
}
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;
/* generate sequence for this symbol and slot */
srslte_sequence_set_LTE_pr(&seq, 2*2*SRSLTE_MAX_PRB, c_init);
/* Compute signal */
for (i = 0; i < 2*q->cell.nof_prb; i++) {
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;
}
free_and_exit:
if (ret == SRSLTE_ERROR) {
srslte_sequence_free(&seq);
srslte_refsignal_cs_free(q);
}
return ret;
}
/** Deallocates a srslte_refsignal_cs_t object allocated with srslte_refsignal_cs_init */
void srslte_refsignal_cs_free(srslte_refsignal_cs_t * q)
{
int i, p;
for (p=0;p<2;p++) {
for (i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
for (int p=0;p<2;p++) {
for (int i=0;i<SRSLTE_NSUBFRAMES_X_FRAME;i++) {
if (q->pilots[p][i]) {
free(q->pilots[p][i]);
}

View File

@ -29,6 +29,7 @@
#include <strings.h>
#include <stdlib.h>
#include <complex.h>
#include <srslte/phy/common/phy_common.h>
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/ch_estimation/refsignal_ul.h"
@ -138,8 +139,8 @@ static int generate_n_prs(srslte_refsignal_ul_t * q) {
}
q->n_prs_pusch[delta_ss][ns] = n_prs;
}
srslte_sequence_free(&seq);
}
srslte_sequence_free(&seq);
return SRSLTE_SUCCESS;
}
@ -160,9 +161,9 @@ static int generate_srslte_sequence_hopping_v(srslte_refsignal_ul_t *q) {
return SRSLTE_ERROR;
}
q->v_pusch[ns][delta_ss] = seq.c[ns];
srslte_sequence_free(&seq);
}
}
srslte_sequence_free(&seq);
return SRSLTE_SUCCESS;
}
@ -170,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
*
*/
int srslte_refsignal_ul_init(srslte_refsignal_ul_t * q, srslte_cell_t cell)
int srslte_refsignal_ul_init(srslte_refsignal_ul_t * q, uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell)) {
if (q != NULL) {
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_refsignal_ul_t));
q->cell = cell;
// Allocate temporal buffer for computing signal argument
q->tmp_arg = srslte_vec_malloc(SRSLTE_NRE * q->cell.nof_prb * sizeof(cf_t));
q->tmp_arg = srslte_vec_malloc(SRSLTE_NRE * max_prb * sizeof(cf_t));
if (!q->tmp_arg) {
perror("malloc");
goto free_and_exit;
}
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;
}
free_and_exit:
@ -226,6 +205,45 @@ void srslte_refsignal_ul_free(srslte_refsignal_ul_t * q) {
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,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pucch_cfg_t *pucch_cfg,
@ -363,15 +381,38 @@ void compute_r(srslte_refsignal_ul_t *q, uint32_t nof_prb, uint32_t ns, uint32_t
}
int srslte_refsignal_dmrs_pusch_pregen_init(srslte_refsignal_ul_t *q, srslte_refsignal_ul_dmrs_pregen_t *pregen,
uint32_t max_prb)
{
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
for (uint32_t cs=0;cs<SRSLTE_NOF_CSHIFT;cs++) {
pregen->r[cs][sf_idx] = (cf_t**) calloc(sizeof(cf_t*), max_prb + 1);
if (pregen->r[cs][sf_idx]) {
for (uint32_t n=0;n<=max_prb;n++) {
if (srslte_dft_precoding_valid_prb(n)) {
pregen->r[cs][sf_idx][n] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*n*2*SRSLTE_NRE);
if (pregen->r[cs][sf_idx][n]) {
} else {
return SRSLTE_ERROR;
}
}
}
} else {
return SRSLTE_ERROR;
}
}
}
return SRSLTE_SUCCESS;
}
int srslte_refsignal_dmrs_pusch_pregen(srslte_refsignal_ul_t *q, srslte_refsignal_ul_dmrs_pregen_t *pregen)
{
for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) {
for (uint32_t cs=0;cs<SRSLTE_NOF_CSHIFT;cs++) {
pregen->r[cs][sf_idx] = (cf_t**) calloc(sizeof(cf_t*), q->cell.nof_prb + 1);
if (pregen->r[cs][sf_idx]) {
for (uint32_t n=0;n<=q->cell.nof_prb;n++) {
if (srslte_dft_precoding_valid_prb(n)) {
pregen->r[cs][sf_idx][n] = (cf_t*) srslte_vec_malloc(sizeof(cf_t)*n*2*SRSLTE_NRE);
if (pregen->r[cs][sf_idx][n]) {
if (srslte_refsignal_dmrs_pusch_gen(q, n, sf_idx, cs, pregen->r[cs][sf_idx][n])) {
return SRSLTE_ERROR;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -40,37 +40,42 @@
#include "srslte/phy/dft/dft_precoding.h"
/* Create DFT plans for transform precoding */
int srslte_dft_precoding_init(srslte_dft_precoding_t *q, uint32_t max_prb)
int srslte_dft_precoding_init(srslte_dft_precoding_t *q, uint32_t max_prb, bool is_tx)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
int ret = SRSLTE_ERROR_INVALID_INPUTS;
bzero(q, sizeof(srslte_dft_precoding_t));
if (max_prb <= SRSLTE_MAX_PRB) {
ret = SRSLTE_ERROR;
ret = SRSLTE_ERROR;
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);
if (srslte_dft_plan_c(&q->dft_plan[i], i*SRSLTE_NRE, SRSLTE_DFT_FORWARD)) {
if (srslte_dft_plan_c(&q->dft_plan[i], i*SRSLTE_NRE, is_tx?SRSLTE_DFT_FORWARD:SRSLTE_DFT_BACKWARD)) {
fprintf(stderr, "Error: Creating DFT plan %d\n",i);
goto clean_exit;
}
srslte_dft_plan_set_norm(&q->dft_plan[i], true);
if (srslte_dft_plan_c(&q->idft_plan[i], i*SRSLTE_NRE, SRSLTE_DFT_BACKWARD)) {
fprintf(stderr, "Error: Creating DFT plan %d\n",i);
goto clean_exit;
}
srslte_dft_plan_set_norm(&q->idft_plan[i], true);
}
}
q->max_prb = max_prb;
ret = SRSLTE_SUCCESS;
}
}
clean_exit:
clean_exit:
if (ret == SRSLTE_ERROR) {
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 */
@ -79,7 +84,6 @@ void srslte_dft_precoding_free(srslte_dft_precoding_t *q)
for (uint32_t i=1;i<=q->max_prb;i++) {
if(srslte_dft_precoding_valid_prb(i)) {
srslte_dft_plan_free(&q->dft_plan[i]);
srslte_dft_plan_free(&q->idft_plan[i]);
}
}
bzero(q, sizeof(srslte_dft_precoding_t));
@ -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,
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) {
@ -112,19 +116,3 @@ int srslte_dft_precoding(srslte_dft_precoding_t *q, cf_t *input, cf_t *output,
return SRSLTE_SUCCESS;
}
int srslte_dft_predecoding(srslte_dft_precoding_t *q, cf_t *input, cf_t *output,
uint32_t nof_prb, uint32_t nof_symbols)
{
if (!srslte_dft_precoding_valid_prb(nof_prb) && nof_prb <= q->max_prb) {
fprintf(stderr, "Error invalid number of PRB (%d)\n", nof_prb);
return SRSLTE_ERROR;
}
for (uint32_t i=0;i<nof_symbols;i++) {
srslte_dft_run_c(&q->idft_plan[nof_prb], &input[i*SRSLTE_NRE*nof_prb], &output[i*SRSLTE_NRE*nof_prb]);
}
return SRSLTE_SUCCESS;
}

View File

@ -29,6 +29,7 @@
#include <stdlib.h>
#include <complex.h>
#include <math.h>
#include <srslte/srslte.h>
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/dft/dft.h"
@ -48,6 +49,12 @@ int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_p
return -1;
}
q->shift_buffer = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN(symbol_sz));
if (!q->shift_buffer) {
perror("malloc");
return -1;
}
srslte_dft_plan_set_mirror(&q->fft_plan, true);
srslte_dft_plan_set_dc(&q->fft_plan, true);
@ -55,7 +62,6 @@ int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_p
q->nof_symbols = SRSLTE_CP_NSYMB(cp);
q->cp = cp;
q->freq_shift = false;
q->shift_buffer = NULL;
q->nof_re = nof_prb * SRSLTE_NRE;
q->nof_guards = ((symbol_sz - q->nof_re) / 2);
q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz);
@ -67,6 +73,32 @@ int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_p
return SRSLTE_SUCCESS;
}
int srslte_ofdm_replan_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_prb) {
if (srslte_dft_replan_c(&q->fft_plan, symbol_sz)) {
fprintf(stderr, "Error: Creating DFT plan\n");
return -1;
}
q->symbol_sz = (uint32_t) symbol_sz;
q->nof_symbols = SRSLTE_CP_NSYMB(cp);
q->cp = cp;
q->nof_re = nof_prb * SRSLTE_NRE;
q->nof_guards = ((symbol_sz - q->nof_re) / 2);
q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz);
if (q->freq_shift) {
srslte_ofdm_set_freq_shift(q, q->freq_shift_f);
}
DEBUG("Replan symbol_sz=%d, nof_symbols=%d, cp=%s, nof_re=%d, nof_guards=%d\n",
q->symbol_sz, q->nof_symbols,
q->cp==SRSLTE_CP_NORM?"Normal":"Extended", q->nof_re, q->nof_guards);
return SRSLTE_SUCCESS;
}
void srslte_ofdm_free_(srslte_ofdm_t *q) {
srslte_dft_plan_free(&q->fft_plan);
if (q->tmp) {
@ -78,30 +110,28 @@ void srslte_ofdm_free_(srslte_ofdm_t *q) {
bzero(q, sizeof(srslte_ofdm_t));
}
int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
int symbol_sz = srslte_symbol_sz(nof_prb);
int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) {
int symbol_sz = srslte_symbol_sz(max_prb);
if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb);
fprintf(stderr, "Error: Invalid nof_prb=%d\n", max_prb);
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;
int ret;
int symbol_sz = srslte_symbol_sz(nof_prb);
int symbol_sz = srslte_symbol_sz(max_prb);
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;
}
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) {
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;
}
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.
* Freq_shift is relative to inter-carrier spacing.
* Caution: This function shall not be called during run-time
*/
int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q, float freq_shift) {
q->shift_buffer = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN(q->symbol_sz));
if (!q->shift_buffer) {
perror("malloc");
return -1;
}
cf_t *ptr = q->shift_buffer;
for (uint32_t n=0;n<2;n++) {
for (uint32_t i=0;i<q->nof_symbols;i++) {
@ -140,7 +211,7 @@ int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q, float freq_shift) {
srslte_dft_plan_set_dc(&q->fft_plan, false);
q->freq_shift = true;
q->freq_shift_f = freq_shift;
return SRSLTE_SUCCESS;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -27,25 +27,22 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <math.h>
#include <srslte/phy/phch/pdsch_cfg.h>
#include <srslte/phy/common/sequence.h>
#include <srslte/phy/phch/pdsch.h>
#include "prb_dl.h"
#include "srslte/phy/phch/pdsch.h"
#include "srslte/phy/phch/sch.h"
#include "srslte/phy/common/phy_common.h"
#include "srslte/phy/utils/bit.h"
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/utils/vector.h"
#include "srslte/phy/utils/bit.h"
#define MAX_PDSCH_RE(cp) (2 * SRSLTE_CP_NSYMB(cp) * 12)
const static srslte_mod_t modulations[4] =
{ SRSLTE_MOD_BPSK, SRSLTE_MOD_QPSK, SRSLTE_MOD_16QAM, SRSLTE_MOD_64QAM };
@ -197,30 +194,24 @@ int srslte_pdsch_get(srslte_pdsch_t *q, cf_t *sf_symbols, cf_t *symbols,
return srslte_pdsch_cp(q, sf_symbols, symbols, grant, lstart, subframe, false);
}
/** Initializes the PDCCH transmitter or receiver */
int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antennas, bool is_receiver)
/** Initializes the PDSCH transmitter and receiver */
static int pdsch_init(srslte_pdsch_t *q, uint32_t max_prb, bool is_ue, uint32_t nof_antennas)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
int i;
if (q != NULL &&
srslte_cell_isvalid(&cell) &&
nof_antennas <= SRSLTE_MAX_PORTS)
{
if (q != NULL)
{
bzero(q, sizeof(srslte_pdsch_t));
ret = SRSLTE_ERROR;
q->cell = cell;
q->max_re = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp);
if (is_receiver) {
q->nof_rx_antennas = nof_antennas;
}
q->max_re = max_prb * MAX_PDSCH_RE(q->cell.cp);
q->is_ue = is_ue;
q->nof_rx_antennas = nof_antennas;
INFO("Init PDSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports,
q->cell.nof_prb, q->max_re);
INFO("Init PDSCH: %d PRBs, max_symbols: %d\n", max_prb, q->max_re);
for (i = 0; i < 4; i++) {
for (int i = 0; i < 4; i++) {
if (srslte_modem_table_lte(&q->mod[i], modulations[i])) {
goto clean;
}
@ -232,7 +223,7 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antenn
goto clean;
}
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
// Allocate int16_t for reception (LLRs)
q->e[i] = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM));
if (!q->e[i]) {
@ -245,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 (i = 0; i < q->cell.nof_ports; i++) {
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
q->x[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->x[i]) {
goto clean;
}
}
/* If it is the receiver side, allocate estimated channel */
if (is_receiver) {
for (i = 0; i < q->cell.nof_ports; i++) {
for (int j = 0; j < q->nof_rx_antennas; j++) {
q->symbols[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->symbols[i]) {
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_re);
if (!q->ce[i][j]) {
goto clean;
@ -264,42 +254,40 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antenn
}
}
}
for (int j=0;j<SRSLTE_MAX(q->nof_rx_antennas, q->cell.nof_ports);j++) {
q->symbols[j] = srslte_vec_malloc(sizeof(cf_t) * q->max_re);
if (!q->symbols[j]) {
goto clean;
}
}
/* Allocate User memory (all zeros) */
q->users = calloc(sizeof(srslte_pdsch_user_t*), 1+SRSLTE_SIRNTI);
q->users = calloc(sizeof(srslte_pdsch_user_t*), q->is_ue?1:(1+SRSLTE_SIRNTI));
if (!q->users) {
perror("malloc");
goto clean;
}
}
ret = SRSLTE_SUCCESS;
if (srslte_sequence_init(&q->tmp_seq, q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
goto clean;
}
clean:
ret = SRSLTE_SUCCESS;
}
clean:
if (ret == SRSLTE_ERROR) {
srslte_pdsch_free(q);
}
return ret;
}
int srslte_pdsch_init_tx(srslte_pdsch_t *q, srslte_cell_t cell) {
return srslte_pdsch_init(q, cell, 0, false);
int srslte_pdsch_init_ue(srslte_pdsch_t *q, uint32_t max_prb, uint32_t nof_antennas)
{
return pdsch_init(q, max_prb, true, nof_antennas);
}
int srslte_pdsch_init_rx(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_antennas) {
return srslte_pdsch_init(q, cell, nof_antennas, true);
int srslte_pdsch_init_enb(srslte_pdsch_t *q, uint32_t max_prb)
{
return pdsch_init(q, max_prb, false, 0);
}
void srslte_pdsch_free(srslte_pdsch_t *q) {
int i;
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (q->e[i]) {
free(q->e[i]);
@ -313,69 +301,107 @@ void srslte_pdsch_free(srslte_pdsch_t *q) {
/* Free sch objects */
srslte_sch_free(&q->dl_sch);
for (i = 0; i < q->cell.nof_ports; i++) {
for (int i = 0; i < SRSLTE_MAX_PORTS; i++) {
if (q->x[i]) {
free(q->x[i]);
}
for (int j=0;j<q->nof_rx_antennas;j++) {
if (q->ce[i][j]) {
free(q->ce[i][j]);
if (q->symbols[i]) {
free(q->symbols[i]);
}
if (q->is_ue) {
for (int j=0;j<q->nof_rx_antennas;j++) {
if (q->ce[i][j]) {
free(q->ce[i][j]);
}
}
}
}
for (int j=0;j<SRSLTE_MAX_PORTS;j++) {
if (q->symbols[j]) {
free(q->symbols[j]);
}
}
if (q->users) {
for (uint16_t u=0;u<SRSLTE_SIRNTI;u++) {
if (q->users[u]) {
srslte_pdsch_free_rnti(q, u);
if (q->is_ue) {
srslte_pdsch_free_rnti(q, 0);
} else {
for (int u=0;u<=SRSLTE_SIRNTI;u++) {
if (q->users[u]) {
srslte_pdsch_free_rnti(q, u);
}
}
}
}
free(q->users);
}
for (i = 0; i < 4; i++) {
srslte_sequence_free(&q->tmp_seq);
for (int i = 0; i < 4; i++) {
srslte_modem_table_free(&q->mod[i]);
}
bzero(q, sizeof(srslte_pdsch_t));
}
/* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while
int srslte_pdsch_set_cell(srslte_pdsch_t *q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
q->max_re = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp);
INFO("PDSCH: Cell config PCI=%d, %d ports, %d PRBs, max_symbols: %d\n", q->cell.nof_ports,
q->cell.id, q->cell.nof_prb, q->max_re);
ret = SRSLTE_SUCCESS;
}
return ret;
}
/* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while
* to execute, so shall be called once the final C-RNTI has been allocated for the session.
*/
int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) {
uint32_t i, j;
if (!q->users[rnti]) {
q->users[rnti] = calloc(1, sizeof(srslte_pdsch_user_t));
if (q->users[rnti]) {
for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
for (j = 0; j < SRSLTE_MAX_CODEWORDS; j++) {
if (srslte_sequence_pdsch(&q->users[rnti]->seq[j][i], rnti, j, 2 * i, q->cell.id,
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) {
ERROR("Generating scrambling sequence");
return SRSLTE_ERROR;
}
uint32_t rnti_idx = q->is_ue?0:rnti;
if (!q->users[rnti_idx] || q->is_ue) {
if (!q->users[rnti_idx]) {
q->users[rnti_idx] = calloc(1, sizeof(srslte_pdsch_user_t));
if(!q->users[rnti_idx]) {
perror("calloc");
return -1;
}
}
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
for (int j = 0; j < SRSLTE_MAX_CODEWORDS; j++) {
if (srslte_sequence_pdsch(&q->users[rnti_idx]->seq[j][i], rnti, j, 2 * i, q->cell.id,
q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM)))
{
fprintf(stderr, "Error initializing PDSCH scrambling sequence\n");
srslte_pdsch_free_rnti(q, rnti);
return SRSLTE_ERROR;
}
}
q->users[rnti]->sequence_generated = true;
}
q->ue_rnti = rnti;
q->users[rnti_idx]->cell_id = q->cell.id;
q->users[rnti_idx]->sequence_generated = true;
} else {
fprintf(stderr, "Error generating PDSCH sequence: rnti=0x%x already generated\n", rnti);
}
return SRSLTE_SUCCESS;
}
void srslte_pdsch_free_rnti(srslte_pdsch_t* q, uint16_t rnti)
{
if (q->users[rnti]) {
uint32_t rnti_idx = q->is_ue?0:rnti;
if (q->users[rnti_idx]) {
for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) {
for (int j = 0; j < SRSLTE_MAX_CODEWORDS; j++) {
srslte_sequence_free(&q->users[rnti]->seq[j][i]);
srslte_sequence_free(&q->users[rnti_idx]->seq[j][i]);
}
}
free(q->users[rnti]);
q->users[rnti] = NULL;
free(q->users[rnti_idx]);
q->users[rnti_idx] = NULL;
q->ue_rnti = 0;
}
}
@ -390,7 +416,7 @@ static void pdsch_decode_debug(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg,
break;
}
DEBUG("SAVED FILE %s: received subframe symbols\n", filename);
srslte_vec_save_file(filename, sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
srslte_vec_save_file(filename, sf_symbols[j], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
for (int i = 0; i < q->cell.nof_ports; i++) {
if (snprintf(filename, FILENAME_MAX, "hest_%d%d.dat", i, j) < 0) {
@ -401,11 +427,21 @@ static void pdsch_decode_debug(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg,
srslte_vec_save_file(filename, ce[i][j], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
}
}
DEBUG("SAVED FILE pdsch_symbols.dat: symbols after equalization\n",0);
srslte_vec_save_file("pdsch_symbols.dat", q->d, cfg->nbits[0].nof_re*sizeof(cf_t));
for (int i=0;i<cfg->nof_layers;i++) {
if (snprintf(filename, FILENAME_MAX, "pdsch_symbols_%d.dat", i) < 0) {
ERROR("Generating file name");
break;
}
DEBUG("SAVED FILE %s: symbols after equalization\n", filename);
srslte_vec_save_file(filename, q->d[i], cfg->nbits[0].nof_re*sizeof(cf_t));
DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n",0);
srslte_vec_save_file("llr.dat", q->e, cfg->nbits[0].nof_bits*sizeof(int16_t));
if (snprintf(filename, FILENAME_MAX, "llr_%d.dat", i) < 0) {
ERROR("Generating file name");
break;
}
DEBUG("SAVED FILE %s: LLR estimates after demodulation and descrambling\n", filename);
srslte_vec_save_file(filename, q->e[i], cfg->nbits[0].nof_bits*sizeof(int16_t));
}
}
}
@ -427,15 +463,17 @@ int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_g
int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, uint32_t cfi,
uint32_t sf_idx, int rvidx[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type,
uint32_t pmi) {
if (cfg) {
if (grant) {
memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t));
}
if (cfg && grant) {
uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant);
memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t));
for (int i = 0; i < grant->nof_tb; i++) {
if (srslte_cbsegm(&cfg->cb_segm[i], (uint32_t) cfg->grant.mcs[i].tbs)) {
fprintf(stderr, "Error computing Codeblock (1) segmentation for TBS=%d\n", cfg->grant.mcs[i].tbs);
return SRSLTE_ERROR;
for (int cw = 0; cw < SRSLTE_MAX_CODEWORDS; cw++) {
if (grant->tb_en[cw]) {
if (srslte_cbsegm(&cfg->cb_segm[cw], (uint32_t) cfg->grant.mcs[cw].tbs)) {
fprintf(stderr, "Error computing Codeblock (1) segmentation for TBS=%d\n", cfg->grant.mcs[cw].tbs);
return SRSLTE_ERROR;
}
}
}
srslte_ra_dl_grant_to_nbits(&cfg->grant, cfi, cell, sf_idx, cfg->nbits);
@ -447,33 +485,36 @@ int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra
/* Check and configure PDSCH transmission modes */
switch(mimo_type) {
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
if (grant->nof_tb != 1) {
ERROR("Number of transport blocks is not supported for single transmission mode.");
if (nof_tb != 1) {
ERROR("Wrong number of transport blocks (%d) for single antenna.", nof_tb);
return SRSLTE_ERROR;
}
cfg->nof_layers = 1;
break;
case SRSLTE_MIMO_TYPE_TX_DIVERSITY:
if (grant->nof_tb != 1) {
ERROR("Number of transport blocks is not supported for transmit diversity mode.");
if (nof_tb != 1) {
ERROR("Wrong number of transport blocks (%d) for transmit diversity.", nof_tb);
return SRSLTE_ERROR;
}
cfg->nof_layers = 2;
break;
case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX:
if (grant->nof_tb == 1) {
if (nof_tb == 1) {
cfg->codebook_idx = pmi;
cfg->nof_layers = 1;
} else {
} else if (nof_tb == 2) {
cfg->codebook_idx = pmi + 1;
cfg->nof_layers = 2;
} else {
ERROR("Wrong number of transport blocks (%d) for spatial multiplexing.", nof_tb);
return SRSLTE_ERROR;
}
INFO("PDSCH configured for Spatial Multiplex; nof_codewords=%d; nof_layers=%d; codebook_idx=%d;\n",
grant->nof_tb, cfg->nof_layers, cfg->codebook_idx);
nof_tb, cfg->nof_layers, cfg->codebook_idx);
break;
case SRSLTE_MIMO_TYPE_CDD:
if (grant->nof_tb != 2) {
ERROR("Number of transport blocks (%d) is not supported for CDD transmission mode.", grant->nof_tb);
if (nof_tb != 2) {
ERROR("Wrong number of transport blocks (%d) for CDD.", nof_tb);
return SRSLTE_ERROR;
}
cfg->nof_layers = 2;
@ -486,7 +527,25 @@ int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra
}
}
static int srslte_pdsch_codeword_encode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_t *cfg,
static srslte_sequence_t *get_user_sequence(srslte_pdsch_t *q, uint16_t rnti,
uint32_t codeword_idx, uint32_t sf_idx, uint32_t len)
{
uint32_t rnti_idx = q->is_ue?0:rnti;
// The scrambling sequence is pregenerated for all RNTIs in the eNodeB but only for C-RNTI in the UE
if (q->users[rnti_idx] && q->users[rnti_idx]->sequence_generated &&
q->users[rnti_idx]->cell_id == q->cell.id &&
q->ue_rnti == rnti &&
((rnti >= SRSLTE_CRNTI_START && rnti < SRSLTE_CRNTI_END) || !q->is_ue))
{
return &q->users[rnti_idx]->seq[codeword_idx][sf_idx];
} else {
srslte_sequence_pdsch(&q->tmp_seq, rnti, codeword_idx, 2 * sf_idx, q->cell.id, len);
return &q->tmp_seq;
}
}
static int srslte_pdsch_codeword_encode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_tx_t *softbuffer, uint16_t rnti, uint8_t *data,
uint32_t codeword_idx) {
srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx];
@ -499,45 +558,36 @@ static int srslte_pdsch_codeword_encode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_
nbits->nof_re, nbits->nof_bits, rv);
/* Channel coding */
if (srslte_dlsch_encode2(&pdsch->dl_sch, cfg, softbuffer, data, pdsch->e[codeword_idx], codeword_idx)) {
if (srslte_dlsch_encode2(&q->dl_sch, cfg, softbuffer, data, q->e[codeword_idx], codeword_idx)) {
ERROR("Error encoding TB %d", codeword_idx);
return SRSLTE_ERROR;
}
/* Select scrambling sequence */
srslte_sequence_t *seq = get_user_sequence(q, rnti, codeword_idx, cfg->sf_idx, nbits->nof_bits);
/* Bit scrambling */
if (!pdsch->users[rnti]) {
srslte_sequence_t seq;
if (srslte_sequence_pdsch(&seq, rnti, codeword_idx, 2 * cfg->sf_idx, pdsch->cell.id, nbits->nof_bits)) {
ERROR("Initialising scrambling sequence");
return SRSLTE_ERROR;
}
srslte_scrambling_bytes(&seq, (uint8_t *) pdsch->e[codeword_idx], nbits->nof_bits);
srslte_sequence_free(&seq);
} else {
srslte_scrambling_bytes(&pdsch->users[rnti]->seq[codeword_idx][cfg->sf_idx],
(uint8_t *) pdsch->e[codeword_idx],
nbits->nof_bits);
}
srslte_scrambling_bytes(seq, (uint8_t *) q->e[codeword_idx], nbits->nof_bits);
/* Bit mapping */
srslte_mod_modulate_bytes(&pdsch->mod[mcs->mod],
(uint8_t *) pdsch->e[codeword_idx],
pdsch->d[codeword_idx], nbits->nof_bits);
srslte_mod_modulate_bytes(&q->mod[mcs->mod],
(uint8_t *) q->e[codeword_idx],
q->d[codeword_idx], nbits->nof_bits);
}
return SRSLTE_SUCCESS;
}
static int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_t *cfg,
static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg,
srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data,
uint32_t codeword_idx) {
uint32_t codeword_idx, bool *ack) {
srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx];
srslte_ra_mcs_t *mcs = &cfg->grant.mcs[codeword_idx];
uint32_t rv = cfg->rv[codeword_idx];
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (nbits->nof_bits) {
if (softbuffer && data && ack) {
INFO("Decoding PDSCH SF: %d (TB %d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n",
cfg->sf_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs,
nbits->nof_re, nbits->nof_bits, rv);
@ -546,25 +596,27 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
* thus we don't need tot set it in the LLRs normalization
*/
srslte_demod_soft_demodulate_s(mcs->mod, pdsch->d[codeword_idx], pdsch->e[codeword_idx], nbits->nof_re);
srslte_demod_soft_demodulate_s(mcs->mod, q->d[codeword_idx], q->e[codeword_idx], nbits->nof_re);
if (pdsch->users[rnti] && pdsch->users[rnti]->sequence_generated) {
srslte_scrambling_s_offset(&pdsch->users[rnti]->seq[codeword_idx][cfg->sf_idx], pdsch->e[codeword_idx],
0, nbits->nof_bits);
} else {
srslte_sequence_t seq;
if (srslte_sequence_pdsch(&seq, rnti, codeword_idx, 2 * cfg->sf_idx, pdsch->cell.id, nbits->nof_bits)) {
ERROR("Initialising scrambling sequence");
return SRSLTE_ERROR;
}
srslte_scrambling_s_offset(&seq, pdsch->e[codeword_idx], 0, nbits->nof_bits);
srslte_sequence_free(&seq);
/* Select scrambling sequence */
srslte_sequence_t *seq = get_user_sequence(q, rnti, codeword_idx, cfg->sf_idx, nbits->nof_bits);
/* Bit scrambling */
srslte_scrambling_s_offset(seq, q->e[codeword_idx], 0, nbits->nof_bits);
/* Return */
ret = srslte_dlsch_decode2(&q->dl_sch, cfg, softbuffer, q->e[codeword_idx], data, codeword_idx);
if (ret == SRSLTE_SUCCESS) {
*ack = true;
} else if (ret == SRSLTE_ERROR) {
*ack = false;
ret = SRSLTE_SUCCESS;
}
return srslte_dlsch_decode2(&pdsch->dl_sch, cfg, softbuffer, pdsch->e[codeword_idx], data, codeword_idx);
} else {
ERROR("Detected NULL pointer");
}
return SRSLTE_SUCCESS;
return ret;
}
/** Decodes the PDSCH from the received symbols
@ -585,9 +637,10 @@ int srslte_pdsch_decode(srslte_pdsch_t *q,
data != NULL &&
cfg != NULL)
{
uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant);
INFO("Decoding PDSCH SF: %d, RNTI: 0x%x, NofSymbols: %d, C_prb=%d, mimo_type=%d, nof_layers=%d, nof_tb=%d\n",
cfg->sf_idx, rnti, cfg->nbits[0].nof_re, cfg->grant.nof_prb, cfg->nof_layers, cfg->grant.nof_tb);
cfg->sf_idx, rnti, cfg->nbits[0].nof_re, cfg->grant.nof_prb, cfg->nof_layers, nof_tb);
// Extract Symbols and Channel Estimates
for (int j=0;j<q->nof_rx_antennas;j++) {
@ -608,10 +661,10 @@ int srslte_pdsch_decode(srslte_pdsch_t *q,
// Prepare layers
int nof_symbols [SRSLTE_MAX_CODEWORDS];
nof_symbols[0] = cfg->nbits[0].nof_re * cfg->grant.nof_tb / cfg->nof_layers;
nof_symbols[1] = cfg->nbits[1].nof_re * cfg->grant.nof_tb / cfg->nof_layers;
nof_symbols[0] = cfg->nbits[0].nof_re * nof_tb / cfg->nof_layers;
nof_symbols[1] = cfg->nbits[1].nof_re * nof_tb / cfg->nof_layers;
if (cfg->nof_layers == cfg->grant.nof_tb) {
if (cfg->nof_layers == nof_tb) {
/* Skip layer demap */
for (i = 0; i < cfg->nof_layers; i++) {
x[i] = q->d[i];
@ -629,21 +682,26 @@ int srslte_pdsch_decode(srslte_pdsch_t *q,
cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, noise_estimate);
// Layer demapping only if necessary
if (cfg->nof_layers != cfg->grant.nof_tb) {
srslte_layerdemap_type(x, q->d, cfg->nof_layers, cfg->grant.nof_tb,
if (cfg->nof_layers != nof_tb) {
srslte_layerdemap_type(x, q->d, cfg->nof_layers, nof_tb,
nof_symbols[0], nof_symbols, cfg->mimo_type);
}
// Codeword decoding
for (uint32_t tb = 0; tb < cfg->grant.nof_tb; tb ++) {
int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb], rnti, data[tb], tb);
acks[tb] = (ret == SRSLTE_SUCCESS);
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb ++) {
if (cfg->grant.tb_en[tb]) {
int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb], rnti, data[tb], tb, &acks[tb]);
/* Check if there has been any execution error */
if (ret) {
return ret;
}
}
}
pdsch_decode_debug(q, cfg, sf_symbols, ce);
return SRSLTE_SUCCESS;
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
@ -689,6 +747,8 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
if (q != NULL &&
cfg != NULL) {
uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant);
for (i = 0; i < q->cell.nof_ports; i++) {
if (sf_symbols[i] == NULL) {
@ -708,15 +768,17 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
return SRSLTE_ERROR_INVALID_INPUTS;
}
for (uint32_t tb = 0; tb < cfg->grant.nof_tb; tb ++) {
ret |= srslte_pdsch_codeword_encode(q, cfg, softbuffers[tb], rnti, data[tb], tb);
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb ++) {
if (cfg->grant.tb_en[tb]) {
ret |= srslte_pdsch_codeword_encode(q, cfg, softbuffers[tb], rnti, data[tb], tb);
}
}
// Layer mapping & precode if necessary
if (q->cell.nof_ports > 1) {
int nof_symbols;
/* If number of layers is equal to transport blocks (codewords) skip layer mapping */
if (cfg->nof_layers == cfg->grant.nof_tb) {
if (cfg->nof_layers == nof_tb) {
for (i = 0; i < cfg->nof_layers; i++) {
x[i] = q->d[i];
}
@ -728,7 +790,7 @@ int srslte_pdsch_encode(srslte_pdsch_t *q,
}
memset(&x[cfg->nof_layers], 0, sizeof(cf_t *) * (SRSLTE_MAX_LAYERS - cfg->nof_layers));
nof_symbols = srslte_layermap_type(q->d, x, cfg->grant.nof_tb, cfg->nof_layers,
nof_symbols = srslte_layermap_type(q->d, x, nof_tb, cfg->nof_layers,
(int[SRSLTE_MAX_CODEWORDS]) {cfg->nbits[0].nof_re, cfg->nbits[1].nof_re},
cfg->mimo_type);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -521,11 +521,10 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr
grant->mcs[1].tbs = 0;
}
}
grant->nof_tb = 0;
for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
grant->tb_en[tb] = dci->tb_en[tb];
if (dci->tb_en[tb]) {
grant->Qm[tb] = srslte_mod_bits_x_symbol(grant->mcs[tb].mod);
grant->nof_tb++;
}
}
grant->pinfo = dci->pinfo;
@ -541,12 +540,14 @@ void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant, uint32_t cfi, srsl
srslte_ra_nbits_t nbits [SRSLTE_MAX_CODEWORDS])
{
// Compute number of RE
for (int i = 0; i < grant->nof_tb; i++) {
/* Compute number of RE for first transport block */
nbits[i].nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb < 10 ? (cfi + 1) : cfi);
nbits[i].lstart = cell.nof_prb < 10 ? (cfi + 1) : cfi;
nbits[i].nof_symb = 2 * SRSLTE_CP_NSYMB(cell.cp) - nbits[0].lstart;
nbits[i].nof_bits = nbits[i].nof_re * grant->Qm[i];
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (grant->tb_en[i]) {
/* Compute number of RE for first transport block */
nbits[i].nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb < 10 ? (cfi + 1) : cfi);
nbits[i].lstart = cell.nof_prb < 10 ? (cfi + 1) : cfi;
nbits[i].nof_symb = 2 * SRSLTE_CP_NSYMB(cell.cp) - nbits[0].lstart;
nbits[i].nof_bits = nbits[i].nof_re * grant->Qm[i];
}
}
}
@ -820,11 +821,13 @@ void srslte_ra_pdsch_fprint(FILE *f, srslte_ra_dl_dci_t *dci, uint32_t nof_prb)
void srslte_ra_dl_grant_fprint(FILE *f, srslte_ra_dl_grant_t *grant) {
srslte_ra_prb_fprint(f, grant);
fprintf(f, " - Number of PRBs:\t\t\t%d\n", grant->nof_prb);
fprintf(f, " - Number of TBs:\t\t\t%d\n", grant->nof_tb);
for (int i = 0; i < grant->nof_tb; i++) {
fprintf(f, " - Transport block:\t\t\t%d\n", i);
fprintf(f, " -> Modulation type:\t\t\t%s\n", srslte_mod_string(grant->mcs[i].mod));
fprintf(f, " -> Transport block size:\t\t%d\n", grant->mcs[i].tbs);
fprintf(f, " - Number of TBs:\t\t\t%d\n", SRSLTE_RA_DL_GRANT_NOF_TB(grant));
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (grant->tb_en[i]) {
fprintf(f, " - Transport block:\t\t\t%d\n", i);
fprintf(f, " -> Modulation type:\t\t\t%s\n", srslte_mod_string(grant->mcs[i].mod));
fprintf(f, " -> Transport block size:\t\t%d\n", grant->mcs[i].tbs);
}
}
}

View File

@ -524,7 +524,7 @@ int srslte_dlsch_decode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbu
int16_t *e_bits, uint8_t *data, int codeword_idx) {
uint32_t Nl = 1;
if (cfg->nof_layers != cfg->grant.nof_tb) {
if (cfg->nof_layers != SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)) {
Nl = 2;
}
@ -553,7 +553,7 @@ int srslte_dlsch_encode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbu
uint8_t *data, uint8_t *e_bits, int codeword_idx) {
uint32_t Nl = 1;
if (cfg->nof_layers != cfg->grant.nof_tb) {
if (cfg->nof_layers != SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)) {
Nl = 2;
}
@ -657,14 +657,17 @@ int srslte_ulsch_uci_decode_ri_ack(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srs
// Deinterleave and decode HARQ bits
if (uci_data->uci_ack_len > 0) {
uint8_t acks[2] = {0, 0};
float beta = beta_harq_offset[cfg->uci_cfg.I_offset_ack];
if (cfg->cb_segm.tbs == 0) {
beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
}
ret = srslte_uci_decode_ack(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, &uci_data->uci_ack);
ret = srslte_uci_decode_ack(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, acks, uci_data->uci_ack_len);
if (ret < 0) {
return ret;
}
uci_data->uci_ack = acks[0];
uci_data->uci_ack_2 = acks[1];
Q_prime_ack = (uint32_t) ret;
// Set zeros to HARQ bits
@ -805,11 +808,13 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
// Encode (and interleave) ACK
if (uci_data.uci_ack_len > 0) {
uint8_t acks [2] = {uci_data.uci_ack, uci_data.uci_ack_2};
float beta = beta_harq_offset[cfg->uci_cfg.I_offset_ack];
if (cfg->cb_segm.tbs == 0) {
beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
}
ret = srslte_uci_encode_ack(cfg, uci_data.uci_ack, uci_data.uci_cqi_len, beta, nb_q/Qm, &q->ack_ri_bits[Q_prime_ri*Qm]);
ret = srslte_uci_encode_ack(cfg, acks, uci_data.uci_ack_len, uci_data.uci_cqi_len,
beta, nb_q / Qm, &q->ack_ri_bits[Q_prime_ri * Qm]);
if (ret < 0) {
return ret;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -137,11 +137,15 @@ int base_init() {
exit(-1);
}
if (srslte_ue_dl_init(&ue_dl, cell, 1)) {
if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) {
fprintf(stderr, "Error initializing UE DL\n");
return -1;
}
if (srslte_ue_dl_set_cell(&ue_dl, cell)) {
fprintf(stderr, "Error initializing UE DL\n");
return -1;
}
srslte_ue_dl_set_rnti(&ue_dl, rnti);
DEBUG("Memory init OK\n",0);

View File

@ -153,7 +153,7 @@ int main(int argc, char **argv) {
int ret = -1;
struct timeval t[3];
srslte_softbuffer_tx_t *softbuffers_tx[SRSLTE_MAX_CODEWORDS];
int M=10;
int M=1;
bool acks[SRSLTE_MAX_CODEWORDS] = {false};
parse_args(argc,argv);
@ -213,8 +213,6 @@ int main(int argc, char **argv) {
return ret;
}
#ifdef DO_OFDM
srslte_ofdm_tx_init(&ofdm_tx, cell.cp, cell.nof_prb);
srslte_ofdm_rx_init(&ofdm_rx, cell.cp, cell.nof_prb);
@ -257,8 +255,8 @@ int main(int argc, char **argv) {
}
for (int i = 0; i < grant.nof_tb; i++) {
if (grant.mcs[i].tbs) {
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (grant.tb_en[i]) {
data_tx[i] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs[i].tbs);
if (!data_tx[i]) {
perror("srslte_vec_malloc");
@ -276,7 +274,11 @@ int main(int argc, char **argv) {
}
}
if (srslte_pdsch_init_rx(&pdsch_rx, cell, nof_rx_antennas)) {
if (srslte_pdsch_init_ue(&pdsch_rx, cell.nof_prb, nof_rx_antennas)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto quit;
}
if (srslte_pdsch_set_cell(&pdsch_rx, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto quit;
}
@ -303,12 +305,11 @@ int main(int argc, char **argv) {
INFO(" cp=%s\n", srslte_cp_string(cell.cp));
INFO(" phich_length=%d\n", (int) cell.phich_length);
INFO(" phich_resources=%d\n", (int) cell.phich_resources);
INFO(" nof_tb=%d\n", pdsch_cfg.grant.nof_tb);
INFO(" nof_prb=%d\n", pdsch_cfg.grant.nof_prb);
INFO(" sf_idx=%d\n", pdsch_cfg.sf_idx);
INFO(" mimo_type=%s\n", srslte_mimotype2str(pdsch_cfg.mimo_type));
INFO(" nof_layers=%d\n", pdsch_cfg.nof_layers);
INFO(" nof_tb=%d\n", pdsch_cfg.grant.nof_tb);
INFO(" nof_tb=%d\n", SRSLTE_RA_DL_GRANT_NOF_TB(&pdsch_cfg.grant));
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
INFO(" Tranport block index %d:\n", i);
INFO(" Qm=%d\n", pdsch_cfg.grant.Qm[i]);
@ -334,18 +335,26 @@ int main(int argc, char **argv) {
srslte_filesource_read(&fsrc, rx_slot_symbols[0], SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
#endif
srslte_chest_dl_t chest;
if (srslte_chest_dl_init(&chest, cell)) {
srslte_chest_dl_t chest;
if (srslte_chest_dl_init(&chest, cell.nof_prb)) {
fprintf(stderr, "Error initializing equalizer\n");
exit(-1);
}
if (srslte_chest_dl_set_cell(&chest, cell)) {
printf("Error initializing equalizer\n");
exit(-1);
}
srslte_chest_dl_estimate(&chest, rx_slot_symbols[0], ce[0], subframe);
srslte_chest_dl_free(&chest);
srslte_filesource_free(&fsrc);
} else {
if (srslte_pdsch_init_tx(&pdsch_tx, cell)) {
if (srslte_pdsch_init_enb(&pdsch_tx, cell.nof_prb)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto quit;
}
if (srslte_pdsch_set_cell(&pdsch_tx, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto quit;
}
@ -372,9 +381,11 @@ int main(int argc, char **argv) {
}
}
for (int tb = 0; tb < grant.nof_tb; tb++) {
for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) {
data_tx[tb][byte] = (uint8_t)(rand() % 256);
for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
if (grant.tb_en[tb]) {
for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) {
data_tx[tb][byte] = (uint8_t) (rand() % 256);
}
}
}
@ -444,8 +455,8 @@ int main(int argc, char **argv) {
srslte_ofdm_rx_sf(&ofdm_rx, tx_sf_symbols[i], rx_slot_symbols[i]);
}
#endif
for (i = 0; i < grant.nof_tb; i++) {
if (grant.mcs[i].tbs) {
for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (grant.tb_en[i]) {
srslte_softbuffer_rx_reset_tbs(softbuffers_rx[i], (uint32_t) grant.mcs[i].tbs);
}
}
@ -464,19 +475,23 @@ int main(int argc, char **argv) {
}
/* Check Tx and Rx bytes */
for (int tb = 0; tb < grant.nof_tb; tb++) {
for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) {
if (data_tx[tb][byte] != data_rx[tb][byte]) {
ERROR("Found BYTE error in TB %d (%02X != %02X), quiting...", tb, data_tx[tb][byte], data_rx[tb][byte]);
ret = SRSLTE_ERROR;
goto quit;
for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
if (grant.tb_en[tb]) {
for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) {
if (data_tx[tb][byte] != data_rx[tb][byte]) {
ERROR("Found BYTE error in TB %d (%02X != %02X), quiting...", tb, data_tx[tb][byte], data_rx[tb][byte]);
ret = SRSLTE_ERROR;
goto quit;
}
}
}
}
/* Check all transport blocks have been decoded OK */
for (int tb = 0; tb < grant.nof_tb; tb++) {
ret |= (acks[tb]) ? SRSLTE_SUCCESS : SRSLTE_ERROR;
for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
if (grant.tb_en[tb]) {
ret |= (acks[tb]) ? SRSLTE_SUCCESS : SRSLTE_ERROR;
}
}
ret = SRSLTE_SUCCESS;

View File

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

View File

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

View File

@ -85,12 +85,14 @@ int main(int argc, char **argv) {
cf_t preamble[MAX_LEN];
memset(preamble, 0, sizeof(cf_t)*MAX_LEN);
srslte_prach_init(p,
N_ifft_ul,
config_idx,
root_seq_idx,
high_speed_flag,
zero_corr_zone);
srslte_prach_init(p, N_ifft_ul);
srslte_prach_set_cell( p,
N_ifft_ul,
config_idx,
root_seq_idx,
high_speed_flag,
zero_corr_zone);
uint32_t seq_index = 0;
uint32_t frequency_offset = 0;

View File

@ -90,12 +90,14 @@ int main(int argc, char **argv) {
cf_t preamble_sum[MAX_LEN];
memset(preamble_sum, 0, sizeof(cf_t)*MAX_LEN);
srslte_prach_init(p,
N_ifft_ul,
preamble_format,
root_seq_idx,
high_speed_flag,
zero_corr_zone);
srslte_prach_init(p, N_ifft_ul);
srslte_prach_set_cell( p,
N_ifft_ul,
preamble_format,
root_seq_idx,
high_speed_flag,
zero_corr_zone);
uint32_t seq_index = 0;
uint32_t frequency_offset = 0;

View File

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

View File

@ -87,15 +87,23 @@ int main(int argc, char **argv) {
parse_args(argc,argv);
if (srslte_pucch_init(&pucch, cell)) {
if (srslte_pucch_init(&pucch)) {
fprintf(stderr, "Error creating PDSCH object\n");
exit(-1);
}
if (srslte_refsignal_ul_init(&dmrs, cell)) {
if (srslte_pucch_set_cell(&pucch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
exit(-1);
}
if (srslte_refsignal_ul_init(&dmrs, cell.nof_prb)) {
fprintf(stderr, "Error creating PDSCH object\n");
exit(-1);
}
if (srslte_refsignal_ul_set_cell(&dmrs, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
exit(-1);
}
bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t));
for (int i=0;i<SRSLTE_PUCCH_MAX_BITS;i++) {

View File

@ -110,7 +110,8 @@ void parse_args(int argc, char **argv) {
}
int main(int argc, char **argv) {
srslte_pusch_t pusch;
srslte_pusch_t pusch_tx;
srslte_pusch_t pusch_rx;
uint8_t *data = NULL;
cf_t *sf_symbols = NULL;
cf_t *ce = NULL;
@ -145,11 +146,23 @@ int main(int argc, char **argv) {
ul_hopping.hopping_offset = 0;
ul_hopping.hop_mode = SRSLTE_PUSCH_HOP_MODE_INTER_SF;
if (srslte_pusch_init(&pusch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
if (srslte_pusch_init_ue(&pusch_tx, cell.nof_prb)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto quit;
}
if (srslte_pusch_set_cell(&pusch_tx, cell)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto quit;
}
if (srslte_pusch_init_enb(&pusch_rx, cell.nof_prb)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto quit;
}
if (srslte_pusch_set_cell(&pusch_rx, cell)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto quit;
}
/* Configure PUSCH */
printf("Encoding rv_idx=%d\n",rv_idx);
@ -159,27 +172,33 @@ int main(int argc, char **argv) {
uci_cfg.I_offset_ri = 2;
uci_cfg.I_offset_ack = 4;
if (srslte_pusch_cfg(&pusch, &cfg, &grant, &uci_cfg, &ul_hopping, NULL, subframe, 0, 0)) {
if (srslte_pusch_cfg(&pusch_tx, &cfg, &grant, &uci_cfg, &ul_hopping, NULL, subframe, 0, 0)) {
fprintf(stderr, "Error configuring PDSCH\n");
exit(-1);
}
if (srslte_pusch_cfg(&pusch_rx, &cfg, &grant, &uci_cfg, &ul_hopping, NULL, subframe, 0, 0)) {
fprintf(stderr, "Error configuring PDSCH\n");
exit(-1);
}
uint16_t rnti = 1234;
srslte_pusch_set_rnti(&pusch, rnti);
srslte_pusch_set_rnti(&pusch_tx, rnti);
srslte_pusch_set_rnti(&pusch_rx, rnti);
srslte_uci_data_t uci_data_tx;
srslte_uci_data_t uci_data_rx;
bzero(&uci_data_tx, sizeof(srslte_uci_data_t));
uci_data_tx.uci_cqi_len = 4;
uci_data_tx.uci_ri_len = 0;
uci_data_tx.uci_ack_len = 0;
uci_data_tx.uci_ack_len = 2;
memcpy(&uci_data_rx, &uci_data_tx, sizeof(srslte_uci_data_t));
for (uint32_t i=0;i<20;i++) {
uci_data_tx.uci_cqi [i] = 1;
}
uci_data_tx.uci_ri = 1;
uci_data_tx.uci_ack = 1;
uci_data_tx.uci_ri = 1;
uci_data_tx.uci_ack = 1;
uci_data_tx.uci_ack_2 = 1;
uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp);
sf_symbols = srslte_vec_malloc(sizeof(cf_t) * nof_re);
@ -211,13 +230,13 @@ int main(int argc, char **argv) {
uint32_t ntrials = 100;
if (srslte_pusch_encode(&pusch, &cfg, &softbuffer_tx, data, uci_data_tx, rnti, sf_symbols)) {
if (srslte_pusch_encode(&pusch_tx, &cfg, &softbuffer_tx, data, uci_data_tx, rnti, sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
exit(-1);
}
if (rv_idx > 0) {
cfg.rv = rv_idx;
if (srslte_pusch_encode(&pusch, &cfg, &softbuffer_tx, data, uci_data_tx, rnti, sf_symbols)) {
if (srslte_pusch_encode(&pusch_tx, &cfg, &softbuffer_tx, data, uci_data_tx, rnti, sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
exit(-1);
}
@ -233,7 +252,7 @@ int main(int argc, char **argv) {
}
gettimeofday(&t[1], NULL);
int r = srslte_pusch_decode(&pusch, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, &uci_data_rx);
int r = srslte_pusch_decode(&pusch_rx, &cfg, &softbuffer_rx, sf_symbols, ce, 0, rnti, data, &uci_data_rx);
gettimeofday(&t[2], NULL);
get_time_interval(t);
if (r) {
@ -250,11 +269,19 @@ int main(int argc, char **argv) {
if (uci_data_tx.uci_ack_len) {
if (uci_data_tx.uci_ack != uci_data_rx.uci_ack) {
printf("UCI ACK bit error: %d != %d\n", uci_data_tx.uci_ack, uci_data_rx.uci_ack);
ret = SRSLTE_ERROR;
}
}
if (uci_data_tx.uci_ack_len > 1) {
if (uci_data_tx.uci_ack_2 != uci_data_rx.uci_ack_2) {
printf("UCI ACK 2 bit error: %d != %d\n", uci_data_tx.uci_ack_2, uci_data_rx.uci_ack_2);
ret = SRSLTE_ERROR;
}
}
if (uci_data_tx.uci_ri_len) {
if (uci_data_tx.uci_ri != uci_data_rx.uci_ri) {
printf("UCI RI bit error: %d != %d\n", uci_data_tx.uci_ri, uci_data_rx.uci_ri);
ret = SRSLTE_ERROR;
}
}
if (uci_data_tx.uci_cqi_len) {
@ -265,7 +292,8 @@ int main(int argc, char **argv) {
}
quit:
srslte_pusch_free(&pusch);
srslte_pusch_free(&pusch_tx);
srslte_pusch_free(&pusch_rx);
srslte_softbuffer_tx_free(&softbuffer_tx);
if (sf_symbols) {

View File

@ -551,24 +551,56 @@ static uint32_t Q_prime_ri_ack(srslte_pusch_cfg_t *cfg,
return Q_prime;
}
static void encode_ri_ack(uint8_t data, srslte_uci_bit_type_t q_encoded_bits[6], uint8_t Qm)
static uint32_t encode_ri_ack(uint8_t data[2], uint32_t data_len, srslte_uci_bit_type_t q_encoded_bits[18], uint8_t Qm)
{
q_encoded_bits[0] = data?UCI_BIT_1:UCI_BIT_0;
q_encoded_bits[1] = UCI_BIT_REPETITION;
for (uint32_t i=2;i<Qm;i++) {
q_encoded_bits[i] = UCI_BIT_PLACEHOLDER;
uint32_t i = 0;
if (data_len == 1) {
q_encoded_bits[i++] = data[0] ? UCI_BIT_1 : UCI_BIT_0;
q_encoded_bits[i++] = UCI_BIT_REPETITION;
while(i < Qm) {
q_encoded_bits[i++] = UCI_BIT_PLACEHOLDER;
}
} else {
q_encoded_bits[i++] = data[0] ? UCI_BIT_1 : UCI_BIT_0;
q_encoded_bits[i++] = data[1] ? UCI_BIT_1 : UCI_BIT_0;
while(i<Qm) {
q_encoded_bits[i++] = UCI_BIT_PLACEHOLDER;
}
q_encoded_bits[i++] = (data[0]^data[1]) ? UCI_BIT_1 : UCI_BIT_0;
q_encoded_bits[i++] = data[0] ? UCI_BIT_1 : UCI_BIT_0;
while(i<Qm*2) {
q_encoded_bits[i++] = UCI_BIT_PLACEHOLDER;
}
q_encoded_bits[i++] = data[1] ? UCI_BIT_1 : UCI_BIT_0;
q_encoded_bits[i++] = (data[0]^data[1]) ? UCI_BIT_1 : UCI_BIT_0;
while(i<Qm*3) {
q_encoded_bits[i++] = UCI_BIT_PLACEHOLDER;
}
}
return i;
}
static int32_t decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos)
static void decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos, uint32_t Qm, int32_t data[3])
{
uint32_t p0 = pos[0].position;
uint32_t p1 = pos[1].position;
uint32_t q0 = c_seq[p0]?q_bits[p0]:-q_bits[p0];
uint32_t q1 = c_seq[p0]?q_bits[p1]:-q_bits[p1];
uint32_t p0 = pos[Qm * 0 + 0].position;
uint32_t p1 = pos[Qm * 0 + 1].position;
uint32_t p2 = pos[Qm * 1 + 0].position;
uint32_t p3 = pos[Qm * 1 + 1].position;
uint32_t p4 = pos[Qm * 2 + 0].position;
uint32_t p5 = pos[Qm * 2 + 1].position;
return -(q0+q1);
int32_t q0 = c_seq[p0] ? q_bits[p0] : -q_bits[p0];
int32_t q1 = c_seq[p1] ? q_bits[p1] : -q_bits[p1];
int32_t q2 = c_seq[p2] ? q_bits[p2] : -q_bits[p2];
int32_t q3 = c_seq[p3] ? q_bits[p3] : -q_bits[p3];
int32_t q4 = c_seq[p4] ? q_bits[p4] : -q_bits[p4];
int32_t q5 = c_seq[p5] ? q_bits[p5] : -q_bits[p5];
data[0] -= q0 + q3;
data[1] -= q1 + q4;
data[2] -= q2 + q5;
}
@ -577,25 +609,29 @@ static int32_t decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *
*/
int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq,
float beta, uint32_t H_prime_total,
uint32_t O_cqi, srslte_uci_bit_t *ack_bits, uint8_t *data)
uint32_t O_cqi, srslte_uci_bit_t *ack_bits, uint8_t acks[2], uint32_t nof_acks)
{
int32_t rx_ack = 0;
int32_t acks_sum[3] = {0, 0, 0};
if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n");
return -1;
}
uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta);
uint32_t Qprime = Q_prime_ri_ack(cfg, nof_acks, O_cqi, beta);
// Use the same interleaver function to get the HARQ bit position
for (uint32_t i=0;i<Qprime;i++) {
for (uint32_t i = 0; i < Qprime; i++) {
uci_ulsch_interleave_ack_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]);
rx_ack += (int32_t) decode_ri_ack(q_bits, c_seq, ack_bits);
if ((i % 3 == 0) && i > 0) {
decode_ri_ack(q_bits, &c_seq[0], &ack_bits[cfg->grant.Qm*(i-3)], cfg->grant.Qm, acks_sum);
}
}
if (data) {
*data = rx_ack>0;
if (acks) {
acks[0] = (uint8_t)(acks_sum[0] > 0);
acks[1] = (uint8_t)(acks_sum[1] > 0);
// TODO: Do something with acks_sum[2]
}
return (int) Qprime;
}
@ -603,23 +639,23 @@ int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_s
/* Encode UCI HARQ/ACK bits as described in 5.2.2.6 of 36.212
* Currently only supporting 1-bit HARQ
*/
int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, uint8_t data,
int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, uint8_t acks[2], uint32_t nof_acks,
uint32_t O_cqi, float beta, uint32_t H_prime_total,
srslte_uci_bit_t *ack_bits)
{
{
if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n");
return -1;
}
uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta);
srslte_uci_bit_type_t q_encoded_bits[6];
uint32_t Qprime = Q_prime_ri_ack(cfg, nof_acks, O_cqi, beta);
srslte_uci_bit_type_t q_encoded_bits[18];
encode_ri_ack(data, q_encoded_bits, cfg->grant.Qm);
uint32_t nof_encoded_bits = encode_ri_ack(acks, nof_acks, q_encoded_bits, cfg->grant.Qm);
for (uint32_t i=0;i<Qprime;i++) {
uci_ulsch_interleave_ack_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]);
uci_ulsch_interleave_put(q_encoded_bits, cfg->grant.Qm, &ack_bits[cfg->grant.Qm*i]);
uci_ulsch_interleave_put(&q_encoded_bits[(i*cfg->grant.Qm)%nof_encoded_bits], cfg->grant.Qm, &ack_bits[cfg->grant.Qm*i]);
}
return (int) Qprime;
@ -632,7 +668,7 @@ int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_se
float beta, uint32_t H_prime_total,
uint32_t O_cqi, srslte_uci_bit_t *ri_bits, uint8_t *data)
{
int32_t rx_ri = 0;
int32_t ri_sum[3] = {0, 0, 0};
if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n");
@ -644,11 +680,13 @@ int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_se
// Use the same interleaver function to get the HARQ bit position
for (uint32_t i=0;i<Qprime;i++) {
uci_ulsch_interleave_ri_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]);
rx_ri += (int32_t) decode_ri_ack(q_bits, c_seq, ri_bits);
if ((i % 3 == 0) && i > 0) {
decode_ri_ack(q_bits, &c_seq[0], &ri_bits[cfg->grant.Qm*(i-3)], cfg->grant.Qm, ri_sum);
}
}
if (data) {
*data = rx_ri>0;
*data = (uint8_t) ((ri_sum[0] + ri_sum[1] + ri_sum[2]) > 0);
}
return (int) Qprime;
@ -659,22 +697,24 @@ int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_se
* Currently only supporting 1-bit RI
*/
int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg,
uint8_t data,
uint8_t ri,
uint32_t O_cqi, float beta, uint32_t H_prime_total,
srslte_uci_bit_t *ri_bits)
{
// FIXME: It supports RI of 1 bit only
uint8_t data[2] = {ri, 0};
if (beta < 0) {
fprintf(stderr, "Error beta is reserved\n");
return -1;
}
uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta);
srslte_uci_bit_type_t q_encoded_bits[6];
srslte_uci_bit_type_t q_encoded_bits[18];
encode_ri_ack(data, q_encoded_bits, cfg->grant.Qm);
uint32_t nof_encoded_bits = encode_ri_ack(data, 1, q_encoded_bits, cfg->grant.Qm);
for (uint32_t i=0;i<Qprime;i++) {
uci_ulsch_interleave_ri_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]);
uci_ulsch_interleave_put(q_encoded_bits, cfg->grant.Qm, &ri_bits[cfg->grant.Qm*i]);
uci_ulsch_interleave_put(&q_encoded_bits[(i*cfg->grant.Qm)%nof_encoded_bits], cfg->grant.Qm, &ri_bits[cfg->grant.Qm*i]);
}
return (int) Qprime;

View File

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

View File

@ -117,6 +117,7 @@ static void* async_thread(void *h) {
return NULL;
}
}
uhd_async_metadata_free(&md);
return NULL;
}
@ -226,7 +227,7 @@ int rf_uhd_start_rx_stream(void *h)
.stream_now = false
};
uhd_usrp_get_time_now(handler->usrp, 0, &stream_cmd.time_spec_full_secs, &stream_cmd.time_spec_frac_secs);
stream_cmd.time_spec_frac_secs += 0.5;
stream_cmd.time_spec_frac_secs += 0.1;
if (stream_cmd.time_spec_frac_secs > 1) {
stream_cmd.time_spec_frac_secs -= 1;
stream_cmd.time_spec_full_secs += 1;
@ -457,14 +458,17 @@ int rf_uhd_close(void *h)
uhd_rx_metadata_free(&handler->rx_md_first);
uhd_rx_metadata_free(&handler->rx_md);
uhd_meta_range_free(&handler->rx_gain_range);
uhd_tx_streamer_free(&handler->tx_stream);
uhd_rx_streamer_free(&handler->rx_stream);
if (handler->has_rssi) {
uhd_sensor_value_free(&handler->rssi_value);
}
handler->async_thread_running = false;
pthread_join(handler->async_thread, NULL);
pthread_join(handler->async_thread, NULL);
uhd_tx_streamer_free(&handler->tx_stream);
uhd_rx_streamer_free(&handler->rx_stream);
uhd_usrp_free(&handler->usrp);
free(handler);
/** Something else to close the USRP?? */
return 0;
@ -488,8 +492,7 @@ double rf_uhd_set_rx_srate(void *h, double freq)
for (int i=0;i<handler->nof_rx_channels;i++) {
uhd_usrp_set_rx_rate(handler->usrp, freq, i);
}
uhd_usrp_get_rx_rate(handler->usrp, 0, &freq);
return freq;
return freq;
}
double rf_uhd_set_tx_srate(void *h, double freq)
@ -498,7 +501,6 @@ double rf_uhd_set_tx_srate(void *h, double freq)
for (int i=0;i<handler->nof_tx_channels;i++) {
uhd_usrp_set_tx_rate(handler->usrp, freq, i);
}
uhd_usrp_get_tx_rate(handler->usrp, 0, &freq);
handler->tx_rate = freq;
return freq;
}
@ -509,7 +511,6 @@ double rf_uhd_set_rx_gain(void *h, double gain)
for (int i=0;i<handler->nof_rx_channels;i++) {
uhd_usrp_set_rx_gain(handler->usrp, gain, i, "");
}
uhd_usrp_get_rx_gain(handler->usrp, 0, "", &gain);
return gain;
}
@ -519,7 +520,6 @@ double rf_uhd_set_tx_gain(void *h, double gain)
for (int i=0;i<handler->nof_tx_channels;i++) {
uhd_usrp_set_tx_gain(handler->usrp, gain, i, "");
}
uhd_usrp_get_tx_gain(handler->usrp, 0, "", &gain);
return gain;
}
@ -551,7 +551,6 @@ double rf_uhd_set_rx_freq(void *h, double freq)
for (int i=0;i<handler->nof_rx_channels;i++) {
uhd_usrp_set_rx_freq(handler->usrp, &tune_request, i, &tune_result);
}
uhd_usrp_get_rx_freq(handler->usrp, 0, &freq);
return freq;
}
@ -567,7 +566,6 @@ double rf_uhd_set_tx_freq(void *h, double freq)
for (int i=0;i<handler->nof_tx_channels;i++) {
uhd_usrp_set_tx_freq(handler->usrp, &tune_request, i, &tune_result);
}
uhd_usrp_get_tx_freq(handler->usrp, 0, &freq);
return freq;
}
@ -629,7 +627,9 @@ int rf_uhd_recv_with_time_multi(void *h,
log_overflow(handler);
} else if (error_code == UHD_RX_METADATA_ERROR_CODE_LATE_COMMAND) {
log_late(handler);
} else if (error_code != UHD_RX_METADATA_ERROR_CODE_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);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -28,6 +28,8 @@
#include <strings.h>
#include <complex.h>
#include <math.h>
#include <srslte/srslte.h>
#include <srslte/phy/sync/sync.h>
#include "srslte/phy/utils/debug.h"
#include "srslte/phy/common/phy_common.h"
@ -39,6 +41,8 @@
#define CFO_EMA_ALPHA 0.1
#define CP_EMA_ALPHA 0.1
#define DEFAULT_CFO_TOL 50.0 // Hz
static bool fft_size_isvalid(uint32_t fft_size) {
if (fft_size >= SRSLTE_SYNC_FFT_SZ_MIN && fft_size <= SRSLTE_SYNC_FFT_SZ_MAX && (fft_size%64) == 0) {
return true;
@ -77,7 +81,10 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o
q->frame_size = frame_size;
q->max_offset = max_offset;
q->sss_alg = SSS_FULL;
q->max_frame_size = frame_size;
q->mean_cfo_isunset = true;
q->mean_cfo2_isunset = true;
q->enable_cfo_corr = true;
if (srslte_cfo_init(&q->cfocorr, q->frame_size)) {
fprintf(stderr, "Error initiating CFO\n");
@ -89,11 +96,8 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o
goto clean_exit;
}
// Set a CFO tolerance of approx 50 Hz
srslte_cfo_set_tol(&q->cfocorr, 50.0/(15000.0*q->fft_size));
// Set a CFO tolerance of approx 50 Hz
srslte_cfo_set_tol(&q->cfocorr2, 50.0/(15000.0*q->fft_size));
// Set default CFO tolerance
srslte_sync_set_cfo_tol(q, DEFAULT_CFO_TOL);
for (int i=0;i<2;i++) {
q->cfo_i_corr[i] = srslte_vec_malloc(sizeof(cf_t)*q->frame_size);
@ -111,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);
q->decimate = decimate;
if(!decimate)
if(!decimate) {
decimate = 1;
if (srslte_pss_synch_init_fft_offset_decim(&q->pss, max_offset, fft_size,0,decimate)) {
}
if (srslte_pss_synch_init_fft_offset_decim(&q->pss, max_offset, fft_size, 0, decimate)) {
fprintf(stderr, "Error initializing PSS object\n");
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) {
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) {
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) {
@ -445,13 +526,18 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t
cf_t *input_cfo = input;
if (q->enable_cfo_corr) {
float cfo = cfo_estimate(q, input);
/* compute exponential moving average CFO */
q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, q->cfo_ema_alpha);
float cfo = cfo_estimate(q, input);
if (q->mean_cfo_isunset) {
q->mean_cfo = cfo;
q->mean_cfo_isunset = false;
} else {
/* compute exponential moving average CFO */
q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, q->cfo_ema_alpha);
}
/* Correct CFO with the averaged CFO estimation */
srslte_cfo_correct(&q->cfocorr2, input, q->temp, -q->mean_cfo / q->fft_size);
srslte_cfo_correct(&q->cfocorr2, input, q->temp, -q->mean_cfo / q->fft_size);
input_cfo = q->temp;
}
@ -504,8 +590,13 @@ srslte_sync_find_ret_t srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t
if (peak_pos + find_offset >= 2*(q->fft_size + SRSLTE_CP_LEN_EXT(q->fft_size))) {
float cfo2 = srslte_pss_synch_cfo_compute(&q->pss, &input[find_offset + peak_pos - q->fft_size]);
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;
} else {
ret = SRSLTE_SYNC_FOUND_NOSPACE;
@ -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) {
q->M_ext_avg = 0;
q->M_ext_avg = 0;
q->M_norm_avg = 0;
srslte_pss_synch_reset(&q->pss);
}

View File

@ -29,6 +29,7 @@
#include <strings.h>
#include <assert.h>
#include <unistd.h>
#include <srslte/srslte.h>
#include "srslte/phy/ue/ue_cell_search.h"
@ -51,11 +52,16 @@ int srslte_ue_cellsearch_init(srslte_ue_cellsearch_t * q, uint32_t max_frames,
cell.id = SRSLTE_CELL_ID_UNKNOWN;
cell.nof_prb = SRSLTE_CS_NOF_PRB;
if (srslte_ue_sync_init(&q->ue_sync, cell, recv_callback, stream_handler)) {
if (srslte_ue_sync_init(&q->ue_sync, cell.nof_prb, true, recv_callback, stream_handler)) {
fprintf(stderr, "Error initiating ue_sync\n");
goto clean_exit;
}
if (srslte_ue_sync_set_cell(&q->ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n");
goto clean_exit;
}
q->sf_buffer[0] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100));
q->nof_rx_antennas = 1;
@ -105,11 +111,15 @@ int srslte_ue_cellsearch_init_multi(srslte_ue_cellsearch_t * q, uint32_t max_fra
cell.id = SRSLTE_CELL_ID_UNKNOWN;
cell.nof_prb = SRSLTE_CS_NOF_PRB;
if (srslte_ue_sync_init_multi(&q->ue_sync, cell, recv_callback, nof_rx_antennas, stream_handler)) {
if (srslte_ue_sync_init_multi(&q->ue_sync, cell.nof_prb, true, recv_callback, nof_rx_antennas, stream_handler)) {
fprintf(stderr, "Error initiating ue_sync\n");
goto clean_exit;
}
if (srslte_ue_sync_set_cell(&q->ue_sync, cell)) {
fprintf(stderr, "Error initiating ue_sync\n");
goto clean_exit;
}
for (int i=0;i<nof_rx_antennas;i++) {
q->sf_buffer[i] = srslte_vec_malloc(3*sizeof(cf_t)*SRSLTE_SF_LEN_PRB(100));
}
@ -242,7 +252,8 @@ int srslte_ue_cellsearch_scan(srslte_ue_cellsearch_t * q,
{
int ret = 0;
float max_peak_value = -1.0;
uint32_t nof_detected_cells = 0;
uint32_t nof_detected_cells = 0;
for (uint32_t N_id_2=0;N_id_2<3 && ret >= 0;N_id_2++) {
ret = srslte_ue_cellsearch_scan_N_id_2(q, N_id_2, &found_cells[N_id_2]);
if (ret < 0) {
@ -273,8 +284,12 @@ int srslte_ue_cellsearch_scan_N_id_2(srslte_ue_cellsearch_t * q,
if (q != NULL)
{
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_reset(&q->ue_sync);
do {

View File

@ -27,6 +27,7 @@
#include "srslte/phy/ue/ue_dl.h"
#include <string.h>
#include <srslte/srslte.h>
#define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb)
@ -35,6 +36,7 @@
#define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define MAX_SFLEN_RE SRSLTE_SF_LEN_RE(max_prb, q->cell.cp)
const static srslte_dci_format_t ue_dci_formats[8][2] = {
/* Mode 1 */ {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1},
@ -51,57 +53,50 @@ static srslte_dci_format_t common_formats[] = {SRSLTE_DCI_FORMAT1A,SRSLTE_DCI_FO
const uint32_t nof_common_formats = 2;
int srslte_ue_dl_init(srslte_ue_dl_t *q,
srslte_cell_t cell,
uint32_t max_prb,
uint32_t nof_rx_antennas)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
nof_rx_antennas <= SRSLTE_MAX_PORTS &&
srslte_cell_isvalid(&cell))
nof_rx_antennas <= SRSLTE_MAX_PORTS)
{
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_ue_dl_t));
q->cell = cell;
q->pkt_errors = 0;
q->pkts_total = 0;
q->pending_ul_dci_rnti = 0;
q->sample_offset = 0;
q->nof_rx_antennas = nof_rx_antennas;
if (srslte_ofdm_rx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) {
q->nof_rx_antennas = nof_rx_antennas;
if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) {
fprintf(stderr, "Error initiating FFT\n");
goto clean_exit;
}
if (srslte_chest_dl_init(&q->chest, cell)) {
if (srslte_chest_dl_init(&q->chest, max_prb)) {
fprintf(stderr, "Error initiating channel estimator\n");
goto clean_exit;
}
if (srslte_regs_init(&q->regs, q->cell)) {
fprintf(stderr, "Error initiating REGs\n");
goto clean_exit;
}
if (srslte_pcfich_init_multi(&q->pcfich, &q->regs, q->cell, nof_rx_antennas)) {
if (srslte_pcfich_init(&q->pcfich, nof_rx_antennas)) {
fprintf(stderr, "Error creating PCFICH object\n");
goto clean_exit;
}
if (srslte_phich_init(&q->phich, &q->regs, q->cell)) {
if (srslte_phich_init(&q->phich, nof_rx_antennas)) {
fprintf(stderr, "Error creating PHICH object\n");
goto clean_exit;
}
if (srslte_pdcch_init_multi(&q->pdcch, &q->regs, q->cell, nof_rx_antennas)) {
if (srslte_pdcch_init_ue(&q->pdcch, max_prb, nof_rx_antennas)) {
fprintf(stderr, "Error creating PDCCH object\n");
goto clean_exit;
}
if (srslte_pdsch_init_rx(&q->pdsch, q->cell, nof_rx_antennas)) {
if (srslte_pdsch_init_ue(&q->pdsch, max_prb, nof_rx_antennas)) {
fprintf(stderr, "Error creating PDSCH object\n");
goto clean_exit;
}
for (int i = 0; i < SRSLTE_MAX_TB; i++) {
q->softbuffers[i] = srslte_vec_malloc(sizeof(srslte_softbuffer_rx_t));
if (!q->softbuffers[i]) {
@ -109,25 +104,25 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
goto clean_exit;
}
if (srslte_softbuffer_rx_init(q->softbuffers[i], q->cell.nof_prb)) {
if (srslte_softbuffer_rx_init(q->softbuffers[i], max_prb)) {
fprintf(stderr, "Error initiating soft buffer\n");
goto clean_exit;
}
}
if (srslte_cfo_init(&q->sfo_correct, q->cell.nof_prb*SRSLTE_NRE)) {
if (srslte_cfo_init(&q->sfo_correct, max_prb*SRSLTE_NRE)) {
fprintf(stderr, "Error initiating SFO correct\n");
goto clean_exit;
}
srslte_cfo_set_tol(&q->sfo_correct, 1e-5f/q->fft.symbol_sz);
for (int j=0;j<nof_rx_antennas;j++) {
q->sf_symbols_m[j] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
q->sf_symbols_m[j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t));
if (!q->sf_symbols_m[j]) {
perror("malloc");
goto clean_exit;
}
for (uint32_t i=0;i<q->cell.nof_ports;i++) {
q->ce_m[i][j] = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
for (uint32_t i=0;i<SRSLTE_MAX_PORTS;i++) {
q->ce_m[i][j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t));
if (!q->ce_m[i][j]) {
perror("malloc");
goto clean_exit;
@ -136,14 +131,13 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
}
q->sf_symbols = q->sf_symbols_m[0];
for (int i=0;i<q->cell.nof_ports;i++) {
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
q->ce[i] = q->ce_m[i][0];
}
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
fprintf(stderr, "Invalid parametres\n");
}
clean_exit:
@ -173,7 +167,7 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) {
if (q->sf_symbols_m[j]) {
free(q->sf_symbols_m[j]);
}
for (uint32_t i=0;i<q->cell.nof_ports;i++) {
for (uint32_t i=0;i<SRSLTE_MAX_PORTS;i++) {
if (q->ce_m[i][j]) {
free(q->ce_m[i][j]);
}
@ -183,11 +177,74 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) {
}
}
int srslte_ue_dl_set_cell(srslte_ue_dl_t *q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
{
q->pkt_errors = 0;
q->pkts_total = 0;
q->pending_ul_dci_rnti = 0;
q->sample_offset = 0;
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
if (q->cell.nof_prb != 0) {
srslte_regs_free(&q->regs);
}
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
if (srslte_regs_init(&q->regs, q->cell)) {
fprintf(stderr, "Error resizing REGs\n");
return SRSLTE_ERROR;
}
if (srslte_cfo_resize(&q->sfo_correct, q->cell.nof_prb*SRSLTE_NRE)) {
fprintf(stderr, "Error resizing SFO correct\n");
return SRSLTE_ERROR;
}
srslte_cfo_set_tol(&q->sfo_correct, 1e-5/q->fft.symbol_sz);
if (srslte_ofdm_rx_set_prb(&q->fft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error resizing FFT\n");
return SRSLTE_ERROR;
}
if (srslte_chest_dl_set_cell(&q->chest, q->cell)) {
fprintf(stderr, "Error resizing channel estimator\n");
return SRSLTE_ERROR;
}
if (srslte_pcfich_set_cell(&q->pcfich, &q->regs, q->cell)) {
fprintf(stderr, "Error resizing PCFICH object\n");
return SRSLTE_ERROR;
}
if (srslte_phich_set_cell(&q->phich, &q->regs, q->cell)) {
fprintf(stderr, "Error resizing PHICH object\n");
return SRSLTE_ERROR;
}
if (srslte_pdcch_set_cell(&q->pdcch, &q->regs, q->cell)) {
fprintf(stderr, "Error resizing PDCCH object\n");
return SRSLTE_ERROR;
}
if (srslte_pdsch_set_cell(&q->pdsch, q->cell)) {
fprintf(stderr, "Error creating PDSCH object\n");
return SRSLTE_ERROR;
}
q->current_rnti = 0;
}
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
}
return ret;
}
/* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while
* to execute, so shall be called once the final C-RNTI has been allocated for the session.
* For the connection procedure, use srslte_pusch_encode_rnti() or srslte_pusch_decode_rnti() functions
*/
void srslte_ue_dl_set_rnti(srslte_ue_dl_t *q, uint16_t rnti) {
srslte_pdsch_set_rnti(&q->pdsch, rnti);
// Compute UE-specific and Common search space for this RNTI
@ -235,7 +292,7 @@ int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_P
/* Correct SFO multiplying by complex exponential in the time domain */
if (q->sample_offset) {
for (int i=0;i<2*SRSLTE_CP_NSYMB(q->cell.cp);i++) {
srslte_cfo_correct(&q->sfo_correct,
srslte_cfo_correct(&q->sfo_correct,
&q->sf_symbols_m[j][i*q->cell.nof_prb*SRSLTE_NRE],
&q->sf_symbols_m[j][i*q->cell.nof_prb*SRSLTE_NRE],
q->sample_offset / q->fft.symbol_sz);
@ -280,21 +337,22 @@ int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t *c
int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx,
int rvidx[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type) {
uint32_t pmi = 0;
uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant);
/* Translates Precoding Information (pinfo) to Precoding matrix Index (pmi) as 3GPP 36.212 Table 5.3.3.1.5-4 */
if (mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) {
if (grant->nof_tb == 1) {
if (nof_tb == 1) {
if (grant->pinfo > 0 && grant->pinfo < 5) {
pmi = grant->pinfo - 1;
} else {
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", q->pdsch_cfg.grant.nof_tb, grant->pinfo);
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo);
return SRSLTE_ERROR;
}
} else {
if (grant->pinfo < 2) {
pmi = grant->pinfo;
} else {
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", q->pdsch_cfg.grant.nof_tb, grant->pinfo);
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo);
return SRSLTE_ERROR;
}
}
@ -336,29 +394,33 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS],
/* ===== These lines of code are supposed to be MAC functionality === */
int rvidx[SRSLTE_MAX_CODEWORDS] = {1};
if (dci_unpacked.rv_idx < 0) {
uint32_t sfn = tti/10;
uint32_t k = (sfn/2)%4;
for (int i = 0; i < grant.nof_tb; i++) {
rvidx[i] = ((uint32_t) ceilf((float) 1.5 * k)) % 4;
srslte_softbuffer_rx_reset_tbs(q->softbuffers[i], (uint32_t) grant.mcs[i].tbs);
uint32_t sfn = tti / 10;
uint32_t k = (sfn / 2) % 4;
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (grant.tb_en[i]) {
rvidx[i] = ((uint32_t) ceilf((float) 1.5 * k)) % 4;
srslte_softbuffer_rx_reset_tbs(q->softbuffers[i], (uint32_t) grant.mcs[i].tbs);
}
}
} else {
for (int i = 0; i < grant.nof_tb; i++) {
switch(i) {
case 0:
rvidx[i] = (uint32_t) dci_unpacked.rv_idx;
break;
case 1:
rvidx[i] = (uint32_t) dci_unpacked.rv_idx_1;
break;
default:
ERROR("Wrong number of transport blocks");
return SRSLTE_ERROR;
for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) {
if (grant.tb_en[i]) {
switch (i) {
case 0:
rvidx[i] = (uint32_t) dci_unpacked.rv_idx;
break;
case 1:
rvidx[i] = (uint32_t) dci_unpacked.rv_idx_1;
break;
default:
ERROR("Wrong number of transport blocks");
return SRSLTE_ERROR;
}
srslte_softbuffer_rx_reset_tbs(q->softbuffers[i], (uint32_t) grant.mcs[i].tbs);
}
srslte_softbuffer_rx_reset_tbs(q->softbuffers[i], (uint32_t) grant.mcs[i].tbs);
}
}
@ -372,14 +434,14 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS],
}
break;
case SRSLTE_DCI_FORMAT2:
if (grant.nof_tb == 1 && dci_unpacked.pinfo == 0) {
if (SRSLTE_RA_DL_GRANT_NOF_TB(&grant) == 1 && dci_unpacked.pinfo == 0) {
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
} else {
mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX;
}
break;
case SRSLTE_DCI_FORMAT2A:
if (grant.nof_tb == 1 && dci_unpacked.pinfo == 0) {
if (SRSLTE_RA_DL_GRANT_NOF_TB(&grant) == 1 && dci_unpacked.pinfo == 0) {
mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY;
} else {
mimo_type = SRSLTE_MIMO_TYPE_CDD;
@ -413,11 +475,13 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS],
noise_estimate,
rnti, data, acks);
for (int tb = 0; tb < q->pdsch_cfg.grant.nof_tb; tb++) {
if (!acks[tb]) {
q->pkt_errors++;
for (int tb = 0; tb < SRSLTE_MAX_TB; tb++) {
if (grant.tb_en[tb]) {
if (!acks[tb]) {
q->pkt_errors++;
}
q->pkts_total++;
}
q->pkts_total++;
}
if (ret == SRSLTE_ERROR) {
@ -447,10 +511,10 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS],
/* Compute the Rank Indicator (RI) and Precoder Matrix Indicator (PMI) by computing the Signal to Interference plus
* Noise Ratio (SINR), valid for TM4 */
int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint32_t *ri, uint32_t *pmi, float *current_sinr) {
int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint8_t *ri, uint8_t *pmi, float *current_sinr) {
float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest);
float best_sinr = -INFINITY;
uint32_t best_pmi = 0, best_ri = 0;
uint8_t best_pmi = 0, best_ri = 0;
if (q->cell.nof_ports < 2 || q->nof_rx_antennas < 2) {
/* Do nothing */
@ -464,11 +528,11 @@ int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint32_t *ri, uint32_t *pmi, f
/* Select the best Rank indicator (RI) and Precoding Matrix Indicator (PMI) */
for (uint32_t nof_layers = 1; nof_layers <= 2; nof_layers++) {
float _sinr = q->sinr[nof_layers - 1][q->pmi[nof_layers - 1]] * nof_layers;
float _sinr = q->sinr[nof_layers - 1][q->pmi[nof_layers - 1]] * nof_layers * nof_layers;
if (_sinr > best_sinr + 0.1) {
best_sinr = _sinr;
best_pmi = q->pmi[nof_layers - 1];
best_ri = nof_layers;
best_pmi = (uint8_t) q->pmi[nof_layers - 1];
best_ri = (uint8_t) (nof_layers - 1);
}
}
@ -509,7 +573,7 @@ int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint32_t *ri, uint32_t *pmi, f
/* Compute the Rank Indicator (RI) by computing the condition number, valid for TM3 */
int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, uint32_t *ri, float *cn) {
int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, uint8_t *ri, float *cn) {
float _cn;
int ret = srslte_pdsch_cn_compute(&q->pdsch, q->ce_m, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp), &_cn);
@ -520,7 +584,7 @@ int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, uint32_t *ri, float *cn) {
/* Set rank indicator */
if (!ret && ri) {
*ri = (_cn > 3.0f)? 1:0;
*ri = (uint8_t)((_cn < 17.0f)? 1:0);
}
return ret;
@ -732,11 +796,11 @@ bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_pr
}
void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuffer, uint32_t tti, uint32_t rv_idx, uint16_t rnti, uint32_t cfi) {
srslte_vec_save_file("sf_symbols", q->sf_symbols_m, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
srslte_vec_save_file("sf_symbols", q->sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
printf("%d samples\n", SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp));
srslte_vec_save_file("ce0", q->ce_m[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
srslte_vec_save_file("ce0", q->ce[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
if (q->cell.nof_ports > 1) {
srslte_vec_save_file("ce1", q->ce_m[1], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
srslte_vec_save_file("ce1", q->ce[1], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
}
srslte_vec_save_file("pcfich_ce0", q->pcfich.ce[0], q->pcfich.nof_symbols*sizeof(cf_t));
srslte_vec_save_file("pcfich_ce1", q->pcfich.ce[1], q->pcfich.nof_symbols*sizeof(cf_t));
@ -749,13 +813,13 @@ void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuf
srslte_vec_save_file("pdcch_symbols", q->pdcch.symbols[0], q->pdcch.nof_cce*36*sizeof(cf_t));
srslte_vec_save_file("pdcch_eq_symbols", q->pdcch.d, q->pdcch.nof_cce*36*sizeof(cf_t));
srslte_vec_save_file("pdcch_llr", q->pdcch.llr, q->pdcch.nof_cce*72*sizeof(float));
srslte_vec_save_file("pdsch_symbols", q->pdsch.d, q->pdsch_cfg.nbits[0].nof_re*sizeof(cf_t));
srslte_vec_save_file("llr", q->pdsch.e, q->pdsch_cfg.nbits[0].nof_bits*sizeof(cf_t));
int cb_len = q->pdsch_cfg.cb_segm[0].K1;
for (int i=0;i<q->pdsch_cfg.cb_segm[0].C;i++) {
char tmpstr[64];
char tmpstr[64];
snprintf(tmpstr,64,"rmout_%d.dat",i);
srslte_vec_save_file(tmpstr, softbuffer->buffer_f[i], (3*cb_len+12)*sizeof(int16_t));
}

View File

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

View File

@ -29,6 +29,7 @@
#include <strings.h>
#include <assert.h>
#include <unistd.h>
#include <srslte/srslte.h>
#include "srslte/phy/ue/ue_sync.h"
@ -128,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,
srslte_cell_t cell,
int (recv_callback)(void*, void*, uint32_t,srslte_timestamp_t*),
void *stream_handler)
uint32_t max_prb,
bool search_cell,
int (recv_callback)(void*, void*, uint32_t,srslte_timestamp_t*),
void *stream_handler)
{
int ret = srslte_ue_sync_init_multi(q, cell, recv_callback_multi_to_single, 1, (void*) q);
int ret = srslte_ue_sync_init_multi(q, max_prb, search_cell, recv_callback_multi_to_single, 1, (void*) q);
q->recv_callback_single = recv_callback;
q->stream_single = stream_handler;
return ret;
}
int srslte_ue_sync_init_multi(srslte_ue_sync_t *q,
srslte_cell_t cell,
uint32_t max_prb,
bool search_cell,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t,srslte_timestamp_t*),
uint32_t nof_rx_antennas,
void *stream_handler)
{
return srslte_ue_sync_init_multi_decim(q, cell,recv_callback ,nof_rx_antennas,stream_handler,1);
return srslte_ue_sync_init_multi_decim(q, max_prb,search_cell, recv_callback ,nof_rx_antennas,stream_handler,1);
}
int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
srslte_cell_t cell,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t,srslte_timestamp_t*),
uint32_t nof_rx_antennas,
void *stream_handler,
int decimate)
uint32_t max_prb,
bool search_cell,
int (recv_callback)(void*, cf_t*[SRSLTE_MAX_PORTS], uint32_t,srslte_timestamp_t*),
uint32_t nof_rx_antennas,
void *stream_handler,
int decimate)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
stream_handler != NULL &&
srslte_nofprb_isvalid(cell.nof_prb) &&
nof_rx_antennas <= SRSLTE_MAX_PORTS &&
recv_callback != NULL)
{
@ -171,104 +174,58 @@ int srslte_ue_sync_init_multi_decim(srslte_ue_sync_t *q,
q->stream = stream_handler;
q->recv_callback = recv_callback;
q->nof_rx_antennas = nof_rx_antennas;
q->cell = cell;
q->fft_size = srslte_symbol_sz(q->cell.nof_prb);
q->fft_size = srslte_symbol_sz(max_prb);
q->sf_len = SRSLTE_SF_LEN(q->fft_size);
q->file_mode = false;
q->correct_cfo = true;
q->agc_period = 0;
q->sample_offset_correct_period = DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD;
q->sfo_ema = DEFAULT_SFO_EMA_COEFF;
if (cell.id == 1000) {
q->max_prb = max_prb;
if (search_cell) {
/* If the cell is unkown, we search PSS/SSS in 5 ms */
q->nof_recv_sf = 5;
q->decode_sss_on_track = true;
} else {
/* If the cell is known, we work on a 1ms basis */
q->nof_recv_sf = 1;
q->decode_sss_on_track = true;
}
q->frame_len = q->nof_recv_sf*q->sf_len;
if(q->fft_size < 700 && q->decimate)
{
if(q->fft_size < 700 && q->decimate) {
q->decimate = 1;
}
if(srslte_sync_init_decim(&q->sfind, q->frame_len, q->frame_len, q->fft_size,q->decimate)) {
fprintf(stderr, "Error initiating sync find\n");
goto clean_exit;
}
if (cell.id == 1000) {
if (search_cell) {
if(srslte_sync_init(&q->strack, q->frame_len, TRACK_FRAME_SIZE, q->fft_size)) {
fprintf(stderr, "Error initiating sync track\n");
goto clean_exit;
}
}
} else {
if(srslte_sync_init(&q->strack, q->frame_len, SRSLTE_CP_LEN_NORM(1,q->fft_size), q->fft_size)) {
fprintf(stderr, "Error initiating sync track\n");
goto clean_exit;
}
}
if (cell.id == 1000) {
/* If the cell id is unknown, enable CP detection on find */
// FIXME: CP detection not working very well. Not supporting Extended CP right now
srslte_sync_cp_en(&q->sfind, false);
srslte_sync_cp_en(&q->strack, false);
srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.8);
srslte_sync_set_cfo_ema_alpha(&q->strack, 0.1);
srslte_sync_cfo_i_detec_en(&q->sfind, false);
q->nof_avg_find_frames = FIND_NOF_AVG_FRAMES;
srslte_sync_set_threshold(&q->sfind, 2.0);
srslte_sync_set_threshold(&q->strack, 1.2);
} else {
srslte_sync_set_N_id_2(&q->sfind, cell.id%3);
srslte_sync_set_N_id_2(&q->strack, cell.id%3);
q->sfind.cp = cell.cp;
q->strack.cp = cell.cp;
srslte_sync_cp_en(&q->sfind, false);
srslte_sync_cp_en(&q->strack, false);
srslte_sync_cfo_i_detec_en(&q->sfind, false);
srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.1);
srslte_sync_set_cfo_ema_alpha(&q->strack, 0.1);
/* In find phase and if the cell is known, do not average pss correlation
* because we only capture 1 subframe and do not know where the peak is.
*/
q->nof_avg_find_frames = 1;
srslte_sync_set_em_alpha(&q->sfind, 1);
srslte_sync_set_threshold(&q->sfind, 3.0);
srslte_sync_set_em_alpha(&q->strack, 0.2);
srslte_sync_set_threshold(&q->strack, 1.2);
}
srslte_ue_sync_reset(q);
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) {
@ -281,13 +238,119 @@ void srslte_ue_sync_free(srslte_ue_sync_t *q) {
}
if (!q->file_mode) {
srslte_sync_free(&q->sfind);
srslte_sync_free(&q->strack);
srslte_sync_free(&q->strack);
} else {
srslte_filesource_free(&q->file_source);
}
bzero(q, sizeof(srslte_ue_sync_t));
}
int srslte_ue_sync_set_cell(srslte_ue_sync_t *q, srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_nofprb_isvalid(cell.nof_prb))
{
ret = SRSLTE_ERROR;
if (cell.nof_prb > q->max_prb) {
fprintf(stderr, "Error in ue_sync_set_cell(): cell.nof_prb must be lower than initialized\n");
return SRSLTE_ERROR;
}
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
q->fft_size = srslte_symbol_sz(q->cell.nof_prb);
q->sf_len = SRSLTE_SF_LEN(q->fft_size);
q->agc_period = 0;
if (cell.id == 1000) {
/* If the cell is unkown, we search PSS/SSS in 5 ms */
q->nof_recv_sf = 5;
q->decode_sss_on_track = true;
} else {
/* If the cell is known, we work on a 1ms basis */
q->nof_recv_sf = 1;
q->decode_sss_on_track = true;
}
q->frame_len = q->nof_recv_sf*q->sf_len;
if(q->fft_size < 700 && q->decimate) {
q->decimate = 1;
}
if(srslte_sync_resize(&q->sfind, q->frame_len, q->frame_len, q->fft_size)) {
fprintf(stderr, "Error initiating sync find\n");
return SRSLTE_ERROR;
}
if (cell.id == 1000) {
if(srslte_sync_resize(&q->strack, q->frame_len, TRACK_FRAME_SIZE, q->fft_size)) {
fprintf(stderr, "Error initiating sync track\n");
return SRSLTE_ERROR;
}
} else {
if(srslte_sync_resize(&q->strack, q->frame_len, SRSLTE_CP_LEN_NORM(1,q->fft_size), q->fft_size)) {
fprintf(stderr, "Error initiating sync track\n");
return SRSLTE_ERROR;
}
}
if (cell.id == 1000) {
/* If the cell id is unknown, enable CP detection on find */
// FIXME: CP detection not working very well. Not supporting Extended CP right now
srslte_sync_cp_en(&q->sfind, false);
srslte_sync_cp_en(&q->strack, false);
srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.8);
srslte_sync_set_cfo_ema_alpha(&q->strack, 0.1);
srslte_sync_cfo_i_detec_en(&q->sfind, false);
q->nof_avg_find_frames = FIND_NOF_AVG_FRAMES;
srslte_sync_set_threshold(&q->sfind, 2.0);
srslte_sync_set_threshold(&q->strack, 1.2);
} else {
srslte_sync_set_N_id_2(&q->sfind, cell.id%3);
srslte_sync_set_N_id_2(&q->strack, cell.id%3);
q->sfind.cp = cell.cp;
q->strack.cp = cell.cp;
srslte_sync_cp_en(&q->sfind, false);
srslte_sync_cp_en(&q->strack, false);
srslte_sync_cfo_i_detec_en(&q->sfind, false);
srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.1);
srslte_sync_set_cfo_ema_alpha(&q->strack, 0.1);
/* In find phase and if the cell is known, do not average pss correlation
* because we only capture 1 subframe and do not know where the peak is.
*/
q->nof_avg_find_frames = 1;
srslte_sync_set_em_alpha(&q->sfind, 1);
srslte_sync_set_threshold(&q->sfind, 3.0);
srslte_sync_set_em_alpha(&q->strack, 0.2);
srslte_sync_set_threshold(&q->strack, 1.2);
}
srslte_ue_sync_reset(q);
ret = SRSLTE_SUCCESS;
}
return ret;
}
void srslte_ue_sync_get_last_timestamp(srslte_ue_sync_t *q, srslte_timestamp_t *timestamp) {
memcpy(timestamp, &q->last_timestamp, sizeof(srslte_timestamp_t));
}
@ -317,6 +380,8 @@ void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, float cfo) {
srslte_sync_set_cfo(&q->strack, cfo/15000);
}
void srslte_ue_sync_set_cfo_tol(srslte_ue_sync_t *q, float cfo_tol) {}
float srslte_ue_sync_get_sfo(srslte_ue_sync_t *q) {
return q->mean_sfo/5e-3;
}
@ -649,7 +714,7 @@ int srslte_ue_sync_zerocopy_multi(srslte_ue_sync_t *q, cf_t *input_buffer[SRSLTE
}
if (q->correct_cfo) {
for (int i=0;i<q->nof_rx_antennas;i++) {
srslte_cfo_correct(&q->sfind.cfocorr,
srslte_cfo_correct(&q->strack.cfocorr,
input_buffer[i],
input_buffer[i],
-srslte_sync_get_cfo(&q->strack) / q->fft_size);

View File

@ -36,22 +36,22 @@
#define CURRENT_SLOTLEN_RE SRSLTE_SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define CURRENT_SFLEN_RE SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define MAX_SFLEN SRSLTE_SF_LEN(srslte_symbol_sz(max_prb))
int srslte_ue_ul_init(srslte_ue_ul_t *q,
srslte_cell_t cell)
#define DEFAULT_CFO_TOL 50.0 // Hz
int srslte_ue_ul_init(srslte_ue_ul_t *q,
uint32_t max_prb)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
srslte_cell_isvalid(&cell))
if (q != NULL)
{
ret = SRSLTE_ERROR;
bzero(q, sizeof(srslte_ue_ul_t));
q->cell = cell;
if (srslte_ofdm_tx_init(&q->fft, q->cell.cp, q->cell.nof_prb)) {
if (srslte_ofdm_tx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) {
fprintf(stderr, "Error initiating FFT\n");
goto clean_exit;
}
@ -60,41 +60,41 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
q->normalize_en = false;
if (srslte_cfo_init(&q->cfo, CURRENT_SFLEN)) {
if (srslte_cfo_init(&q->cfo, MAX_SFLEN)) {
fprintf(stderr, "Error creating CFO object\n");
goto clean_exit;
}
srslte_cfo_set_tol(&q->cfo, 0);
if (srslte_pusch_init(&q->pusch, q->cell)) {
srslte_ue_ul_set_cfo_tol(q, DEFAULT_CFO_TOL);
if (srslte_pusch_init_ue(&q->pusch, max_prb)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit;
}
if (srslte_pucch_init(&q->pucch, q->cell)) {
if (srslte_pucch_init(&q->pucch)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit;
}
if (srslte_softbuffer_tx_init(&q->softbuffer, q->cell.nof_prb)) {
if (srslte_softbuffer_tx_init(&q->softbuffer, max_prb)) {
fprintf(stderr, "Error initiating soft buffer\n");
goto clean_exit;
}
if (srslte_refsignal_ul_init(&q->signals, cell)) {
if (srslte_refsignal_ul_init(&q->signals, max_prb)) {
fprintf(stderr, "Error initiating srslte_refsignal_ul\n");
goto clean_exit;
}
q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_PRB(max_prb) * sizeof(cf_t));
if (!q->sf_symbols) {
perror("malloc");
goto clean_exit;
}
q->refsignal = srslte_vec_malloc(2 * SRSLTE_NRE * q->cell.nof_prb * sizeof(cf_t));
q->refsignal = srslte_vec_malloc(2 * SRSLTE_NRE * max_prb * sizeof(cf_t));
if (!q->refsignal) {
perror("malloc");
goto clean_exit;
}
q->srs_signal = srslte_vec_malloc(SRSLTE_NRE * q->cell.nof_prb * sizeof(cf_t));
q->srs_signal = srslte_vec_malloc(SRSLTE_NRE * max_prb * sizeof(cf_t));
if (!q->srs_signal) {
perror("malloc");
goto clean_exit;
@ -102,8 +102,7 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
q->signals_pregenerated = false;
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
fprintf(stderr, "Invalid parameters\n");
}
clean_exit:
@ -115,7 +114,7 @@ clean_exit:
void srslte_ue_ul_free(srslte_ue_ul_t *q) {
if (q) {
srslte_ofdm_rx_free(&q->fft);
srslte_ofdm_tx_free(&q->fft);
srslte_pusch_free(&q->pusch);
srslte_pucch_free(&q->pucch);
srslte_softbuffer_tx_free(&q->softbuffer);
@ -140,6 +139,54 @@ void srslte_ue_ul_free(srslte_ue_ul_t *q) {
}
}
int srslte_ue_ul_set_cell(srslte_ue_ul_t *q,
srslte_cell_t cell)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL && srslte_cell_isvalid(&cell))
{
if (q->cell.id != cell.id || q->cell.nof_prb == 0) {
memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
if (srslte_ofdm_tx_set_prb(&q->fft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error resizing FFT\n");
return SRSLTE_ERROR;
}
if (srslte_cfo_resize(&q->cfo, SRSLTE_SF_LEN_PRB(q->cell.nof_prb))) {
fprintf(stderr, "Error resizing CFO object\n");
return SRSLTE_ERROR;
}
srslte_ue_ul_set_cfo_tol(q, q->current_cfo_tol);
if (srslte_pusch_set_cell(&q->pusch, q->cell)) {
fprintf(stderr, "Error resizing PUSCH object\n");
return SRSLTE_ERROR;
}
if (srslte_pucch_set_cell(&q->pucch, q->cell)) {
fprintf(stderr, "Error resizing PUSCH object\n");
return SRSLTE_ERROR;
}
if (srslte_refsignal_ul_set_cell(&q->signals, q->cell)) {
fprintf(stderr, "Error resizing srslte_refsignal_ul\n");
return SRSLTE_ERROR;
}
q->signals_pregenerated = false;
}
ret = SRSLTE_SUCCESS;
} else {
fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n",
cell.id, cell.nof_ports, cell.nof_prb);
}
return ret;
}
void srslte_ue_ul_set_cfo_tol(srslte_ue_ul_t *q, float tol) {
q->current_cfo_tol = tol;
srslte_cfo_set_tol(&q->cfo, tol/(15000.0*srslte_symbol_sz(q->cell.nof_prb)));
}
void srslte_ue_ul_set_cfo(srslte_ue_ul_t *q, float cur_cfo) {
q->current_cfo = cur_cfo;
}
@ -154,7 +201,7 @@ void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q, bool enabled)
q->normalize_en = enabled;
}
/* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while
/* Precalculate the PUSCH scramble sequences for a given RNTI. This function takes a while
* to execute, so shall be called once the final C-RNTI has been allocated for the session.
* For the connection procedure, use srslte_pusch_encode_rnti() or srslte_pusch_decode_rnti() functions
*/
@ -230,6 +277,14 @@ void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format
pucch_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 1a
}
if (format >= SRSLTE_PUCCH_FORMAT_2) {
/* Append Differential CQI */
memcpy(&uci_data->uci_cqi[uci_data->uci_cqi_len], uci_data->uci_dif_cqi, uci_data->uci_dif_cqi_len);
uci_data->uci_cqi_len += uci_data->uci_dif_cqi_len;
/* Append PMI */
memcpy(&uci_data->uci_cqi[uci_data->uci_cqi_len], uci_data->uci_pmi, uci_data->uci_pmi_len);
uci_data->uci_cqi_len += uci_data->uci_pmi_len;
srslte_uci_encode_cqi_pucch(uci_data->uci_cqi, uci_data->uci_cqi_len, pucch_bits);
if (format > SRSLTE_PUCCH_FORMAT_2) {
pucch2_bits[0] = uci_data->uci_ack;
@ -295,7 +350,7 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal);
if (q->cfo_en) {
srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));
srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));
}
if (q->normalize_en) {
@ -365,7 +420,7 @@ int srslte_ue_ul_srs_encode(srslte_ue_ul_t *q, uint32_t tti, cf_t *output_signal
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal);
if (q->cfo_en) {
srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));
srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));
}
if (q->normalize_en) {
@ -407,7 +462,7 @@ int srslte_ue_ul_pusch_encode_rnti_softbuffer(srslte_ue_ul_t *q,
q->pusch_cfg.grant.n_prb_tilde,
q->sf_symbols);
} else {
if (srslte_refsignal_dmrs_pusch_gen(&q->signals, q->pusch_cfg.grant.L_prb,
q->pusch_cfg.sf_idx,
q->pusch_cfg.grant.ncs_dmrs,
@ -434,7 +489,7 @@ int srslte_ue_ul_pusch_encode_rnti_softbuffer(srslte_ue_ul_t *q,
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal);
if (q->cfo_en) {
srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));
srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));
}
if (q->normalize_en) {

View File

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

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