diff --git a/lib/examples/cell_measurement.c b/lib/examples/cell_measurement.c index 37796682f..bfb8194df 100644 --- a/lib/examples/cell_measurement.c +++ b/lib/examples/cell_measurement.c @@ -249,7 +249,7 @@ int main(int argc, char **argv) { fprintf(stderr, "Error initiating ue_sync\n"); return -1; } - if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) { + if (srslte_ue_dl_init(&ue_dl, sf_buffer, cell.nof_prb, 1)) { fprintf(stderr, "Error initiating UE downlink processing module\n"); return -1; } @@ -257,7 +257,7 @@ int main(int argc, char **argv) { fprintf(stderr, "Error initiating UE downlink processing module\n"); return -1; } - if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) { + if (srslte_ue_mib_init(&ue_mib, sf_buffer, cell.nof_prb)) { fprintf(stderr, "Error initaiting UE MIB decoder\n"); return -1; } @@ -271,8 +271,16 @@ int main(int argc, char **argv) { /* Initialize subframe counter */ sf_cnt = 0; - - if (srslte_ofdm_rx_init(&fft, cell.cp, cell.nof_prb)) { + + int sf_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp); + + cf_t *sf_symbols = srslte_vec_malloc(sf_re * sizeof(cf_t)); + + for (int i=0;i class metrics_listener { public: - virtual void set_metrics(metrics_t &m, float report_period_secs=1.0) = 0; -}; + virtual void set_metrics(metrics_t &m) = 0; +}; template class metrics_hub : public periodic_thread { public: - metrics_hub() { - m = NULL; - } - bool init(metrics_interface *m_, float report_period_secs=1.0) { - m = m_; + metrics_hub() + :m(NULL) + ,report_period_secs(1) + {} + bool init(metrics_interface *m_, float report_period_secs_=1.0) { + m = m_; + report_period_secs = report_period_secs_; start_periodic(report_period_secs*1e6); return true; } @@ -60,8 +62,8 @@ private: } } metrics_interface *m; - std::vector*> listeners; - + std::vector*> listeners; + float report_period_secs; }; } // namespace srslte diff --git a/lib/include/srslte/common/pcap.h b/lib/include/srslte/common/pcap.h index d9937c060..db1dc17d0 100644 --- a/lib/include/srslte/common/pcap.h +++ b/lib/include/srslte/common/pcap.h @@ -80,8 +80,9 @@ typedef struct pcaprec_hdr_s { #define MAC_LTE_UEID_TAG 0x03 /* 2 bytes, network order */ -#define MAC_LTE_SUBFRAME_TAG 0x04 +#define MAC_LTE_FRAME_SUBFRAME_TAG 0x04 /* 2 bytes, network order */ +/* SFN is stored in 12 MSB and SF in 4 LSB */ #define MAC_LTE_PREDFINED_DATA_TAG 0x05 /* 1 byte */ @@ -150,7 +151,7 @@ inline int MAC_LTE_PCAP_WritePDU(FILE *fd, MAC_Context_Info_t *context, pcaprec_hdr_t packet_header; char context_header[256]; int offset = 0; - unsigned short tmp16; + uint16_t tmp16; /* Can't write if file wasn't successfully opened */ if (fd == NULL) { @@ -176,9 +177,11 @@ inline int MAC_LTE_PCAP_WritePDU(FILE *fd, MAC_Context_Info_t *context, memcpy(context_header+offset, &tmp16, 2); offset += 2; - /* Subframe number */ - context_header[offset++] = MAC_LTE_SUBFRAME_TAG; - tmp16 = htons(context->subFrameNumber); + /* Subframe Number and System Frame Number */ + /* SFN is stored in 12 MSB and SF in 4 LSB */ + context_header[offset++] = MAC_LTE_FRAME_SUBFRAME_TAG; + tmp16 = (context->sysFrameNumber << 4) | context->subFrameNumber; + tmp16 = htons(tmp16); memcpy(context_header+offset, &tmp16, 2); offset += 2; @@ -215,4 +218,4 @@ inline void MAC_LTE_PCAP_Close(FILE *fd) fclose(fd); } -#endif /* UEPCAP_H */ \ No newline at end of file +#endif /* UEPCAP_H */ diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 8561ba55c..88dfd285c 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -445,7 +445,8 @@ typedef struct { float snr_ema_coeff; std::string snr_estim_alg; bool cfo_integer_enabled; - float cfo_correct_tol_hz; + float cfo_correct_tol_hz; + float cfo_ema; int time_correct_period; bool sfo_correct_disable; std::string sss_algorithm; diff --git a/lib/include/srslte/phy/common/phy_common.h b/lib/include/srslte/phy/common/phy_common.h index 148a12974..4a1eeb27d 100644 --- a/lib/include/srslte/phy/common/phy_common.h +++ b/lib/include/srslte/phy/common/phy_common.h @@ -101,8 +101,8 @@ typedef enum {SRSLTE_SF_NORM, SRSLTE_SF_MBSFN} srslte_sf_t; #define SRSLTE_CP_ISEXT(cp) (cp==SRSLTE_CP_EXT) #define SRSLTE_CP_NSYMB(cp) (SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_NORM_NSYMB:SRSLTE_CP_EXT_NSYMB) -#define SRSLTE_CP_LEN(symbol_sz, c) ((int) ceil((((float) (c)*(symbol_sz))/2048))) -#define SRSLTE_CP_LEN_NORM(symbol, symbol_sz) ((symbol==0)?SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_0_LEN):SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_LEN)) +#define SRSLTE_CP_LEN(symbol_sz, c) ((int) ceilf((((float) (c)*(symbol_sz))/2048.0f))) +#define SRSLTE_CP_LEN_NORM(symbol, symbol_sz) (((symbol)==0)?SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_0_LEN):SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_NORM_LEN)) #define SRSLTE_CP_LEN_EXT(symbol_sz) (SRSLTE_CP_LEN((symbol_sz),SRSLTE_CP_EXT_LEN)) #define SRSLTE_SLOT_LEN(symbol_sz) (symbol_sz*15/2) @@ -197,7 +197,8 @@ typedef enum SRSLTE_API { SRSLTE_MOD_BPSK = 0, SRSLTE_MOD_QPSK, SRSLTE_MOD_16QAM, - SRSLTE_MOD_64QAM + SRSLTE_MOD_64QAM, + SRSLTE_MOD_LAST } srslte_mod_t; typedef struct SRSLTE_API { diff --git a/lib/include/srslte/phy/dft/dft.h b/lib/include/srslte/phy/dft/dft.h index b7fc663d8..b3dd4378b 100644 --- a/lib/include/srslte/phy/dft/dft.h +++ b/lib/include/srslte/phy/dft/dft.h @@ -63,6 +63,7 @@ typedef struct SRSLTE_API { void *in; // Input buffer void *out; // Output buffer void *p; // DFT plan + bool is_guru; bool forward; // Forward transform? bool mirror; // Shift negative and positive frequencies? bool db; // Provide output in dB? @@ -85,6 +86,17 @@ SRSLTE_API int srslte_dft_plan_c(srslte_dft_plan_t *plan, int dft_points, srslte_dft_dir_t dir); +SRSLTE_API int srslte_dft_plan_guru_c(srslte_dft_plan_t *plan, + int dft_points, + srslte_dft_dir_t dir, + cf_t *in_buffer, + cf_t *out_buffer, + int istride, + int ostride, + int how_many, + int idist, + int odist); + SRSLTE_API int srslte_dft_plan_r(srslte_dft_plan_t *plan, int dft_points, srslte_dft_dir_t dir); @@ -92,6 +104,16 @@ SRSLTE_API int srslte_dft_plan_r(srslte_dft_plan_t *plan, SRSLTE_API int srslte_dft_replan(srslte_dft_plan_t *plan, const int new_dft_points); +SRSLTE_API int srslte_dft_replan_guru_c(srslte_dft_plan_t *plan, + const int new_dft_points, + cf_t *in_buffer, + cf_t *out_buffer, + int istride, + int ostride, + int how_many, + int idist, + int odist); + SRSLTE_API int srslte_dft_replan_c(srslte_dft_plan_t *plan, int new_dft_points); @@ -129,6 +151,8 @@ SRSLTE_API void srslte_dft_run_c(srslte_dft_plan_t *plan, cf_t *in, cf_t *out); +SRSLTE_API void srslte_dft_run_guru_c(srslte_dft_plan_t *plan); + SRSLTE_API void srslte_dft_run_r(srslte_dft_plan_t *plan, float *in, float *out); diff --git a/lib/include/srslte/phy/dft/ofdm.h b/lib/include/srslte/phy/dft/ofdm.h index 1363f5638..cba963ca4 100644 --- a/lib/include/srslte/phy/dft/ofdm.h +++ b/lib/include/srslte/phy/dft/ofdm.h @@ -47,14 +47,18 @@ /* This is common for both directions */ typedef struct SRSLTE_API{ srslte_dft_plan_t fft_plan; + srslte_dft_plan_t fft_plan_sf[2]; uint32_t max_prb; uint32_t nof_symbols; uint32_t symbol_sz; uint32_t nof_guards; uint32_t nof_re; uint32_t slot_sz; + uint32_t sf_sz; srslte_cp_t cp; cf_t *tmp; // for removing zero padding + cf_t *in_buffer; + cf_t *out_buffer; bool mbsfn_subframe; uint32_t mbsfn_guard_len; @@ -69,12 +73,16 @@ typedef struct SRSLTE_API{ SRSLTE_API int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, + cf_t *in_buffer, + cf_t *out_buffer, int symbol_sz, int nof_prb, srslte_dft_dir_t dir); SRSLTE_API int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, + cf_t *in_buffer, + cf_t *out_buffer, int symbol_sz, int nof_prb, srslte_dft_dir_t dir, @@ -82,12 +90,14 @@ SRSLTE_API int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, SRSLTE_API int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp_type, + cf_t *in_buffer, + cf_t *out_buffer, uint32_t nof_prb); - - SRSLTE_API int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp_type, + cf_t *in_buffer, + cf_t *out_buffer, uint32_t max_prb); SRSLTE_API int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q, @@ -100,39 +110,35 @@ SRSLTE_API int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q, SRSLTE_API void srslte_ofdm_rx_free(srslte_ofdm_t *q); -SRSLTE_API void srslte_ofdm_rx_slot(srslte_ofdm_t *q, - cf_t *input, - cf_t *output); - -SRSLTE_API void srslte_ofdm_rx_sf(srslte_ofdm_t *q, - cf_t *input, - cf_t *output); - +SRSLTE_API void srslte_ofdm_rx_slot(srslte_ofdm_t *q, + int slot_in_sf); +SRSLTE_API void srslte_ofdm_rx_sf(srslte_ofdm_t *q); SRSLTE_API int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp_type, + cf_t *in_buffer, + cf_t *out_buffer, uint32_t nof_prb); SRSLTE_API int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, + cf_t *in_buffer, + cf_t *out_buffer, uint32_t nof_prb); SRSLTE_API void srslte_ofdm_tx_free(srslte_ofdm_t *q); -SRSLTE_API void srslte_ofdm_tx_slot(srslte_ofdm_t *q, - cf_t *input, - cf_t *output); +SRSLTE_API void srslte_ofdm_tx_slot(srslte_ofdm_t *q, + int slot_in_sf); SRSLTE_API void srslte_ofdm_tx_slot_mbsfn(srslte_ofdm_t *q, cf_t *input, cf_t *output); -SRSLTE_API void srslte_ofdm_tx_sf(srslte_ofdm_t *q, - cf_t *input, - cf_t *output); +SRSLTE_API void srslte_ofdm_tx_sf(srslte_ofdm_t *q); SRSLTE_API int srslte_ofdm_set_freq_shift(srslte_ofdm_t *q, float freq_shift); @@ -144,4 +150,4 @@ SRSLTE_API void srslte_ofdm_set_non_mbsfn_region(srslte_ofdm_t *q, uint8_t non_mbsfn_region); -#endif \ No newline at end of file +#endif diff --git a/lib/include/srslte/phy/enb/enb_dl.h b/lib/include/srslte/phy/enb/enb_dl.h index 7c3166e5c..8d4f3a73a 100644 --- a/lib/include/srslte/phy/enb/enb_dl.h +++ b/lib/include/srslte/phy/enb/enb_dl.h @@ -68,7 +68,7 @@ typedef struct SRSLTE_API { cf_t *sf_symbols[SRSLTE_MAX_PORTS]; cf_t *slot1_symbols[SRSLTE_MAX_PORTS]; - srslte_ofdm_t ifft; + srslte_ofdm_t ifft[SRSLTE_MAX_PORTS]; srslte_pbch_t pbch; srslte_pcfich_t pcfich; srslte_regs_t regs; @@ -109,7 +109,8 @@ typedef struct { } srslte_enb_dl_phich_t; /* This function shall be called just after the initial synchronization */ -SRSLTE_API int srslte_enb_dl_init(srslte_enb_dl_t *q, +SRSLTE_API int srslte_enb_dl_init(srslte_enb_dl_t *q, + cf_t *out_buffer[SRSLTE_MAX_PORTS], uint32_t max_prb); SRSLTE_API void srslte_enb_dl_free(srslte_enb_dl_t *q); @@ -146,8 +147,7 @@ SRSLTE_API void srslte_enb_dl_put_phich(srslte_enb_dl_t *q, SRSLTE_API void srslte_enb_dl_put_base(srslte_enb_dl_t *q, uint32_t tti); -SRSLTE_API void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q, - cf_t *signal_buffer); +SRSLTE_API void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q); SRSLTE_API int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q, uint16_t rnti); diff --git a/lib/include/srslte/phy/enb/enb_ul.h b/lib/include/srslte/phy/enb/enb_ul.h index 855b645ca..0957ccbc0 100644 --- a/lib/include/srslte/phy/enb/enb_ul.h +++ b/lib/include/srslte/phy/enb/enb_ul.h @@ -101,6 +101,7 @@ typedef struct { /* This function shall be called just after the initial synchronization */ SRSLTE_API int srslte_enb_ul_init(srslte_enb_ul_t *q, + cf_t *in_buffer, uint32_t max_prb); SRSLTE_API void srslte_enb_ul_free(srslte_enb_ul_t *q); diff --git a/lib/include/srslte/phy/phch/pdsch_cfg.h b/lib/include/srslte/phy/phch/pdsch_cfg.h index eb4927fbb..63b3fefcc 100644 --- a/lib/include/srslte/phy/phch/pdsch_cfg.h +++ b/lib/include/srslte/phy/phch/pdsch_cfg.h @@ -48,6 +48,7 @@ typedef struct SRSLTE_API { uint32_t nof_layers; uint32_t codebook_idx; srslte_mimo_type_t mimo_type; + bool tb_cw_swap; } srslte_pdsch_cfg_t; #endif diff --git a/lib/include/srslte/phy/phch/ra.h b/lib/include/srslte/phy/phch/ra.h index 3039455ed..f4274e416 100644 --- a/lib/include/srslte/phy/phch/ra.h +++ b/lib/include/srslte/phy/phch/ra.h @@ -103,13 +103,11 @@ typedef struct SRSLTE_API { bool prb_idx[2][SRSLTE_MAX_PRB]; uint32_t nof_prb; uint32_t Qm[SRSLTE_MAX_CODEWORDS]; - uint32_t Qm2[SRSLTE_MAX_CODEWORDS]; srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS]; - srslte_ra_mcs_t mcs2[SRSLTE_MAX_CODEWORDS]; - uint32_t nof_tb; srslte_sf_t sf_type; bool tb_en[SRSLTE_MAX_CODEWORDS]; uint32_t pinfo; + bool tb_cw_swap; } 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)) @@ -226,8 +224,7 @@ SRSLTE_API uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, SRSLTE_API int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, uint32_t nof_prb, uint32_t n_rb_ho, - srslte_ra_ul_grant_t *grant, - uint32_t harq_pid); + srslte_ra_ul_grant_t *grant); SRSLTE_API void srslte_ra_ul_grant_to_nbits(srslte_ra_ul_grant_t *grant, srslte_cp_t cp, diff --git a/lib/include/srslte/phy/ue/ue_dl.h b/lib/include/srslte/phy/ue/ue_dl.h index 0b0fc44d2..0486ad7d4 100644 --- a/lib/include/srslte/phy/ue/ue_dl.h +++ b/lib/include/srslte/phy/ue/ue_dl.h @@ -80,7 +80,7 @@ typedef struct SRSLTE_API { srslte_pmch_t pmch; srslte_phich_t phich; srslte_regs_t regs; - srslte_ofdm_t fft; + srslte_ofdm_t fft[SRSLTE_MAX_PORTS]; srslte_ofdm_t fft_mbsfn; srslte_chest_dl_t chest; @@ -128,6 +128,7 @@ 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, + cf_t *in_buffer[SRSLTE_MAX_PORTS], uint32_t max_prb, uint32_t nof_rx_antennas); diff --git a/lib/include/srslte/phy/ue/ue_mib.h b/lib/include/srslte/phy/ue/ue_mib.h index 5d2ef14fa..ee52b31d4 100644 --- a/lib/include/srslte/phy/ue/ue_mib.h +++ b/lib/include/srslte/phy/ue/ue_mib.h @@ -79,6 +79,7 @@ typedef struct SRSLTE_API { } srslte_ue_mib_t; SRSLTE_API int srslte_ue_mib_init(srslte_ue_mib_t *q, + cf_t *in_buffer[SRSLTE_MAX_PORTS], uint32_t max_prb); SRSLTE_API void srslte_ue_mib_free(srslte_ue_mib_t *q); @@ -89,7 +90,6 @@ SRSLTE_API int srslte_ue_mib_set_cell(srslte_ue_mib_t * q, SRSLTE_API void srslte_ue_mib_reset(srslte_ue_mib_t * q); SRSLTE_API int srslte_ue_mib_decode(srslte_ue_mib_t * q, - cf_t *input, uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN], uint32_t *nof_tx_ports, int *sfn_offset); diff --git a/lib/include/srslte/phy/ue/ue_sync.h b/lib/include/srslte/phy/ue/ue_sync.h index bd280acd0..e5877dd23 100644 --- a/lib/include/srslte/phy/ue/ue_sync.h +++ b/lib/include/srslte/phy/ue/ue_sync.h @@ -185,7 +185,10 @@ 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); + float cfo); + +SRSLTE_API void srslte_ue_sync_set_cfo_ema(srslte_ue_sync_t *q, + float ema); SRSLTE_API void srslte_ue_sync_cfo_i_detec_en(srslte_ue_sync_t *q, bool enable); diff --git a/lib/include/srslte/phy/ue/ue_ul.h b/lib/include/srslte/phy/ue/ue_ul.h index 3492180e3..617833a61 100644 --- a/lib/include/srslte/phy/ue/ue_ul.h +++ b/lib/include/srslte/phy/ue/ue_ul.h @@ -108,6 +108,7 @@ 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, + cf_t *out_buffer, uint32_t max_prb); SRSLTE_API void srslte_ue_ul_free(srslte_ue_ul_t *q); diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index 08eed115f..09e9cff8e 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -33,6 +33,11 @@ #endif #include #endif /* LV_HAVE_SSE */ +#include + +#ifdef HAVE_NEON +#include +#endif /* * SSE Macros @@ -121,7 +126,17 @@ #define SRSLTE_SIMD_C16_SIZE 8 #else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON +#define SRSLTE_SIMD_F_SIZE 4 +#define SRSLTE_SIMD_CF_SIZE 4 + +#define SRSLTE_SIMD_I_SIZE 4 + +#define SRSLTE_SIMD_S_SIZE 8 +#define SRSLTE_SIMD_C16_SIZE 8 + +#else /* LV_HAVE_NEON */ #define SRSLTE_SIMD_F_SIZE 0 #define SRSLTE_SIMD_CF_SIZE 0 @@ -130,6 +145,7 @@ #define SRSLTE_SIMD_S_SIZE 0 #define SRSLTE_SIMD_C16_SIZE 0 +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -147,6 +163,10 @@ typedef __m256 simd_f_t; #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE typedef __m128 simd_f_t; +#else /* HAVE_NEON */ +#ifdef HAVE_NEON +typedef float32x4_t simd_f_t; +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -161,6 +181,10 @@ static inline simd_f_t srslte_simd_f_load(float *ptr) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_load_ps(ptr); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vld1q_f32(ptr); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -170,11 +194,15 @@ static inline simd_f_t srslte_simd_f_loadu(float *ptr) { #ifdef LV_HAVE_AVX512 return _mm512_loadu_ps(ptr); #else /* LV_HAVE_AVX512 */ - #ifdef LV_HAVE_AVX2 + #ifdef LV_HAVE_AVX2 return _mm256_loadu_ps(ptr); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_loadu_ps(ptr); +#else /* LV_HAVE_SSE */ + #ifdef HAVE_NEON + return vld1q_f32(ptr); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -189,6 +217,10 @@ static inline void srslte_simd_f_store(float *ptr, simd_f_t simdreg) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE _mm_store_ps(ptr, simdreg); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + vst1q_f32(ptr, simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -203,6 +235,10 @@ static inline void srslte_simd_f_storeu(float *ptr, simd_f_t simdreg) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE _mm_storeu_ps(ptr, simdreg); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + vst1q_f32(ptr, simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -217,6 +253,10 @@ static inline simd_f_t srslte_simd_f_set1(float x) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_set1_ps(x); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vdupq_n_f32(x); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -231,6 +271,10 @@ static inline simd_f_t srslte_simd_f_mul(simd_f_t a, simd_f_t b) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_mul_ps(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vmulq_f32(a,b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -243,8 +287,12 @@ static inline simd_f_t srslte_simd_f_rcp(simd_f_t a) { #ifdef LV_HAVE_AVX2 return _mm256_rcp_ps(a); #else /* LV_HAVE_AVX2 */ - #ifdef LV_HAVE_SSE +#ifdef LV_HAVE_SSE return _mm_rcp_ps(a); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vmulq_f32(vrecpeq_f32(a), vrecpsq_f32(vrecpeq_f32(a), a)); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -260,11 +308,30 @@ static inline simd_f_t srslte_simd_f_addsub(simd_f_t a, simd_f_t b) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_addsub_ps(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON // CURRENTLY USES GENERIC IMPLEMENTATION FOR NEON + float* a_ptr = (float*) &a; + float* b_ptr = (float*) &b; + simd_f_t ret; + float* c_ptr = (float*) &ret; + for(int i = 0; i<4;i++){ + if(i%2==0){ + c_ptr[i] = a_ptr[i] - b_ptr[i]; + }else{ + c_ptr[i] = a_ptr[i] + b_ptr[i]; + } + } + + return ret; +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ } + + + static inline simd_f_t srslte_simd_f_sub(simd_f_t a, simd_f_t b) { #ifdef LV_HAVE_AVX512 return _mm512_sub_ps(a, b); @@ -274,6 +341,10 @@ static inline simd_f_t srslte_simd_f_sub(simd_f_t a, simd_f_t b) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_sub_ps(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vsubq_f32(a, b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -286,8 +357,12 @@ static inline simd_f_t srslte_simd_f_add(simd_f_t a, simd_f_t b) { #ifdef LV_HAVE_AVX2 return _mm256_add_ps(a, b); #else /* LV_HAVE_AVX2 */ -#ifdef LV_HAVE_SSE +#ifdef LV_HAVE_SSE return _mm_add_ps(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vaddq_f32(a, b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -300,8 +375,12 @@ static inline simd_f_t srslte_simd_f_zero (void) { #ifdef LV_HAVE_AVX2 return _mm256_setzero_ps(); #else /* LV_HAVE_AVX2 */ -#ifdef LV_HAVE_SSE +#ifdef LV_HAVE_SSE return _mm_setzero_ps(); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vdupq_n_f32(0); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -316,6 +395,10 @@ static inline simd_f_t srslte_simd_f_swap(simd_f_t a) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_shuffle_ps(a, a, 0b10110001); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vcombine_f32(vrev64_f32(vget_low_f32(a)), vrev64_f32(vget_high_f32(a))); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -344,6 +427,10 @@ static inline simd_f_t srslte_simd_f_hadd(simd_f_t a, simd_f_t b) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_hadd_ps(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vcombine_f32( vpadd_f32( vget_low_f32(a), vget_high_f32(a) ), vpadd_f32( vget_low_f32(b), vget_high_f32(b) ) ); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -358,6 +445,12 @@ static inline simd_f_t srslte_simd_f_sqrt(simd_f_t a) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_sqrt_ps(a); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + float32x4_t sqrt_reciprocal = vrsqrteq_f32(a); + sqrt_reciprocal = vmulq_f32(vrsqrtsq_f32(vmulq_f32(a,sqrt_reciprocal), sqrt_reciprocal),sqrt_reciprocal); + return vmulq_f32(a,sqrt_reciprocal); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -368,10 +461,15 @@ static inline simd_f_t srslte_simd_f_sqrt(simd_f_t a) { #if SRSLTE_SIMD_CF_SIZE +#ifdef HAVE_NEON + typedef float32x4x2_t simd_cf_t; +#else typedef struct { simd_f_t re; simd_f_t im; + } simd_cf_t; +#endif /* Complex Single precission Floating point functions */ static inline simd_cf_t srslte_simd_cfi_load(cf_t *ptr) { @@ -399,6 +497,10 @@ static inline simd_cf_t srslte_simd_cfi_load(cf_t *ptr) { __m128 i2 = _mm_load_ps((float*)(ptr + 2)); ret.re = _mm_shuffle_ps(i1, i2, _MM_SHUFFLE(2,0,2,0)); ret.im = _mm_shuffle_ps(i1, i2, _MM_SHUFFLE(3,1,3,1)); +#else +#ifdef HAVE_NEON + ret = vld2q_f32((float*)(ptr)); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -431,6 +533,10 @@ static inline simd_cf_t srslte_simd_cfi_loadu(cf_t *ptr) { __m128 i2 = _mm_loadu_ps((float*)(ptr + 2)); ret.re = _mm_shuffle_ps(i1, i2, _MM_SHUFFLE(2,0,2,0)); ret.im = _mm_shuffle_ps(i1, i2, _MM_SHUFFLE(3,1,3,1)); +#else +#ifdef HAVE_NEON + ret = vld2q_f32((float*)(ptr)); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -450,6 +556,11 @@ static inline simd_cf_t srslte_simd_cf_load(float *re, float *im) { #ifdef LV_HAVE_SSE ret.re = _mm_load_ps(re); ret.im = _mm_load_ps(im); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + ret.val[0] = vld1q_f32(re); + ret.val[1] = vld1q_f32(im); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -469,6 +580,11 @@ static inline simd_cf_t srslte_simd_cf_loadu(float *re, float *im) { #ifdef LV_HAVE_SSE ret.re = _mm_loadu_ps(re); ret.im = _mm_loadu_ps(im); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + ret.val[0] = vld1q_f32(re); + ret.val[1] = vld1q_f32(im); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -497,6 +613,10 @@ static inline void srslte_simd_cfi_store(cf_t *ptr, simd_cf_t simdreg) { #ifdef LV_HAVE_SSE _mm_store_ps((float*)(ptr), _mm_unpacklo_ps(simdreg.re, simdreg.im)); _mm_store_ps((float*)(ptr + 2), _mm_unpackhi_ps(simdreg.re, simdreg.im)); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + vst2q_f32((float*)(ptr), simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -524,6 +644,10 @@ static inline void srslte_simd_cfi_storeu(cf_t *ptr, simd_cf_t simdreg) { #ifdef LV_HAVE_SSE _mm_storeu_ps((float*)(ptr), _mm_unpacklo_ps(simdreg.re, simdreg.im)); _mm_storeu_ps((float*)(ptr + 2), _mm_unpackhi_ps(simdreg.re, simdreg.im)); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + vst2q_f32((float*)(ptr), simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -541,6 +665,11 @@ static inline void srslte_simd_cf_store(float *re, float *im, simd_cf_t simdreg) #ifdef LV_HAVE_SSE _mm_store_ps((float *) re, simdreg.re); _mm_store_ps((float *) im, simdreg.im); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + vst1q_f32((float *) re, simdreg.val[0]); + vst1q_f32((float *) im, simdreg.val[1]); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -558,6 +687,11 @@ static inline void srslte_simd_cf_storeu(float *re, float *im, simd_cf_t simdreg #ifdef LV_HAVE_SSE _mm_storeu_ps((float *) re, simdreg.re); _mm_storeu_ps((float *) im, simdreg.im); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + vst1q_f32((float *) re, simdreg.val[0]); + vst1q_f32((float *) im, simdreg.val[1]); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -576,6 +710,11 @@ static inline simd_cf_t srslte_simd_cf_set1 (cf_t x) { #ifdef LV_HAVE_SSE ret.re = _mm_set1_ps(__real__ x); ret.im = _mm_set1_ps(__imag__ x); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + ret.val[0] = vdupq_n_f32(__real__ x); + ret.val[1] = vdupq_n_f32(__imag__ x); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -601,6 +740,13 @@ static inline simd_cf_t srslte_simd_cf_prod (simd_cf_t a, simd_cf_t b) { _mm_mul_ps(a.im, b.im)); ret.im = _mm_add_ps(_mm_mul_ps(a.re, b.im), _mm_mul_ps(a.im, b.re)); +#else +#ifdef HAVE_NEON + ret.val[0] = vsubq_f32(vmulq_f32(a.val[0],b.val[0]), + vmulq_f32(a.val[1],b.val[1])); + ret.val[1] = vaddq_f32(vmulq_f32(a.val[0],b.val[1]), + vmulq_f32(a.val[1],b.val[0])); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -626,6 +772,13 @@ static inline simd_cf_t srslte_simd_cf_conjprod (simd_cf_t a, simd_cf_t b) { _mm_mul_ps(a.im, b.im)); ret.im = _mm_sub_ps(_mm_mul_ps(a.im, b.re), _mm_mul_ps(a.re, b.im)); + #else +#ifdef HAVE_NEON + ret.val[0] = vaddq_f32(vmulq_f32(a.val[0],b.val[0]), + vmulq_f32(a.val[1],b.val[1])); + ret.val[1] = vsubq_f32(vmulq_f32(a.val[1],b.val[0]), + vmulq_f32(a.val[0],b.val[1])); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -645,6 +798,11 @@ static inline simd_cf_t srslte_simd_cf_add (simd_cf_t a, simd_cf_t b) { #ifdef LV_HAVE_SSE ret.re = _mm_add_ps(a.re, b.re); ret.im = _mm_add_ps(a.im, b.im); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + ret.val[0] = vaddq_f32(a.val[0],b.val[0]); + ret.val[1] = vaddq_f32(a.val[1],b.val[1]); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -665,6 +823,11 @@ static inline simd_cf_t srslte_simd_cf_mul (simd_cf_t a, simd_f_t b) { #ifdef LV_HAVE_SSE ret.re = _mm_mul_ps(a.re, b); ret.im = _mm_mul_ps(a.im, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + ret.val[0] = vmulq_f32(a.val[0],b); + ret.val[1] = vmulq_f32(a.val[1],b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -699,6 +862,16 @@ static inline simd_cf_t srslte_simd_cf_rcp (simd_cf_t a) { simd_f_t neg_a_im = _mm_xor_ps(_mm_set1_ps(-0.0f), a.im); ret.re = _mm_mul_ps(a.re, rcp); ret.im = _mm_mul_ps(neg_a_im, rcp); + #else /* LV_HAVE_SSE */ + #ifdef HAVE_NEON + simd_f_t a2re = vmulq_f32(a.val[0], a.val[0]); + simd_f_t a2im = vmulq_f32(a.val[1], a.val[1]); + simd_f_t mod2 = vaddq_f32(a2re, a2im); + simd_f_t rcp = vmulq_f32(vrecpeq_f32(mod2), vrecpsq_f32(vrecpeq_f32(mod2), mod2)); + simd_f_t neg_a_im = vnegq_f32(a.val[1]); + ret.val[0] = vmulq_f32(a.val[0], rcp); + ret.val[1] = vmulq_f32(neg_a_im, rcp); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -718,7 +891,12 @@ static inline simd_cf_t srslte_simd_cf_zero (void) { #ifdef LV_HAVE_SSE ret.re = _mm_setzero_ps(); ret.im = _mm_setzero_ps(); -#endif /* LV_HAVE_SSE */ +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + ret.val[0] = vdupq_n_f32(0); + ret.val[1] = vdupq_n_f32(0); +#endif /* HAVE_NEON */ +#endif /* HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ return ret; @@ -739,6 +917,11 @@ typedef __m256 simd_sel_t; #ifdef LV_HAVE_SSE typedef __m128i simd_i_t; typedef __m128 simd_sel_t; +#else /* LV_HAVE_AVX2 */ +#ifdef HAVE_NEON +typedef int32x4_t simd_i_t; +typedef int32x4_t simd_sel_t; +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -752,6 +935,10 @@ static inline simd_i_t srslte_simd_i_load(int *x) { #else #ifdef LV_HAVE_SSE return _mm_load_si128((__m128i*)x); +#else + #ifdef HAVE_NEON + return vld1q_s32((int*)x); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -766,6 +953,10 @@ static inline void srslte_simd_i_store(int *x, simd_i_t reg) { #else #ifdef LV_HAVE_SSE _mm_store_si128((__m128i*)x, reg); +#else +#ifdef HAVE_NEON + vst1q_s32((int*)x, reg); +#endif /*HAVE_NEON*/ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -780,6 +971,10 @@ static inline simd_i_t srslte_simd_i_set1(int x) { #else #ifdef LV_HAVE_SSE return _mm_set1_epi32(x); +#else + #ifdef HAVE_NEON + return vdupq_n_s32(x); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -794,6 +989,10 @@ static inline simd_i_t srslte_simd_i_add(simd_i_t a, simd_i_t b) { #else #ifdef LV_HAVE_SSE return _mm_add_epi32(a, b); +#else +#ifdef HAVE_NEON + return vaddq_s32(a, b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -808,6 +1007,10 @@ static inline simd_sel_t srslte_simd_f_max(simd_f_t a, simd_f_t b) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return (simd_sel_t) _mm_cmpgt_ps(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return (simd_sel_t) vcgtq_f32(a, b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -822,6 +1025,23 @@ static inline simd_i_t srslte_simd_i_select(simd_i_t a, simd_i_t b, simd_sel_t s #else #ifdef LV_HAVE_SSE return (__m128i) _mm_blendv_ps((__m128)a, (__m128)b, selector); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON // CURRENTLY USES GENERIC IMPLEMENTATION FOR NEON + int* a_ptr = (int*) &a; + int* b_ptr = (int*) &b; + simd_i_t ret; + int* sel = (int*) &selector; + int* c_ptr = (int*) &ret; + for(int i = 0;i<4;i++) + { + if(sel[i] == -1){ + c_ptr[i] = b_ptr[i]; + }else{ + c_ptr[i] = a_ptr[i]; + } + } + return ret; +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -841,6 +1061,10 @@ typedef __m256i simd_s_t; #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE typedef __m128i simd_s_t; +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON +typedef int16x8_t simd_s_t; +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -854,6 +1078,10 @@ static inline simd_s_t srslte_simd_s_load(int16_t *ptr) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_load_si128((__m128i*) ptr); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vld1q_s16(ptr); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -868,6 +1096,10 @@ static inline simd_s_t srslte_simd_s_loadu(int16_t *ptr) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_loadu_si128((__m128i*) ptr); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vld1q_s16(ptr); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -882,6 +1114,10 @@ static inline void srslte_simd_s_store(int16_t *ptr, simd_s_t simdreg) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE _mm_store_si128((__m128i*) ptr, simdreg); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + vst1q_s16( ptr, simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -896,11 +1132,14 @@ static inline void srslte_simd_s_storeu(int16_t *ptr, simd_s_t simdreg) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE _mm_storeu_si128((__m128i*) ptr, simdreg); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + vst1q_s16(ptr, simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ } - static inline simd_s_t srslte_simd_s_zero(void) { #ifdef LV_HAVE_AVX512 return _mm512_setzero_si512(); @@ -910,6 +1149,10 @@ static inline simd_s_t srslte_simd_s_zero(void) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_setzero_si128(); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vdupq_n_s16(0); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -924,6 +1167,10 @@ static inline simd_s_t srslte_simd_s_mul(simd_s_t a, simd_s_t b) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_mullo_epi16(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vmulq_s16(a, b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -938,6 +1185,10 @@ static inline simd_s_t srslte_simd_s_add(simd_s_t a, simd_s_t b) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_add_epi16(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vaddq_s16(a, b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -952,6 +1203,10 @@ static inline simd_s_t srslte_simd_s_sub(simd_s_t a, simd_s_t b) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_sub_epi16(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vsubq_s16(a, b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -962,8 +1217,9 @@ static inline simd_s_t srslte_simd_s_sub(simd_s_t a, simd_s_t b) { #if SRSLTE_SIMD_C16_SIZE -typedef struct { +typedef #ifdef LV_HAVE_AVX512 + struct { union { __m512i m512; int16_t i16[32]; @@ -974,24 +1230,32 @@ typedef struct { } im; #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 - union { - __m256i m256; - int16_t i16[16]; - } re; - union { - __m256i m256; - int16_t i16[16]; - } im; + struct { + union { + __m256i m256; + int16_t i16[16]; + } re; + union { + __m256i m256; + int16_t i16[16]; + } im; #else #ifdef LV_HAVE_SSE - union { - __m128i m128; - int16_t i16[8]; - } re; - union { - __m128i m128; - int16_t i16[8]; - } im; + struct { + union { + __m128i m128; + int16_t i16[8]; + } re; + union { + __m128i m128; + int16_t i16[8]; + } im; +#else +#ifdef HAVE_NEON + union { + int16x8x2_t m128; + int16_t i16[16]; +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -1017,6 +1281,10 @@ static inline simd_c16_t srslte_simd_c16i_load(c16_t *ptr) { __m128i in2 = _mm_load_si128((__m128i*)(ptr + 8)); ret.re.m128 = _mm_blend_epi16(in1,_mm_shufflelo_epi16(_mm_shufflehi_epi16(in2, 0b10100000), 0b10100000), 0b10101010); ret.im.m128 = _mm_blend_epi16(_mm_shufflelo_epi16(_mm_shufflehi_epi16(in1, 0b11110101), 0b11110101),in2, 0b10101010); +#else /* LV_HAVE_SSE*/ +#ifdef HAVE_NEON + ret.m128 = vld2q_s16((int16_t*)(ptr)); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -1032,6 +1300,11 @@ static inline simd_c16_t srslte_simd_c16_load(int16_t *re, int16_t *im) { #ifdef LV_HAVE_SSE ret.re.m128 = _mm_load_si128((__m128i*)(re)); ret.im.m128 = _mm_load_si128((__m128i*)(im)); +#else /* LV_HAVE_SSE*/ +#ifdef HAVE_NEON + ret.m128.val[0] = vld1q_s16((int16_t*)(re)); + ret.m128.val[1] = vld1q_s16((int16_t*)(im)); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ return ret; @@ -1046,6 +1319,11 @@ static inline simd_c16_t srslte_simd_c16_loadu(int16_t *re, int16_t *im) { #ifdef LV_HAVE_SSE ret.re.m128 = _mm_loadu_si128((__m128i*)(re)); ret.im.m128 = _mm_loadu_si128((__m128i*)(im)); +#else /* LV_HAVE_SSE*/ +#ifdef HAVE_NEON + ret.m128.val[0] = vld1q_s16((int16_t*)(re)); + ret.m128.val[1] = vld1q_s16((int16_t*)(im)); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ return ret; @@ -1063,6 +1341,10 @@ static inline void srslte_simd_c16i_store(c16_t *ptr, simd_c16_t simdreg) { __m128i im_sw = _mm_shufflelo_epi16(_mm_shufflehi_epi16(simdreg.im.m128, 0b10110001), 0b10110001); _mm_store_si128((__m128i *) (ptr), _mm_blend_epi16(simdreg.re.m128, im_sw, 0b10101010)); _mm_store_si128((__m128i *) (ptr + 8), _mm_blend_epi16(re_sw, simdreg.im.m128, 0b10101010)); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + vst2q_s16((int16_t*)(ptr) ,simdreg.m128); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ } @@ -1079,6 +1361,10 @@ static inline void srslte_simd_c16i_storeu(c16_t *ptr, simd_c16_t simdreg) { __m128i im_sw = _mm_shufflelo_epi16(_mm_shufflehi_epi16(simdreg.im.m128, 0b10110001), 0b10110001); _mm_storeu_si128((__m128i *) (ptr), _mm_blend_epi16(simdreg.re.m128, im_sw, 0b10101010)); _mm_storeu_si128((__m128i *) (ptr + 8), _mm_blend_epi16(re_sw, simdreg.im.m128, 0b10101010)); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + vst2q_s16((int16_t*)(ptr) ,simdreg.m128); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ } @@ -1091,6 +1377,11 @@ static inline void srslte_simd_c16_store(int16_t *re, int16_t *im, simd_c16_t si #ifdef LV_HAVE_SSE _mm_store_si128((__m128i *) re, simdreg.re.m128); _mm_store_si128((__m128i *) im, simdreg.im.m128); +#else +#ifdef HAVE_NEON + vst1q_s16((int16_t *) re, simdreg.m128.val[0]); + vst1q_s16((int16_t *) im, simdreg.m128.val[1]); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ } @@ -1103,6 +1394,11 @@ static inline void srslte_simd_c16_storeu(int16_t *re, int16_t *im, simd_c16_t s #ifdef LV_HAVE_SSE _mm_storeu_si128((__m128i *) re, simdreg.re.m128); _mm_storeu_si128((__m128i *) im, simdreg.im.m128); +#else +#ifdef HAVE_NEON + vst1q_s16((int16_t *) re, simdreg.m128.val[0]); + vst1q_s16((int16_t *) im, simdreg.m128.val[1]); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ } @@ -1134,6 +1430,11 @@ static inline simd_c16_t srslte_simd_c16_add (simd_c16_t a, simd_c16_t b) { #ifdef LV_HAVE_SSE ret.re.m128 = _mm_add_epi16(a.re.m128, b.re.m128); ret.im.m128 = _mm_add_epi16(a.im.m128, b.im.m128); +#else +#ifdef HAVE_NEON + ret.m128.val[0] = vaddq_s16(a.m128.val[0],a.m128.val[0]); + ret.m128.val[1] = vaddq_s16(a.m128.val[1],a.m128.val[1]); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ return ret; @@ -1148,7 +1449,12 @@ static inline simd_c16_t srslte_simd_c16_zero (void) { #ifdef LV_HAVE_SSE ret.re.m128 = _mm_setzero_si128(); ret.im.m128 = _mm_setzero_si128(); -#endif /* LV_HAVE_SSE */ +#else +#ifdef HAVE_NEON + ret.m128.val[0] = vdupq_n_s16(0); + ret.m128.val[1] = vdupq_n_s16(0); +#endif /* HAVE_NEON */ +#endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ return ret; } @@ -1182,6 +1488,12 @@ static inline simd_s_t srslte_simd_convert_2f_s(simd_f_t a, simd_f_t b) { __m128i ai = _mm_cvttps_epi32(a); __m128i bi = _mm_cvttps_epi32(b); return _mm_packs_epi32(ai, bi); + #else +#ifdef HAVE_NEON + int32x4_t ai = vcvtq_s32_f32(a); + int32x4_t bi = vcvtq_s32_f32(b); + return (simd_s_t)vcombine_s16(vqmovn_s32(ai), vqmovn_s32(bi)); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ diff --git a/lib/include/srslte/upper/rlc_am.h b/lib/include/srslte/upper/rlc_am.h index afbd18544..cee0d5959 100644 --- a/lib/include/srslte/upper/rlc_am.h +++ b/lib/include/srslte/upper/rlc_am.h @@ -163,6 +163,8 @@ private: static const int reordering_timeout_id = 1; + static const int poll_periodicity = 8; // After how many data PDUs a status PDU shall be requested + // Timer checks bool status_prohibited(); bool poll_retx(); diff --git a/lib/src/asn1/liblte_rrc.cc b/lib/src/asn1/liblte_rrc.cc index e4621994e..c53399384 100644 --- a/lib/src/asn1/liblte_rrc.cc +++ b/lib/src/asn1/liblte_rrc.cc @@ -4764,6 +4764,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_plmn_identity_ie(LIBLTE_RRC_PLMN_IDENTITY_STRU if(plmn_id != NULL && ie_ptr != NULL) { + if(0xFFFF == plmn_id->mcc) { + mcc_opt = false; + } liblte_value_2_bits(mcc_opt, ie_ptr, 1); if(true == mcc_opt) @@ -12754,7 +12757,241 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_paging_msg(LIBLTE_BIT_MSG_STRUCT *msg, Document Reference: 36.331 v10.0.0 Section 6.2.2 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_cgi_info_ie(LIBLTE_RRC_CGI_INFO_STRUCT *cgi_info, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(cgi_info != NULL && + ie_ptr != NULL) + { + liblte_value_2_bits(cgi_info->have_plmn_identity_list, ie_ptr, 1); + liblte_rrc_pack_cell_global_id_eutra_ie(&cgi_info->cell_global_id, ie_ptr); + liblte_rrc_pack_tracking_area_code_ie(cgi_info->tracking_area_code, ie_ptr); + if(cgi_info->have_plmn_identity_list) { + liblte_value_2_bits(cgi_info->n_plmn_identity_list-1, ie_ptr, 3); + for(uint32 i=0; in_plmn_identity_list; i++) { + liblte_rrc_pack_plmn_identity_ie(&cgi_info->plmn_identity_list[i], ie_ptr); + } + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_cgi_info_ie(uint8 **ie_ptr, + LIBLTE_RRC_CGI_INFO_STRUCT *cgi_info) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + cgi_info != NULL) + { + cgi_info->have_plmn_identity_list = (bool)liblte_bits_2_value(ie_ptr, 1); + liblte_rrc_unpack_cell_global_id_eutra_ie(ie_ptr, &cgi_info->cell_global_id); + liblte_rrc_unpack_tracking_area_code_ie(ie_ptr, &cgi_info->tracking_area_code); + if(cgi_info->have_plmn_identity_list) { + cgi_info->n_plmn_identity_list = liblte_bits_2_value(ie_ptr, 3) + 1; + for(uint32 i=0; in_plmn_identity_list; i++) { + liblte_rrc_unpack_plmn_identity_ie(ie_ptr, &cgi_info->plmn_identity_list[i]); + } + } + err = LIBLTE_SUCCESS; + } + + return(err); +} + +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_result_ie(LIBLTE_RRC_MEAS_RESULT_STRUCT *meas_result, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(meas_result != NULL && + ie_ptr != NULL) + { + //ext + liblte_value_2_bits(0, ie_ptr, 1); + + //options + liblte_value_2_bits(meas_result->have_rsrp, ie_ptr, 1); + liblte_value_2_bits(meas_result->have_rsrq, ie_ptr, 1); + + if(meas_result->have_rsrp) { + liblte_rrc_pack_rsrp_range_ie(meas_result->rsrp_result, ie_ptr); + } + if(meas_result->have_rsrq) { + liblte_rrc_pack_rsrq_range_ie(meas_result->rsrq_result, ie_ptr); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_result_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_RESULT_STRUCT *meas_result) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + meas_result != NULL) + { + //ext + bool ext = liblte_bits_2_value(ie_ptr, 1); + + //options + meas_result->have_rsrp = liblte_bits_2_value(ie_ptr, 1); + meas_result->have_rsrq = liblte_bits_2_value(ie_ptr, 1); + + if(meas_result->have_rsrp) { + liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &meas_result->rsrp_result); + } + if(meas_result->have_rsrq) { + liblte_rrc_unpack_rsrq_range_ie(ie_ptr, &meas_result->rsrq_result); + } + + //skip extensions + liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_result_eutra_ie(LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT *meas_result_eutra, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(meas_result_eutra != NULL && + ie_ptr != NULL) + { + liblte_value_2_bits(meas_result_eutra->have_cgi_info, ie_ptr, 1); + liblte_rrc_pack_phys_cell_id_ie(meas_result_eutra->phys_cell_id, ie_ptr); + if(meas_result_eutra->have_cgi_info) { + liblte_rrc_pack_cgi_info_ie(&meas_result_eutra->cgi_info, ie_ptr); + } + liblte_rrc_pack_meas_result_ie(&meas_result_eutra->meas_result, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_result_eutra_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT *meas_result_eutra) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + meas_result_eutra != NULL) + { + meas_result_eutra->have_cgi_info = liblte_bits_2_value(ie_ptr, 1); + liblte_rrc_unpack_phys_cell_id_ie(ie_ptr, &meas_result_eutra->phys_cell_id); + if(meas_result_eutra->have_cgi_info) { + liblte_rrc_unpack_cgi_info_ie(ie_ptr, &meas_result_eutra->cgi_info); + } + liblte_rrc_unpack_meas_result_ie(ie_ptr, &meas_result_eutra->meas_result); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +LIBLTE_ERROR_ENUM liblte_rrc_pack_measurement_report_msg(LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *meas_report, + LIBLTE_BIT_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(meas_report != NULL && + msg != NULL) + { + //MeasurementReport + liblte_value_2_bits(0, &msg_ptr, 1); //critical extensions + liblte_value_2_bits(0, &msg_ptr, 3); //c1 + + //MeasurementReport-r8-IEs + liblte_value_2_bits(0, &msg_ptr, 1); //non-critical extensions + + //MeasResults + liblte_value_2_bits(0, &msg_ptr, 1); //ext + liblte_value_2_bits(meas_report->have_meas_result_neigh_cells, &msg_ptr, 1); + liblte_rrc_pack_meas_id_ie(meas_report->meas_id, &msg_ptr); + liblte_rrc_pack_rsrp_range_ie(meas_report->pcell_rsrp_result, &msg_ptr); + liblte_rrc_pack_rsrq_range_ie(meas_report->pcell_rsrq_result, &msg_ptr); + if(meas_report->have_meas_result_neigh_cells) { + liblte_value_2_bits(0, &msg_ptr, 1); //choice from before extension marker + liblte_value_2_bits(meas_report->meas_result_neigh_cells_choice, &msg_ptr, 2); + if(meas_report->meas_result_neigh_cells_choice != LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA) { + printf("NOT HANDLING %s\n", liblte_rrc_meas_reult_neigh_cells_text[meas_report->meas_result_neigh_cells_choice]); + } else { + //MeasResultListEUTRA + liblte_value_2_bits(meas_report->meas_result_neigh_cells.eutra.n_result-1, &msg_ptr, 3); + for(uint32 i=0; imeas_result_neigh_cells.eutra.n_result; i++) { + liblte_rrc_pack_meas_result_eutra_ie(&meas_report->meas_result_neigh_cells.eutra.result_eutra_list[i], &msg_ptr); + } + } + } + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_measurement_report_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *meas_report) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + meas_report != NULL) + { + //MeasurementReport + bool crit_ext = liblte_bits_2_value(&msg_ptr, 1); //critical extensions + liblte_bits_2_value(&msg_ptr, 3); //c1 + + //MeasurementReport-r8-IEs + bool non_crit_ext = liblte_bits_2_value(&msg_ptr, 1); //non-critical extensions + + //MeasResults + bool ext = liblte_bits_2_value(&msg_ptr, 1); + meas_report->have_meas_result_neigh_cells = liblte_bits_2_value(&msg_ptr, 1); + liblte_rrc_unpack_meas_id_ie(&msg_ptr, &meas_report->meas_id); + liblte_rrc_unpack_rsrp_range_ie(&msg_ptr, &meas_report->pcell_rsrp_result); + liblte_rrc_unpack_rsrq_range_ie(&msg_ptr, &meas_report->pcell_rsrq_result); + if(meas_report->have_meas_result_neigh_cells) { + liblte_bits_2_value(&msg_ptr, 1); //choice from before extension marker + meas_report->meas_result_neigh_cells_choice = (LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_ENUM) liblte_bits_2_value(&msg_ptr, 2); + if(meas_report->meas_result_neigh_cells_choice != LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA) { + printf("NOT HANDLING %s\n", liblte_rrc_meas_reult_neigh_cells_text[meas_report->meas_result_neigh_cells_choice]); + } else { + //MeasResultListEUTRA + meas_report->meas_result_neigh_cells.eutra.n_result = liblte_bits_2_value(&msg_ptr, 3) + 1; + for(uint32 i=0; imeas_result_neigh_cells.eutra.n_result; i++) { + liblte_rrc_unpack_meas_result_eutra_ie(&msg_ptr, &meas_report->meas_result_neigh_cells.eutra.result_eutra_list[i]); + } + } + } + + //skip extensions + liblte_rrc_consume_noncrit_extension(crit_ext, __func__, &msg_ptr); + liblte_rrc_consume_noncrit_extension(non_crit_ext, __func__, &msg_ptr); + liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* Message Name: MBSFN Area Configuration @@ -13550,9 +13787,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_dcch_msg(LIBLTE_RRC_UL_DCCH_MSG_STRUCT *ul_ err = liblte_rrc_pack_csfb_parameters_request_cdma2000_msg((LIBLTE_RRC_CSFB_PARAMETERS_REQUEST_CDMA2000_STRUCT *)&ul_dcch_msg->msg, &global_msg); }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT == ul_dcch_msg->msg_type){ - printf("NOT HANDLING MEASUREMENT REPORT\n"); -// err = liblte_rrc_pack_measurement_report_msg((LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg, -// &global_msg); + err = liblte_rrc_pack_measurement_report_msg((LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg, + &global_msg); }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE == ul_dcch_msg->msg_type){ err = liblte_rrc_pack_rrc_connection_reconfiguration_complete_msg((LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *)&ul_dcch_msg->msg, &global_msg); @@ -13630,9 +13866,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_dcch_msg(LIBLTE_BIT_MSG_STRUCT *m err = liblte_rrc_unpack_csfb_parameters_request_cdma2000_msg(&global_msg, (LIBLTE_RRC_CSFB_PARAMETERS_REQUEST_CDMA2000_STRUCT *)&ul_dcch_msg->msg); }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT == ul_dcch_msg->msg_type){ - printf("NOT HANDLING MEASUREMENT REPORT\n"); -// err = liblte_rrc_unpack_measurement_report_msg(&global_msg, -// (LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg); + err = liblte_rrc_unpack_measurement_report_msg(&global_msg, + (LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg); }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE == ul_dcch_msg->msg_type){ err = liblte_rrc_unpack_rrc_connection_reconfiguration_complete_msg(&global_msg, (LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *)&ul_dcch_msg->msg); diff --git a/lib/src/common/pdu.cc b/lib/src/common/pdu.cc index 57bc07043..b8d17d984 100644 --- a/lib/src/common/pdu.cc +++ b/lib/src/common/pdu.cc @@ -823,7 +823,7 @@ void rar_subh::write_subheader(uint8_t** ptr, bool is_last) // Section 6.2.3 void rar_subh::write_payload(uint8_t** ptr) { - *(*ptr + 0) = (uint8_t) (ta&0x7f0)>>4; + *(*ptr + 0) = (uint8_t) ((ta&0x7f0)>>4); *(*ptr + 1) = (uint8_t) ((ta&0xf) <<4) | (grant[0]<<3) | (grant[1]<<2) | (grant[2]<<1) | grant[3]; uint8_t *x = &grant[4]; *(*ptr + 2) = (uint8_t) srslte_bit_pack(&x, 8); diff --git a/lib/src/phy/common/phy_common.c b/lib/src/phy/common/phy_common.c index b502fbd75..b4f5e122b 100644 --- a/lib/src/phy/common/phy_common.c +++ b/lib/src/phy/common/phy_common.c @@ -605,7 +605,7 @@ int srslte_band_get_fd_region(enum band_geographical_area region, srslte_earfcn_ /* Returns the interval tti1-tti2 mod 10240 */ uint32_t srslte_tti_interval(uint32_t tti1, uint32_t tti2) { - if (tti1 > tti2) { + if (tti1 >= tti2) { return tti1-tti2; } else { return 10240-tti2+tti1; diff --git a/lib/src/phy/dft/dft_fftw.c b/lib/src/phy/dft/dft_fftw.c index b4a627742..9d6898117 100644 --- a/lib/src/phy/dft/dft_fftw.c +++ b/lib/src/phy/dft/dft_fftw.c @@ -56,9 +56,7 @@ void srslte_dft_load() { 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); - } + fftwf_export_wisdom_to_filename(FFTW_WISDOM_FILE); #endif } @@ -93,6 +91,27 @@ static void allocate(srslte_dft_plan_t *plan, int size_in, int size_out, int len plan->out = fftwf_malloc(size_out*len); } +int srslte_dft_replan_guru_c(srslte_dft_plan_t *plan, const int new_dft_points, cf_t *in_buffer, + cf_t *out_buffer, int istride, int ostride, int how_many, + int idist, int odist) { + int sign = (plan->forward) ? FFTW_FORWARD : FFTW_BACKWARD; + + const fftwf_iodim iodim = {new_dft_points, istride, ostride}; + const fftwf_iodim howmany_dims = {how_many, idist, odist}; + + /* Destroy current plan */ + fftwf_destroy_plan(plan->p); + + plan->p = fftwf_plan_guru_dft(1, &iodim, 1, &howmany_dims, in_buffer, out_buffer, sign, FFTW_TYPE); + if (!plan->p) { + return -1; + } + plan->size = new_dft_points; + plan->init_size = plan->size; + + return 0; +} + 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) { @@ -107,6 +126,32 @@ int srslte_dft_replan_c(srslte_dft_plan_t *plan, const int new_dft_points) { return 0; } +int srslte_dft_plan_guru_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir, cf_t *in_buffer, + cf_t *out_buffer, int istride, int ostride, int how_many, + int idist, int odist) { + int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD; + + const fftwf_iodim iodim = {dft_points, istride, ostride}; + const fftwf_iodim howmany_dims = {how_many, idist, odist}; + + plan->p = fftwf_plan_guru_dft(1, &iodim, 1, &howmany_dims, in_buffer, out_buffer, 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; + plan->mirror = false; + plan->db = false; + plan->norm = false; + plan->dc = false; + plan->is_guru = true; + + 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; @@ -123,6 +168,7 @@ int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_ plan->db = false; plan->norm = false; plan->dc = false; + plan->is_guru = false; return 0; } @@ -232,6 +278,14 @@ void srslte_dft_run_c(srslte_dft_plan_t *plan, cf_t *in, cf_t *out) { plan->forward, plan->mirror, plan->dc); } +void srslte_dft_run_guru_c(srslte_dft_plan_t *plan) { + if (plan->is_guru == true) { + fftwf_execute(plan->p); + } else { + fprintf(stderr, "srslte_dft_run_guru_c: the selected plan is not guru!\n"); + } +} + void srslte_dft_run_r(srslte_dft_plan_t *plan, float *in, float *out) { float norm; int i; @@ -255,8 +309,10 @@ void srslte_dft_run_r(srslte_dft_plan_t *plan, float *in, float *out) { void srslte_dft_plan_free(srslte_dft_plan_t *plan) { if (!plan) return; if (!plan->size) return; - if (plan->in) fftwf_free(plan->in); - if (plan->out) fftwf_free(plan->out); + if (!plan->is_guru) { + if (plan->in) fftwf_free(plan->in); + if (plan->out) fftwf_free(plan->out); + } if (plan->p) fftwf_destroy_plan(plan->p); bzero(plan, sizeof(srslte_dft_plan_t)); } diff --git a/lib/src/phy/dft/ofdm.c b/lib/src/phy/dft/ofdm.c index db5939274..8ea690bb5 100644 --- a/lib/src/phy/dft/ofdm.c +++ b/lib/src/phy/dft/ofdm.c @@ -37,23 +37,79 @@ #include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/vector.h" +/* Uncomment next line for avoiding Guru DFT call */ +//#define AVOID_GURU -int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_prb, srslte_dft_dir_t dir) { - return srslte_ofdm_init_mbsfn_(q, cp, symbol_sz, nof_prb, dir, SRSLTE_SF_NORM); +int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, int symbol_sz, int nof_prb, srslte_dft_dir_t dir) { + return srslte_ofdm_init_mbsfn_(q, cp, in_buffer, out_buffer, symbol_sz, nof_prb, dir, SRSLTE_SF_NORM); } +int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, int symbol_sz, int nof_prb, srslte_dft_dir_t dir, srslte_sf_t sf_type) { -int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_prb, srslte_dft_dir_t dir, srslte_sf_t sf_type) { + /* Set OFDM object attributes */ + q->symbol_sz = (uint32_t) symbol_sz; + q->nof_symbols = SRSLTE_CP_NSYMB(cp); + q->nof_symbols_mbsfn = SRSLTE_CP_NSYMB(SRSLTE_CP_EXT); + q->cp = cp; + q->freq_shift = false; + q->nof_re = (uint32_t) nof_prb * SRSLTE_NRE; + q->nof_guards = ((symbol_sz - q->nof_re) / 2); + q->slot_sz = (uint32_t) SRSLTE_SLOT_LEN(symbol_sz); + q->sf_sz = (uint32_t) SRSLTE_SF_LEN(symbol_sz); + q->in_buffer = in_buffer; + q->out_buffer= out_buffer; if (srslte_dft_plan_c(&q->fft_plan, symbol_sz, dir)) { fprintf(stderr, "Error: Creating DFT plan\n"); return -1; } + +#ifdef AVOID_GURU q->tmp = srslte_vec_malloc((uint32_t) symbol_sz * sizeof(cf_t)); if (!q->tmp) { perror("malloc"); return -1; } + bzero(q->tmp, sizeof(cf_t) * symbol_sz); +#else + int cp1 = SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN_NORM(0, symbol_sz):SRSLTE_CP_LEN_EXT(symbol_sz); + int cp2 = SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN_NORM(1, symbol_sz):SRSLTE_CP_LEN_EXT(symbol_sz); + + q->tmp = srslte_vec_malloc(sizeof(cf_t) * q->sf_sz); + if (!q->tmp) { + perror("malloc"); + return -1; + } + bzero(q->tmp, sizeof(cf_t) * q->sf_sz); + + if (dir == SRSLTE_DFT_BACKWARD) { + bzero(in_buffer, sizeof(cf_t) * SRSLTE_SF_LEN_RE(nof_prb, cp)); + }else { + bzero(in_buffer, sizeof(cf_t) * q->sf_sz); + } + + for (int slot = 0; slot < 2; slot++) { + //bzero(&q->fft_plan_sf[slot], sizeof(srslte_dft_plan_t)); + //bzero(q->tmp + SRSLTE_CP_NSYMB(cp)*symbol_sz*slot, sizeof(cf_t) * (cp1 + (SRSLTE_CP_NSYMB(cp) - 1)*cp2 + SRSLTE_CP_NSYMB(cp)*symbol_sz)); + if (dir == SRSLTE_DFT_FORWARD) { + if (srslte_dft_plan_guru_c(&q->fft_plan_sf[slot], symbol_sz, dir, + in_buffer + cp1 + q->slot_sz * slot, + q->tmp + q->nof_symbols * q->symbol_sz * slot, + 1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz + cp2, symbol_sz)) { + fprintf(stderr, "Error: Creating DFT plan (1)\n"); + return -1; + } + } else { + if (srslte_dft_plan_guru_c(&q->fft_plan_sf[slot], symbol_sz, dir, + q->tmp + q->nof_symbols * q->symbol_sz * slot, + out_buffer + cp1 + q->slot_sz * slot, + 1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz, symbol_sz + cp2)) { + fprintf(stderr, "Error: Creating DFT plan (1)\n"); + return -1; + } + } + } +#endif q->shift_buffer = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN(symbol_sz)); if (!q->shift_buffer) { @@ -64,15 +120,6 @@ int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int srslte_dft_plan_set_mirror(&q->fft_plan, true); srslte_dft_plan_set_dc(&q->fft_plan, true); - q->symbol_sz = (uint32_t) symbol_sz; - q->nof_symbols = SRSLTE_CP_NSYMB(cp); - q->nof_symbols_mbsfn = SRSLTE_CP_NSYMB(SRSLTE_CP_EXT); - q->cp = cp; - q->freq_shift = false; - q->nof_re = nof_prb * SRSLTE_NRE; - q->nof_guards = ((symbol_sz - q->nof_re) / 2); - q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz); - DEBUG("Init %s symbol_sz=%d, nof_symbols=%d, cp=%s, nof_re=%d, nof_guards=%d\n", dir==SRSLTE_DFT_FORWARD?"FFT":"iFFT", q->symbol_sz, q->nof_symbols, q->cp==SRSLTE_CP_NORM?"Normal":"Extended", q->nof_re, q->nof_guards); @@ -101,9 +148,60 @@ int srslte_ofdm_replan_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof 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_re = (uint32_t) nof_prb * SRSLTE_NRE; q->nof_guards = ((symbol_sz - q->nof_re) / 2); - q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz); + q->slot_sz = (uint32_t) SRSLTE_SLOT_LEN(symbol_sz); + q->sf_sz = (uint32_t) SRSLTE_SF_LEN(symbol_sz); + +#ifndef AVOID_GURU + cf_t *in_buffer = q->in_buffer; + cf_t *out_buffer = q->out_buffer; + + int cp1 = SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN_NORM(0, symbol_sz):SRSLTE_CP_LEN_EXT(symbol_sz); + int cp2 = SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN_NORM(1, symbol_sz):SRSLTE_CP_LEN_EXT(symbol_sz); + + srslte_dft_dir_t dir = q->fft_plan_sf[0].dir; + + if (q->tmp) { + free(q->tmp); + } + + q->tmp = srslte_vec_malloc(sizeof(cf_t) * q->sf_sz); + if (!q->tmp) { + perror("malloc"); + return -1; + } + bzero(q->tmp, sizeof(cf_t) * q->sf_sz); + + if (dir == SRSLTE_DFT_BACKWARD) { + bzero(in_buffer, sizeof(cf_t) * SRSLTE_SF_LEN_RE(nof_prb, cp)); + }else { + bzero(in_buffer, sizeof(cf_t) * q->sf_sz); + } + + for (int slot = 0; slot < 2; slot++) { + srslte_dft_plan_free(&q->fft_plan_sf[slot]); + + if (dir == SRSLTE_DFT_FORWARD) { + if (srslte_dft_plan_guru_c(&q->fft_plan_sf[slot], symbol_sz, dir, + in_buffer + cp1 + q->slot_sz * slot, + q->tmp + q->nof_symbols * q->symbol_sz * slot, + 1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz + cp2, symbol_sz)) { + fprintf(stderr, "Error: Creating DFT plan (1)\n"); + return -1; + } + } else { + if (srslte_dft_plan_guru_c(&q->fft_plan_sf[slot], symbol_sz, dir, + q->tmp + q->nof_symbols * q->symbol_sz * slot, + out_buffer + cp1 + q->slot_sz * slot, + 1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz, symbol_sz + cp2)) { + fprintf(stderr, "Error: Creating DFT plan (1)\n"); + return -1; + } + } + } +#endif /* AVOID_GURU */ + if (q->freq_shift) { srslte_ofdm_set_freq_shift(q, q->freq_shift_f); @@ -118,6 +216,15 @@ int srslte_ofdm_replan_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof void srslte_ofdm_free_(srslte_ofdm_t *q) { srslte_dft_plan_free(&q->fft_plan); + +#ifndef AVOID_GURU + for (int slot = 0; slot < 2; slot++) { + if (q->fft_plan_sf[slot].init_size) { + srslte_dft_plan_free(&q->fft_plan_sf[slot]); + } + } +#endif + if (q->tmp) { free(q->tmp); } @@ -127,28 +234,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 max_prb) { +int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t max_prb) { int symbol_sz = srslte_symbol_sz(max_prb); if (symbol_sz < 0) { fprintf(stderr, "Error: Invalid nof_prb=%d\n", max_prb); return -1; } q->max_prb = max_prb; - return srslte_ofdm_init_(q, cp, symbol_sz, max_prb, SRSLTE_DFT_FORWARD); + return srslte_ofdm_init_(q, cp, in_buffer, out_buffer, symbol_sz, max_prb, SRSLTE_DFT_FORWARD); } -int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) +int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t nof_prb) { int symbol_sz = srslte_symbol_sz(nof_prb); if (symbol_sz < 0) { fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb); return -1; } - return srslte_ofdm_init_mbsfn_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_FORWARD, SRSLTE_SF_MBSFN); + return srslte_ofdm_init_mbsfn_(q, cp, in_buffer, out_buffer, symbol_sz, nof_prb, SRSLTE_DFT_FORWARD, SRSLTE_SF_MBSFN); } -int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) { +int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t max_prb) { uint32_t i; int ret; @@ -158,7 +265,7 @@ int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) { return -1; } q->max_prb = max_prb; - ret = srslte_ofdm_init_(q, cp, symbol_sz, max_prb, SRSLTE_DFT_BACKWARD); + ret = srslte_ofdm_init_(q, cp, in_buffer, out_buffer, symbol_sz, max_prb, SRSLTE_DFT_BACKWARD); if (ret == SRSLTE_SUCCESS) { @@ -173,7 +280,7 @@ int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) { return ret; } -int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) +int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t nof_prb) { uint32_t i; int ret; @@ -184,7 +291,7 @@ int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb return -1; } - ret = srslte_ofdm_init_mbsfn_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_BACKWARD, SRSLTE_SF_MBSFN); + ret = srslte_ofdm_init_mbsfn_(q, cp, in_buffer, out_buffer, symbol_sz, nof_prb, SRSLTE_DFT_BACKWARD, SRSLTE_SF_MBSFN); if (ret == SRSLTE_SUCCESS) { srslte_dft_plan_set_norm(&q->fft_plan, false); @@ -207,7 +314,8 @@ int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) { } 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"); + fprintf(stderr, "OFDM (Rx): Error calling set_prb: nof_prb (%d) must be equal or lower initialized max_prb (%d)\n", + nof_prb, q->max_prb); return -1; } } @@ -234,7 +342,8 @@ int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) { } return ret; } else { - fprintf(stderr, "OFDM: Error calling set_prb: nof_prb must be equal or lower initialized max_prb\n"); + fprintf(stderr, "OFDM (Tx): Error calling set_prb: nof_prb (%d) must be equal or lower initialized max_prb (%d)\n", + nof_prb, q->max_prb); return -1; } } @@ -274,8 +383,12 @@ void srslte_ofdm_tx_free(srslte_ofdm_t *q) { /* Transforms input samples into output OFDM symbols. * Performs FFT on a each symbol and removes CP. */ -void srslte_ofdm_rx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) { +void srslte_ofdm_rx_slot(srslte_ofdm_t *q, int slot_in_sf) { + cf_t *output = q->out_buffer + slot_in_sf * q->nof_re * q->nof_symbols; + +#ifdef AVOID_GURU uint32_t i; + cf_t *input = q->in_buffer + slot_in_sf * q->slot_sz; for (i=0;inof_symbols;i++) { input += SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz); srslte_dft_run_c(&q->fft_plan, input, q->tmp); @@ -283,6 +396,25 @@ void srslte_ofdm_rx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) { input += q->symbol_sz; output += q->nof_re; } +#else + float norm = 1.0f/sqrtf(q->fft_plan.size); + cf_t *tmp = q->tmp + slot_in_sf * q->symbol_sz * q->nof_symbols; + uint32_t dc = (q->fft_plan.dc) ? 1:0; + + srslte_dft_run_guru_c(&q->fft_plan_sf[slot_in_sf]); + + for (int i = 0; i < q->nof_symbols; i++) { + memcpy(output, tmp + q->symbol_sz - q->nof_re / 2, sizeof(cf_t) * q->nof_re / 2); + memcpy(output + q->nof_re / 2, &tmp[dc], sizeof(cf_t) * q->nof_re / 2); + + if (q->fft_plan.norm) { + srslte_vec_sc_prod_cfc(output, norm, output, q->nof_re); + } + + tmp += q->symbol_sz; + output += q->nof_re; + } +#endif } void srslte_ofdm_rx_slot_mbsfn(srslte_ofdm_t *q, cf_t *input, cf_t *output) @@ -314,29 +446,32 @@ void srslte_ofdm_rx_slot_zerocopy(srslte_ofdm_t *q, cf_t *input, cf_t *output) { } } -void srslte_ofdm_rx_sf(srslte_ofdm_t *q, cf_t *input, cf_t *output) { - uint32_t n; +void srslte_ofdm_rx_sf(srslte_ofdm_t *q) { + uint32_t n; if (q->freq_shift) { - srslte_vec_prod_ccc(input, q->shift_buffer, input, 2*q->slot_sz); + srslte_vec_prod_ccc(q->in_buffer, q->shift_buffer, q->in_buffer, 2*q->slot_sz); } if(!q->mbsfn_subframe){ for (n=0;n<2;n++) { - srslte_ofdm_rx_slot(q, &input[n*q->slot_sz], &output[n*q->nof_re*q->nof_symbols]); + srslte_ofdm_rx_slot(q, n); } } else{ - srslte_ofdm_rx_slot_mbsfn(q, &input[0*q->slot_sz], &output[0*q->nof_re*q->nof_symbols]); - srslte_ofdm_rx_slot(q, &input[1*q->slot_sz], &output[1*q->nof_re*q->nof_symbols]); + srslte_ofdm_rx_slot_mbsfn(q, &q->in_buffer[0*q->slot_sz], &q->out_buffer[0*q->nof_re*q->nof_symbols]); + srslte_ofdm_rx_slot(q, 1); } } /* Transforms input OFDM symbols into output samples. * Performs FFT on a each symbol and adds CP. */ -void srslte_ofdm_tx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) { - uint32_t i, cp_len; - for (i=0;inof_symbols;i++) { - cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz); +void srslte_ofdm_tx_slot(srslte_ofdm_t *q, int slot_in_sf) { + cf_t *input = q->in_buffer + slot_in_sf * q->nof_re * q->nof_symbols; + cf_t *output = q->out_buffer + slot_in_sf * q->slot_sz; + +#ifdef AVOID_GURU + for (int i=0;inof_symbols;i++) { + int cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz); memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t)); srslte_dft_run_c(&q->fft_plan, q->tmp, &output[cp_len]); input += q->nof_re; @@ -344,6 +479,60 @@ void srslte_ofdm_tx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) { memcpy(output, &output[q->symbol_sz], cp_len * sizeof(cf_t)); output += q->symbol_sz + cp_len; } +#else + float norm = 1.0f/sqrtf(q->symbol_sz); + cf_t *tmp = q->tmp + slot_in_sf * q->symbol_sz * q->nof_symbols; + + bzero(tmp, q->slot_sz); + uint32_t dc = (q->fft_plan.dc) ? 1:0; + + for (int i = 0; i < q->nof_symbols; i++) { + memcpy(&tmp[dc], &input[q->nof_re / 2], q->nof_re / 2 * sizeof(cf_t)); + memcpy(&tmp[q->symbol_sz - q->nof_re / 2], &input[0], q->nof_re / 2 * sizeof(cf_t)); + + input += q->nof_re; + tmp += q->symbol_sz; + } + + srslte_dft_run_guru_c(&q->fft_plan_sf[slot_in_sf]); + + for (int i=0;inof_symbols;i++) { + int cp_len = SRSLTE_CP_ISNORM(q->cp) ? SRSLTE_CP_LEN_NORM(i, q->symbol_sz) : SRSLTE_CP_LEN_EXT(q->symbol_sz); + + if (q->fft_plan.norm) { + srslte_vec_sc_prod_cfc(&output[cp_len], norm, &output[cp_len], q->symbol_sz); + } + + /* add CP */ + memcpy(output, &output[q->symbol_sz], cp_len * sizeof(cf_t)); + output += q->symbol_sz + cp_len; + } +#endif + + /*input = q->in_buffer + slot_in_sf * q->nof_re * q->nof_symbols; + cf_t *output2 = srslte_vec_malloc(sizeof(cf_t) * q->slot_sz); + cf_t *o2 = output2; + bzero(q->tmp, sizeof(cf_t)*q->symbol_sz); + //bzero(output2, sizeof(cf_t)*q->slot_sz); + for (int i=0;inof_symbols;i++) { + int cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz); + memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t)); + srslte_dft_run_c(&q->fft_plan, q->tmp, &o2[cp_len]); + input += q->nof_re; + memcpy(o2, &o2[q->symbol_sz], cp_len * sizeof(cf_t)); + o2 += q->symbol_sz + cp_len; + } + cf_t *output1 = q->out_buffer + slot_in_sf * q->slot_sz;//srslte_vec_malloc(sizeof(cf_t) * q->slot_sz); + + for (int i = 0; i < q->slot_sz; i++) { + float error = cabsf(output1[i] - output2[i])/cabsf(output2[i]); + cf_t k = output1[i]/output2[i]; + if (error > 0.1) printf("%d/%05d error=%f output=%+f%+fi gold=%+f%+fi k=%+f%+fi\n", slot_in_sf, i, error, + __real__ output1[i], __imag__ output1[i], + __real__ output2[i], __imag__ output2[i], + __real__ k, __imag__ k); + } + free(output2);/**/ } void srslte_ofdm_tx_slot_mbsfn(srslte_ofdm_t *q, cf_t *input, cf_t *output) @@ -369,20 +558,20 @@ void srslte_ofdm_set_normalize(srslte_ofdm_t *q, bool normalize_enable) { srslte_dft_plan_set_norm(&q->fft_plan, normalize_enable); } -void srslte_ofdm_tx_sf(srslte_ofdm_t *q, cf_t *input, cf_t *output) +void srslte_ofdm_tx_sf(srslte_ofdm_t *q) { - uint32_t n; + uint32_t n; if(!q->mbsfn_subframe){ for (n=0;n<2;n++) { - srslte_ofdm_tx_slot(q, &input[n*q->nof_re*q->nof_symbols], &output[n*q->slot_sz]); + srslte_ofdm_tx_slot(q, n); } } else{ - srslte_ofdm_tx_slot_mbsfn(q, &input[0*q->nof_re*q->nof_symbols], &output[0*q->slot_sz]); - srslte_ofdm_tx_slot(q, &input[1*q->nof_re*q->nof_symbols], &output[1*q->slot_sz]); + srslte_ofdm_tx_slot_mbsfn(q, &q->in_buffer[0*q->nof_re*q->nof_symbols], &q->out_buffer[0*q->slot_sz]); + srslte_ofdm_tx_slot(q, 1); } if (q->freq_shift) { - srslte_vec_prod_ccc(output, q->shift_buffer, output, 2*q->slot_sz); + srslte_vec_prod_ccc(q->out_buffer, q->shift_buffer, q->out_buffer, 2*q->slot_sz); } } diff --git a/lib/src/phy/dft/test/ofdm_test.c b/lib/src/phy/dft/test/ofdm_test.c index 11aac7f4e..e77fcd39e 100644 --- a/lib/src/phy/dft/test/ofdm_test.c +++ b/lib/src/phy/dft/test/ofdm_test.c @@ -35,16 +35,28 @@ int nof_prb = -1; srslte_cp_t cp = SRSLTE_CP_NORM; +int nof_repetitions = 128; + +static double elapsed_us(struct timeval *ts_start, struct timeval *ts_end) { + if (ts_end->tv_usec > ts_start->tv_usec) { + return ((double) ts_end->tv_sec - (double) ts_start->tv_sec) * 1000000 + + (double) ts_end->tv_usec - (double) ts_start->tv_usec; + } else { + return ((double) ts_end->tv_sec - (double) ts_start->tv_sec - 1) * 1000000 + + ((double) ts_end->tv_usec + 1000000) - (double) ts_start->tv_usec; + } +} void usage(char *prog) { printf("Usage: %s\n", prog); printf("\t-n nof_prb [Default All]\n"); printf("\t-e extended cyclic prefix [Default Normal]\n"); + printf("\t-r nof_repetitions [Default %d]\n", nof_repetitions); } void parse_args(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "ne")) != -1) { + while ((opt = getopt(argc, argv, "ner")) != -1) { switch (opt) { case 'n': nof_prb = atoi(argv[optind]); @@ -52,6 +64,9 @@ void parse_args(int argc, char **argv) { case 'e': cp = SRSLTE_CP_EXT; break; + case 'r': + nof_repetitions = atoi(argv[optind]); + break; default: usage(argv[0]); exit(-1); @@ -61,6 +76,7 @@ void parse_args(int argc, char **argv) { int main(int argc, char **argv) { + struct timeval start, end; srslte_ofdm_t fft, ifft; cf_t *input, *outfft, *outifft; float mse; @@ -81,48 +97,65 @@ int main(int argc, char **argv) { printf("Running test for %d PRB, %d RE... ", n_prb, n_re);fflush(stdout); - input = malloc(sizeof(cf_t) * n_re); + input = srslte_vec_malloc(sizeof(cf_t) * n_re * 2); if (!input) { perror("malloc"); exit(-1); } - outfft = malloc(sizeof(cf_t) * SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb))); + outfft = srslte_vec_malloc(sizeof(cf_t) * n_re * 2); if (!outfft) { perror("malloc"); exit(-1); } - outifft = malloc(sizeof(cf_t) * n_re); + outifft = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb)) * 2); if (!outifft) { perror("malloc"); exit(-1); } + bzero(outifft, sizeof(cf_t) * SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb)) * 2); - if (srslte_ofdm_rx_init(&fft, cp, n_prb)) { + if (srslte_ofdm_rx_init(&fft, cp, outifft, outfft, n_prb)) { fprintf(stderr, "Error initializing FFT\n"); exit(-1); } - srslte_dft_plan_set_norm(&fft.fft_plan, true); + srslte_ofdm_set_normalize(&fft, true); - if (srslte_ofdm_tx_init(&ifft, cp, n_prb)) { + if (srslte_ofdm_tx_init(&ifft, cp, input, outifft, n_prb)) { fprintf(stderr, "Error initializing iFFT\n"); exit(-1); } - srslte_dft_plan_set_norm(&ifft.fft_plan, true); + srslte_ofdm_set_normalize(&ifft, true); for (i=0;i 1.0f) printf("%04d. %+.1f%+.1fi Vs. %+.1f%+.1f %+.1f%+.1f (mse=%f)\n", i, __real__ input[i], __imag__ input[i], __real__ outifft[i], __imag__ outifft[i], __real__ outfft[i], __imag__ outfft[i], mse); } - printf("MSE=%f\n", mse); + /*for (i=0;i= 0.07) { printf("MSE too large\n"); diff --git a/lib/src/phy/enb/enb_dl.c b/lib/src/phy/enb/enb_dl.c index 2ba179399..98224d740 100644 --- a/lib/src/phy/enb/enb_dl.c +++ b/lib/src/phy/enb/enb_dl.c @@ -31,6 +31,7 @@ #include #include #include +#include #define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb) @@ -41,7 +42,7 @@ #define SRSLTE_ENB_RF_AMP 0.1 -int srslte_enb_dl_init(srslte_enb_dl_t *q, uint32_t max_prb) +int srslte_enb_dl_init(srslte_enb_dl_t *q, cf_t *out_buffer[SRSLTE_MAX_PORTS], uint32_t max_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -53,13 +54,22 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, uint32_t max_prb) q->cfi = 3; q->tx_amp = SRSLTE_ENB_RF_AMP; - - if (srslte_ofdm_tx_init(&q->ifft, SRSLTE_CP_NORM, max_prb)) { - fprintf(stderr, "Error initiating FFT\n"); - goto clean_exit; + + for (int i=0;isf_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][SRSLTE_SLOT_LEN_RE(max_prb, SRSLTE_CP_NORM)]; } - srslte_ofdm_set_normalize(&q->ifft, true); + for (int i = 0; i < SRSLTE_MAX_PORTS; i++) { + if (srslte_ofdm_tx_init(&q->ifft[i], SRSLTE_CP_NORM, q->sf_symbols[i], out_buffer[i], max_prb)) { + fprintf(stderr, "Error initiating FFT (%d)\n", i); + goto clean_exit; + } + } if (srslte_pbch_init(&q->pbch)) { fprintf(stderr, "Error creating PBCH object\n"); @@ -89,15 +99,6 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, uint32_t max_prb) goto clean_exit; } - for (int i=0;isf_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][SRSLTE_SLOT_LEN_RE(max_prb, SRSLTE_CP_NORM)]; - } - ret = SRSLTE_SUCCESS; } else { @@ -114,7 +115,9 @@ clean_exit: void srslte_enb_dl_free(srslte_enb_dl_t *q) { if (q) { - srslte_ofdm_tx_free(&q->ifft); + for (int i = 0; i < SRSLTE_MAX_PORTS; i++) { + srslte_ofdm_tx_free(&q->ifft[i]); + } srslte_regs_free(&q->regs); srslte_pbch_free(&q->pbch); srslte_pcfich_free(&q->pcfich); @@ -152,9 +155,11 @@ int srslte_enb_dl_set_cell(srslte_enb_dl_t *q, srslte_cell_t 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; + for (int i = 0; i < q->cell.nof_ports; i++) { + if (srslte_ofdm_tx_set_prb(&q->ifft[i], q->cell.cp, q->cell.nof_prb)) { + fprintf(stderr, "Error re-planning iFFT (%d)\n", i); + return SRSLTE_ERROR; + } } if (srslte_pbch_set_cell(&q->pbch, q->cell)) { fprintf(stderr, "Error creating PBCH object\n"); @@ -264,14 +269,15 @@ void srslte_enb_dl_put_base(srslte_enb_dl_t *q, uint32_t tti) } -void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q, cf_t *signal_buffer) +void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q) { - - srslte_ofdm_tx_sf(&q->ifft, q->sf_symbols[0], signal_buffer); - // TODO: PAPR control - float norm_factor = (float) sqrt(q->cell.nof_prb)/15; - srslte_vec_sc_prod_cfc(signal_buffer, q->tx_amp*norm_factor, signal_buffer, SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); + float norm_factor = (float) sqrt(q->cell.nof_prb)/15/sqrt(q->ifft[0].symbol_sz); + + for (int i = 0; i < q->cell.nof_ports; i++) { + srslte_ofdm_tx_sf(&q->ifft[i]); + srslte_vec_sc_prod_cfc(q->ifft[i].out_buffer, q->tx_amp*norm_factor, q->ifft[i].out_buffer, (uint32_t) SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); + } } int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q, uint16_t rnti) diff --git a/lib/src/phy/enb/enb_ul.c b/lib/src/phy/enb/enb_ul.c index db05d44ea..f94eb0277 100644 --- a/lib/src/phy/enb/enb_ul.c +++ b/lib/src/phy/enb/enb_ul.c @@ -40,6 +40,7 @@ #define MAX_CANDIDATES 16 int srslte_enb_ul_init(srslte_enb_ul_t *q, + cf_t *in_buffer, uint32_t max_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -55,8 +56,20 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q, perror("malloc"); goto clean_exit; } - - if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) { + + 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(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t)); + if (!q->ce) { + perror("malloc"); + goto clean_exit; + } + + if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, in_buffer, q->sf_symbols, max_prb)) { fprintf(stderr, "Error initiating FFT\n"); goto clean_exit; } @@ -80,18 +93,6 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q, goto clean_exit; } - 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(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t)); - if (!q->ce) { - perror("malloc"); - goto clean_exit; - } - ret = SRSLTE_SUCCESS; } else { @@ -254,7 +255,7 @@ int srslte_enb_ul_cfg_ue(srslte_enb_ul_t *q, uint16_t rnti, void srslte_enb_ul_fft(srslte_enb_ul_t *q, cf_t *signal_buffer) { - srslte_ofdm_rx_sf(&q->fft, signal_buffer, q->sf_symbols); + srslte_ofdm_rx_sf(&q->fft); } int get_pucch(srslte_enb_ul_t *q, uint16_t rnti, diff --git a/lib/src/phy/mimo/precoding.c b/lib/src/phy/mimo/precoding.c index a21219a91..5d96bed27 100644 --- a/lib/src/phy/mimo/precoding.c +++ b/lib/src/phy/mimo/precoding.c @@ -1454,7 +1454,7 @@ int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_ return srslte_predecoding_single_multi(y, h[0], x[0], nof_rxant, nof_symbols, noise_estimate); } else { fprintf(stderr, - "Number of ports and layers must be 1 for transmission on single antenna ports\n"); + "Number of ports and layers must be 1 for transmission on single antenna ports (%d, %d)\n", nof_ports, nof_layers); return -1; } break; diff --git a/lib/src/phy/modem/demod_hard.c b/lib/src/phy/modem/demod_hard.c index 76f54236d..899559ecc 100644 --- a/lib/src/phy/modem/demod_hard.c +++ b/lib/src/phy/modem/demod_hard.c @@ -44,6 +44,7 @@ int srslte_demod_hard_demodulate(srslte_demod_hard_t* q, cf_t* symbols, uint8_t int nbits=-1; switch(q->mod) { + case SRSLTE_MOD_LAST: case SRSLTE_MOD_BPSK: hard_bpsk_demod(symbols,bits,nsymbols); nbits=nsymbols; diff --git a/lib/src/phy/modem/modem_table.c b/lib/src/phy/modem/modem_table.c index c19e52e77..3c4ad2417 100644 --- a/lib/src/phy/modem/modem_table.c +++ b/lib/src/phy/modem/modem_table.c @@ -82,6 +82,7 @@ int srslte_modem_table_set(srslte_modem_table_t* q, cf_t* table, uint32_t nsymbo int srslte_modem_table_lte(srslte_modem_table_t* q, srslte_mod_t modulation) { srslte_modem_table_init(q); switch(modulation) { + case SRSLTE_MOD_LAST: case SRSLTE_MOD_BPSK: q->nbits_x_symbol = 1; q->nsymbols = 2; diff --git a/lib/src/phy/phch/dci.c b/lib/src/phy/phch/dci.c index 2daa7e10d..3ce4cd6ae 100644 --- a/lib/src/phy/phch/dci.c +++ b/lib/src/phy/phch/dci.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "srslte/phy/phch/dci.h" #include "srslte/phy/common/phy_common.h" @@ -111,7 +112,7 @@ int srslte_dci_rar_to_ul_grant(srslte_dci_rar_grant_t *rar, uint32_t nof_prb, srslte_ra_type2_from_riv(riv, &ul_dci->type2_alloc.L_crb, &ul_dci->type2_alloc.RB_start, nof_prb, nof_prb); - if (srslte_ra_ul_dci_to_grant(ul_dci, nof_prb, n_rb_ho, grant, 0)) { + if (srslte_ra_ul_dci_to_grant(ul_dci, nof_prb, n_rb_ho, grant)) { return SRSLTE_ERROR; } @@ -177,7 +178,7 @@ int srslte_dci_msg_to_ul_grant(srslte_dci_msg_t *msg, uint32_t nof_prb, return ret; } - if (srslte_ra_ul_dci_to_grant(ul_dci, nof_prb, n_rb_ho, grant, harq_pid)) { + if (srslte_ra_ul_dci_to_grant(ul_dci, nof_prb, n_rb_ho, grant)) { return ret; } @@ -1159,7 +1160,32 @@ int dci_format2AB_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32 } else if (msg->format == SRSLTE_DCI_FORMAT2A) { data->pinfo = srslte_bit_pack(&y, precoding_bits_f2a(nof_ports)); } - + + // Table 5.3.3.1.5-1 + if (SRSLTE_RA_DL_GRANT_NOF_TB(data) == 2) { + if (data->tb_cw_swap) { + uint32_t tmp = data->rv_idx; + data->rv_idx = data->rv_idx_1; + data->rv_idx_1 = tmp; + + tmp = data->mcs_idx; + data->mcs_idx = data->mcs_idx_1; + data->mcs_idx_1 = tmp; + + bool tmp_ndi = data->ndi; + data->ndi = data->ndi_1; + data->ndi_1 = tmp_ndi; + } + } + + // Table 5.3.3.1.5-2 + if (!data->tb_en[0]) { + data->rv_idx = data->rv_idx_1; + data->mcs_idx = data->mcs_idx_1; + data->ndi = data->ndi_1; + + data->tb_en[1] = false; + } return SRSLTE_SUCCESS; } diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index b438a2957..b984adee3 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -477,6 +477,7 @@ int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra cfg->sf_idx = sf_idx; memcpy(cfg->rv, rvidx, sizeof(uint32_t) * SRSLTE_MAX_CODEWORDS); cfg->mimo_type = mimo_type; + cfg->tb_cw_swap = grant->tb_cw_swap; /* Check and configure PDSCH transmission modes */ switch(mimo_type) { @@ -492,7 +493,7 @@ int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra ERROR("Wrong number of transport blocks (%d) for transmit diversity.", nof_tb); return SRSLTE_ERROR; } - cfg->nof_layers = 2; + cfg->nof_layers = cell.nof_ports; break; case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX: if (nof_tb == 1) { @@ -543,19 +544,19 @@ static srslte_sequence_t *get_user_sequence(srslte_pdsch_t *q, uint16_t rnti, 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]; - srslte_ra_mcs_t *mcs = &cfg->grant.mcs[codeword_idx]; - uint32_t rv = cfg->rv[codeword_idx]; + uint32_t codeword_idx, uint32_t tb_idx) { + srslte_ra_nbits_t *nbits = &cfg->nbits[tb_idx]; + srslte_ra_mcs_t *mcs = &cfg->grant.mcs[tb_idx]; + uint32_t rv = cfg->rv[tb_idx]; if (nbits->nof_bits) { - INFO("Encoding 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, + INFO("Encoding PDSCH SF: %d (TB%d -> CW%d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", + cfg->sf_idx, tb_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs, nbits->nof_re, nbits->nof_bits, rv); /* Channel coding */ - if (srslte_dlsch_encode2(&q->dl_sch, cfg, softbuffer, data, q->e[codeword_idx], codeword_idx)) { - ERROR("Error encoding TB %d", codeword_idx); + if (srslte_dlsch_encode2(&q->dl_sch, cfg, softbuffer, data, q->e[codeword_idx], tb_idx)) { + ERROR("Error encoding (TB%d -> CW%d)", tb_idx, codeword_idx); return SRSLTE_ERROR; } @@ -577,15 +578,15 @@ static int srslte_pdsch_codeword_encode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data, - uint32_t codeword_idx, bool *ack) { - srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx]; - srslte_ra_mcs_t *mcs = &cfg->grant.mcs[codeword_idx]; - uint32_t rv = cfg->rv[codeword_idx]; + uint32_t codeword_idx, uint32_t tb_idx, bool *ack) { + srslte_ra_nbits_t *nbits = &cfg->nbits[tb_idx]; + srslte_ra_mcs_t *mcs = &cfg->grant.mcs[tb_idx]; + uint32_t rv = cfg->rv[tb_idx]; int ret = SRSLTE_ERROR_INVALID_INPUTS; 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, + INFO("Decoding PDSCH SF: %d (CW%d -> TB%d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", + cfg->sf_idx, codeword_idx, tb_idx, srslte_mod_string(mcs->mod), mcs->tbs, nbits->nof_re, nbits->nof_bits, rv); /* demodulate symbols @@ -601,7 +602,7 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c 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); + ret = srslte_dlsch_decode2(&q->dl_sch, cfg, softbuffer, q->e[codeword_idx], data, tb_idx); q->last_nof_iterations[codeword_idx] = srslte_sch_last_noi(&q->dl_sch); @@ -610,6 +611,9 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c } else if (ret == SRSLTE_ERROR) { *ack = false; ret = SRSLTE_SUCCESS; + } else if (ret == SRSLTE_ERROR_INVALID_INPUTS) { + *ack = false; + ret = SRSLTE_ERROR; } } else { ERROR("Detected NULL pointer in TB%d &softbuffer=%p &data=%p &ack=%p", codeword_idx, softbuffer, (void*)data, ack); @@ -677,24 +681,32 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, } // Pre-decoder - srslte_predecoding_type_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers, - cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, noise_estimate); + if (srslte_predecoding_type_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers, + cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, noise_estimate)<0) { + return -1; + } // Layer demapping only if necessary 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 < SRSLTE_MAX_CODEWORDS; tb ++) { - /* Decode only if transport block is enabled and the default ACK is not true */ - if (cfg->grant.tb_en[tb] && !acks[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; + /* Codeword decoding: Implementation of 3GPP 36.212 Table 5.3.3.1.5-1 and Table 5.3.3.1.5-2 */ + uint32_t cw_idx = (nof_tb == SRSLTE_MAX_TB && cfg->tb_cw_swap) ? 1 : 0; + for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) { + /* Decode only if transport block is enabled and the default ACK is not true */ + if (cfg->grant.tb_en[tb_idx]) { + if (!acks[tb_idx]) { + int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb_idx], rnti, data[tb_idx], cw_idx, tb_idx, &acks[tb_idx]); + + /* Check if there has been any execution error */ + if (ret) { + return ret; + } } + + cw_idx = (cw_idx + 1) % SRSLTE_MAX_CODEWORDS; } } @@ -767,20 +779,23 @@ int srslte_pdsch_encode(srslte_pdsch_t *q, } /* If both transport block size is zero return error */ - if (cfg->grant.mcs[0].tbs == 0) { + if (!nof_tb) { return SRSLTE_ERROR_INVALID_INPUTS; } - if (cfg->nbits[0].nof_re > q->max_re) { + if (cfg->nbits[0].nof_re > q->max_re || cfg->nbits[1].nof_re > q->max_re) { fprintf(stderr, "Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n", cfg->nbits[0].nof_re, q->max_re, q->cell.nof_prb); return SRSLTE_ERROR_INVALID_INPUTS; } - 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); + /* Implementation of 3GPP 36.212 Table 5.3.3.1.5-1 and Table 5.3.3.1.5-2 */ + uint32_t cw_idx = (nof_tb == SRSLTE_MAX_TB && cfg->tb_cw_swap) ? 1 : 0; + for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) { + if (cfg->grant.tb_en[tb_idx]) { + ret |= srslte_pdsch_codeword_encode(q, cfg, softbuffers[tb_idx], rnti, data[tb_idx], cw_idx, tb_idx); + cw_idx = (cw_idx + 1) % SRSLTE_MAX_CODEWORDS; } } diff --git a/lib/src/phy/phch/ra.c b/lib/src/phy/phch/ra.c index be10c304c..735794e35 100644 --- a/lib/src/phy/phch/ra.c +++ b/lib/src/phy/phch/ra.c @@ -185,108 +185,87 @@ int srslte_ra_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, srslte_ra_ } } -srslte_mod_t last_mod[8]; -uint32_t last_ul_tbs_idx[8]; -uint32_t last_dl_tbs[8]; -uint32_t last_dl_tbs2[8]; - -static int ul_dci_to_grant_mcs(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant, uint32_t harq_pid) { - int tbs = -1; +static void ul_dci_to_grant_mcs(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant) { // 8.6.2 First paragraph if (dci->mcs_idx <= 28) { /* Table 8.6.1-1 on 36.213 */ if (dci->mcs_idx < 11) { grant->mcs.mod = SRSLTE_MOD_QPSK; - tbs = srslte_ra_tbs_from_idx(dci->mcs_idx, grant->L_prb); - last_ul_tbs_idx[harq_pid%8] = dci->mcs_idx; + grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx, grant->L_prb); } else if (dci->mcs_idx < 21) { grant->mcs.mod = SRSLTE_MOD_16QAM; - tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-1, grant->L_prb); - last_ul_tbs_idx[harq_pid%8] = dci->mcs_idx-1; + grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-1, grant->L_prb); } else if (dci->mcs_idx < 29) { grant->mcs.mod = SRSLTE_MOD_64QAM; - tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-2, grant->L_prb); - last_ul_tbs_idx[harq_pid%8] = dci->mcs_idx-2; + grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-2, grant->L_prb); } else { fprintf(stderr, "Invalid MCS index %d\n", dci->mcs_idx); } - last_mod[harq_pid%8] = grant->mcs.mod; } else if (dci->mcs_idx == 29 && dci->cqi_request && grant->L_prb <= 4) { // 8.6.1 and 8.6.2 36.213 second paragraph grant->mcs.mod = SRSLTE_MOD_QPSK; - tbs = srslte_ra_tbs_from_idx(last_ul_tbs_idx[harq_pid%8], grant->L_prb); - dci->rv_idx = 1; + grant->mcs.tbs = 0; + dci->rv_idx = 1; } else if (dci->mcs_idx >= 29) { - // Else use last TBS/Modulation and use mcs to obtain rv_idx - tbs = srslte_ra_tbs_from_idx(last_ul_tbs_idx[harq_pid%8], grant->L_prb); - grant->mcs.mod = last_mod[harq_pid%8]; + // Else use last TBS/Modulation and use mcs to obtain rv_idx + grant->mcs.tbs = -1; + grant->mcs.mod = SRSLTE_MOD_LAST; dci->rv_idx = dci->mcs_idx - 28; - DEBUG("TTI=%d, harq_pid=%d, mcs_idx=%d, tbs=%d, mod=%d, rv=%d\n", - harq_pid, harq_pid%8, dci->mcs_idx, tbs/8, grant->mcs.mod, dci->rv_idx); - } - if (tbs < 0) { - fprintf(stderr, "Error computing TBS\n"); - return SRSLTE_ERROR; - } else { - grant->mcs.tbs = (uint32_t) tbs; - return SRSLTE_SUCCESS; + DEBUG("mcs_idx=%d, tbs=%d, mod=%d, rv=%d\n", + dci->mcs_idx, grant->mcs.tbs/8, grant->mcs.mod, dci->rv_idx); } } -void srslte_ra_ul_grant_to_nbits(srslte_ra_ul_grant_t *grant, srslte_cp_t cp, uint32_t N_srs, srslte_ra_nbits_t *nbits) +void srslte_ra_ul_grant_to_nbits(srslte_ra_ul_grant_t *grant, srslte_cp_t cp, uint32_t N_srs, srslte_ra_nbits_t *nbits) { - nbits->nof_symb = 2*(SRSLTE_CP_NSYMB(cp)-1) - N_srs; + nbits->nof_symb = 2*(SRSLTE_CP_NSYMB(cp)-1) - N_srs; nbits->nof_re = nbits->nof_symb*grant->M_sc; nbits->nof_bits = nbits->nof_re * grant->Qm; } /** Compute PRB allocation for Uplink as defined in 8.1 and 8.4 of 36.213 */ -int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, uint32_t nof_prb, uint32_t n_rb_ho, srslte_ra_ul_grant_t *grant, - uint32_t harq_pid) +int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, uint32_t nof_prb, uint32_t n_rb_ho, srslte_ra_ul_grant_t *grant) { - - // Compute PRB allocation + + // Compute PRB allocation if (!srslte_ra_ul_dci_to_grant_prb_allocation(dci, grant, n_rb_ho, nof_prb)) { - - // Compute MCS - if (!ul_dci_to_grant_mcs(dci, grant, harq_pid)) { - - // Fill rest of grant structure - grant->mcs.idx = dci->mcs_idx; - grant->M_sc = grant->L_prb*SRSLTE_NRE; - grant->M_sc_init = grant->M_sc; // FIXME: What should M_sc_init be? - grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod); - } else { - fprintf(stderr, "Error computing MCS\n"); - return SRSLTE_ERROR; - } + + // Compute MCS + ul_dci_to_grant_mcs(dci, grant); + + // Fill rest of grant structure + grant->mcs.idx = dci->mcs_idx; + grant->M_sc = grant->L_prb*SRSLTE_NRE; + grant->M_sc_init = grant->M_sc; // FIXME: What should M_sc_init be? + grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod); + } else { printf("Error computing UL PRB allocation\n"); - return SRSLTE_ERROR; + return SRSLTE_ERROR; } return SRSLTE_SUCCESS; } -uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t cell, uint32_t nof_prb, uint32_t nof_ctrl_symbols) +uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t cell, uint32_t nof_prb, uint32_t nof_ctrl_symbols) { - uint32_t nof_refs = 0; + uint32_t nof_refs = 0; uint32_t nof_symb = 2*SRSLTE_CP_NSYMB(cell.cp)-nof_ctrl_symbols; switch(cell.nof_ports) { - case 1: - nof_refs = 2*3; - break; - case 2: - nof_refs = 4*3; - break; - case 4: - nof_refs = 4*4; - break; + case 1: + nof_refs = 2*3; + break; + case 2: + nof_refs = 4*3; + break; + case 4: + nof_refs = 4*4; + break; } return nof_prb * (nof_symb*SRSLTE_NRE-nof_refs); } /* Computes the number of RE for each PRB in the prb_dist structure */ -uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t cell, +uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t cell, uint32_t sf_idx, uint32_t nof_ctrl_symbols) { uint32_t j, s; @@ -300,7 +279,7 @@ uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t ce } } } - return nof_re; + return nof_re; } @@ -315,7 +294,7 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_ uint32_t bitmask; uint32_t P = srslte_ra_type0_P(nof_prb); uint32_t n_rb_rbg_subset, n_rb_type1; - + bzero(grant, sizeof(srslte_ra_dl_grant_t)); switch (dci->alloc_type) { case SRSLTE_RA_ALLOC_TYPE0: @@ -352,14 +331,14 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_ * P * P + dci->type1_alloc.rbg_subset * P + (i + shift) % P] = true; grant->nof_prb++; } else { - return SRSLTE_ERROR; + return SRSLTE_ERROR; } } } memcpy(&grant->prb_idx[1], &grant->prb_idx[0], SRSLTE_MAX_PRB*sizeof(bool)); break; case SRSLTE_RA_ALLOC_TYPE2: - if (dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) { + if (dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) { for (i = 0; i < dci->type2_alloc.L_crb; i++) { grant->prb_idx[0][i + dci->type2_alloc.RB_start] = true; grant->nof_prb++; @@ -408,13 +387,13 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_ if (n_tilde_prb_odd < nof_prb) { grant->prb_idx[0][n_tilde_prb_odd] = true; } else { - return SRSLTE_ERROR; + return SRSLTE_ERROR; } } else { if (n_tilde_prb_odd + N_gap - N_tilde_vrb / 2 < nof_prb) { grant->prb_idx[0][n_tilde_prb_odd + N_gap - N_tilde_vrb / 2] = true; } else { - return SRSLTE_ERROR; + return SRSLTE_ERROR; } } grant->nof_prb++; @@ -422,13 +401,13 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_ if(n_tilde_prb_even < nof_prb) { grant->prb_idx[1][n_tilde_prb_even] = true; } else { - return SRSLTE_ERROR; + return SRSLTE_ERROR; } } else { if (n_tilde_prb_even + N_gap - N_tilde_vrb / 2 < nof_prb) { grant->prb_idx[1][n_tilde_prb_even + N_gap - N_tilde_vrb / 2] = true; } else { - return SRSLTE_ERROR; + return SRSLTE_ERROR; } } } @@ -442,8 +421,7 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_ } int srslte_dl_fill_ra_mcs(srslte_ra_mcs_t *mcs, uint32_t nprb) { - uint32_t i_tbs = 0; - int tbs = -1; + int i_tbs = 0; if (mcs->idx < 10) { mcs->mod = SRSLTE_MOD_QPSK; i_tbs = mcs->idx; @@ -455,30 +433,26 @@ int srslte_dl_fill_ra_mcs(srslte_ra_mcs_t *mcs, uint32_t nprb) { i_tbs = mcs->idx-2; } else if (mcs->idx == 29) { mcs->mod = SRSLTE_MOD_QPSK; - tbs = 0; - i_tbs = 0; + i_tbs = -1; } else if (mcs->idx == 30) { mcs->mod = SRSLTE_MOD_16QAM; - tbs = 0; - i_tbs = 0; + i_tbs = -1; } else if (mcs->idx == 31) { mcs->mod = SRSLTE_MOD_64QAM; - tbs = 0; - i_tbs = 0; + i_tbs = -1; } - - if (tbs == -1) { + + int tbs = -1; + if (i_tbs >= 0) { tbs = srslte_ra_tbs_from_idx(i_tbs, nprb); - if (tbs >= 0) { - mcs->tbs = tbs; - } - } - return tbs; + mcs->tbs = tbs; + } + return tbs; } int srslte_dl_fill_ra_mcs_pmch(srslte_ra_mcs_t *mcs, uint32_t nprb) { - uint32_t i_tbs = 0; - int tbs = -1; + uint32_t i_tbs = 0; + int tbs = -1; if (mcs->idx < 5) { mcs->mod = SRSLTE_MOD_QPSK; i_tbs = mcs->idx*2; @@ -492,7 +466,7 @@ int srslte_dl_fill_ra_mcs_pmch(srslte_ra_mcs_t *mcs, uint32_t nprb) { mcs->mod = SRSLTE_MOD_64QAM; i_tbs = mcs->idx + 5; }else if (mcs->idx < 28) { - //mcs->mod = SRSLTE_MOD_256QAM; + //mcs->mod = SRSLTE_MOD_256QAM; i_tbs = mcs->idx + 5; }else if (mcs->idx == 28) { mcs->mod = SRSLTE_MOD_QPSK; @@ -511,15 +485,15 @@ int srslte_dl_fill_ra_mcs_pmch(srslte_ra_mcs_t *mcs, uint32_t nprb) { tbs = 0; i_tbs = 0; } - - + + if (tbs == -1) { tbs = srslte_ra_tbs_from_idx(i_tbs, nprb); if (tbs >= 0) { - mcs->tbs = tbs; + mcs->tbs = tbs; } - } - return tbs; + } + return tbs; } /* Modulation order and transport block size determination 7.1.7 in 36.213 @@ -530,9 +504,9 @@ int srslte_dl_fill_ra_mcs_pmch(srslte_ra_mcs_t *mcs, uint32_t nprb) { * */ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *grant, bool crc_is_crnti) { uint32_t n_prb=0; - int tbs = -1; - uint32_t i_tbs = 0; - + int tbs = -1; + uint32_t i_tbs = 0; + if (!crc_is_crnti) { if (dci->dci_is_1a) { n_prb = dci->type2_alloc.n_prb1a == SRSLTE_RA_TYPE2_NPRB1A_2 ? 2 : 3; @@ -546,35 +520,21 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr } } else { fprintf(stderr, "Error decoding DCI: P/SI/RA-RNTI supports Format1A/1C only\n"); - return SRSLTE_ERROR; + return SRSLTE_ERROR; } grant->mcs[0].mod = SRSLTE_MOD_QPSK; grant->mcs[0].tbs = (uint32_t) tbs; } else { n_prb = grant->nof_prb; - grant->nof_tb = 0; if (dci->tb_en[0]) { grant->mcs[0].idx = dci->mcs_idx; - tbs = srslte_dl_fill_ra_mcs(&grant->mcs[0], n_prb); - if (tbs) { - last_dl_tbs[dci->harq_process%8] = tbs; - } else { - // For mcs>=29, set last TBS received for this PID - grant->mcs[0].tbs = last_dl_tbs[dci->harq_process%8]; - } - grant->nof_tb++; + grant->mcs[0].tbs = srslte_dl_fill_ra_mcs(&grant->mcs[0], n_prb); } else { grant->mcs[0].tbs = 0; } if (dci->tb_en[1]) { grant->mcs[1].idx = dci->mcs_idx_1; - tbs = srslte_dl_fill_ra_mcs(&grant->mcs[1], n_prb); - if (tbs) { - last_dl_tbs2[dci->harq_process%8] = tbs; - } else { - // For mcs>=29, set last TBS received for this PID - grant->mcs[1].tbs = last_dl_tbs2[dci->harq_process%8]; - } + grant->mcs[1].tbs = srslte_dl_fill_ra_mcs(&grant->mcs[1], n_prb); } else { grant->mcs[1].tbs = 0; } @@ -586,8 +546,9 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr } } grant->pinfo = dci->pinfo; + grant->tb_cw_swap = dci->tb_cw_swap; - if (tbs < 0) { + if (grant->mcs[0].tbs < 0 || grant->mcs[1].tbs < 0) { return SRSLTE_ERROR; } else { return SRSLTE_SUCCESS; @@ -599,10 +560,10 @@ void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant, uint32_t cfi, srsl { // Compute number of RE for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { + 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; 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; if (SRSLTE_SF_NORM == grant->sf_type) { nbits[i].nof_symb = 2 * SRSLTE_CP_NSYMB(cell.cp) - nbits[0].lstart; } else if (SRSLTE_SF_MBSFN == grant->sf_type) { @@ -622,10 +583,12 @@ int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci, if (msg_rnti >= SRSLTE_CRNTI_START && msg_rnti <= SRSLTE_CRNTI_END) { crc_is_crnti = true; } - // Compute PRB allocation - if (!srslte_ra_dl_dci_to_grant_prb_allocation(dci, grant, nof_prb)) { - // Compute MCS - if (!dl_dci_to_grant_mcs(dci, grant, crc_is_crnti)) { + // Compute PRB allocation + int ret =srslte_ra_dl_dci_to_grant_prb_allocation(dci, grant, nof_prb); + if (!ret) { + // Compute MCS + ret = dl_dci_to_grant_mcs(dci, grant, crc_is_crnti); + if (ret == SRSLTE_SUCCESS) { // Apply Section 7.1.7.3. If RA-RNTI and Format1C rv_idx=0 if (msg_rnti >= SRSLTE_RARNTI_START && msg_rnti <= SRSLTE_RARNTI_END && dci->dci_is_1c) @@ -907,4 +870,4 @@ void srslte_ra_prb_fprint(FILE *f, srslte_ra_dl_grant_t *grant) { } } -} \ No newline at end of file +} diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index e76fa6aef..930364725 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -458,12 +458,12 @@ static int decode_tb(srslte_sch_t *q, if (cb_segm->F) { fprintf(stderr, "Error filler bits are not supported. Use standard TBS\n"); - return SRSLTE_ERROR; + return SRSLTE_ERROR_INVALID_INPUTS; } if (cb_segm->C > softbuffer->max_cb) { fprintf(stderr, "Error number of CB (%d) exceeds soft buffer size (%d CBs)\n", cb_segm->C, softbuffer->max_cb); - return SRSLTE_ERROR; + return SRSLTE_ERROR_INVALID_INPUTS; } bool crc_ok = true; @@ -517,15 +517,15 @@ int srslte_dlsch_decode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuf int srslte_dlsch_decode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, - int16_t *e_bits, uint8_t *data, int codeword_idx) { + int16_t *e_bits, uint8_t *data, int tb_idx) { uint32_t Nl = 1; if (cfg->nof_layers != SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)) { Nl = 2; } - return decode_tb(q, softbuffer, &cfg->cb_segm[codeword_idx], - cfg->grant.Qm[codeword_idx] * Nl, cfg->rv[codeword_idx], cfg->nbits[codeword_idx].nof_bits, + return decode_tb(q, softbuffer, &cfg->cb_segm[tb_idx], + cfg->grant.Qm[tb_idx] * Nl, cfg->rv[tb_idx], cfg->nbits[tb_idx].nof_bits, e_bits, data); } @@ -546,15 +546,15 @@ int srslte_dlsch_encode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuf } int srslte_dlsch_encode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, - uint8_t *data, uint8_t *e_bits, int codeword_idx) { + uint8_t *data, uint8_t *e_bits, int tb_idx) { uint32_t Nl = 1; if (cfg->nof_layers != SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)) { Nl = 2; } - return encode_tb(q, softbuffer, &cfg->cb_segm[codeword_idx], cfg->grant.Qm[codeword_idx]*Nl, cfg->rv[codeword_idx], - cfg->nbits[codeword_idx].nof_bits, data, e_bits); + return encode_tb(q, softbuffer, &cfg->cb_segm[tb_idx], cfg->grant.Qm[tb_idx]*Nl, cfg->rv[tb_idx], + cfg->nbits[tb_idx].nof_bits, data, e_bits); } /* Compute the interleaving function on-the-fly, because it depends on number of RI bits diff --git a/lib/src/phy/phch/test/CMakeLists.txt b/lib/src/phy/phch/test/CMakeLists.txt index 6e6b8c024..f1a2bccee 100644 --- a/lib/src/phy/phch/test/CMakeLists.txt +++ b/lib/src/phy/phch/test/CMakeLists.txt @@ -119,6 +119,14 @@ add_test(pdsch_test_multiplex1cw_p0_50 pdsch_test -x multiplex -a 2 -p 0 -n 50) add_test(pdsch_test_multiplex1cw_p0_75 pdsch_test -x multiplex -a 2 -p 0 -n 75) add_test(pdsch_test_multiplex1cw_p0_100 pdsch_test -x multiplex -a 2 -p 0 -n 100) +# PDSCH test for Spatial Multiplex transmision mode with PMI = 0 (1 codeword, swapped) +add_test(pdsch_test_multiplex1cw_p0_6_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 6 -F 1) +add_test(pdsch_test_multiplex1cw_p0_15_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 15) +add_test(pdsch_test_multiplex1cw_p0_25_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 25) +add_test(pdsch_test_multiplex1cw_p0_50_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 50) +add_test(pdsch_test_multiplex1cw_p0_75_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 75) +add_test(pdsch_test_multiplex1cw_p0_100_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 100) + # PDSCH test for Spatial Multiplex transmision mode with PMI = 1 (1 codeword) add_test(pdsch_test_multiplex1cw_p1_6 pdsch_test -x multiplex -a 2 -p 1 -n 6) add_test(pdsch_test_multiplex1cw_p1_12 pdsch_test -x multiplex -a 2 -p 1 -n 12) @@ -151,6 +159,14 @@ add_test(pdsch_test_multiplex2cw_p0_50 pdsch_test -x multiplex -a 2 -t 0 -p 0 - add_test(pdsch_test_multiplex2cw_p0_75 pdsch_test -x multiplex -a 2 -t 0 -p 0 -n 75) add_test(pdsch_test_multiplex2cw_p0_100 pdsch_test -x multiplex -a 2 -t 0 -p 0 -n 100) +# PDSCH test for Spatial Multiplex transmision mode with PMI = 0 (2 codeword, swapped) +add_test(pdsch_test_multiplex2cw_p0_6_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -M 28 -n 6 -w -F 1) +add_test(pdsch_test_multiplex2cw_p0_12_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -m 28 -n 12 -w) +add_test(pdsch_test_multiplex2cw_p0_25_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -M 28 -n 25 -w) +add_test(pdsch_test_multiplex2cw_p0_50_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -m 28 -n 50 -w) +add_test(pdsch_test_multiplex2cw_p0_75_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -M 28 -n 75 -w) +add_test(pdsch_test_multiplex2cw_p0_100_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -m 28 -n 100 -w) + # PDSCH test for Spatial Multiplex transmision mode with PMI = 1 (2 codeword) add_test(pdsch_test_multiplex2cw_p1_6 pdsch_test -x multiplex -a 2 -t 0 -p 1 -n 6) add_test(pdsch_test_multiplex2cw_p1_12 pdsch_test -x multiplex -a 2 -t 0 -p 1 -n 12) diff --git a/lib/src/phy/phch/test/pbch_file_test.c b/lib/src/phy/phch/test/pbch_file_test.c index 734640d55..2ca12e4c9 100644 --- a/lib/src/phy/phch/test/pbch_file_test.c +++ b/lib/src/phy/phch/test/pbch_file_test.c @@ -140,7 +140,7 @@ int base_init() { return -1; } - if (srslte_ofdm_init_(&fft, cell.cp, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { + if (srslte_ofdm_init_(&fft, cell.cp, input_buffer, fft_buffer, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { fprintf(stderr, "Error initializing FFT\n"); return -1; } @@ -203,7 +203,7 @@ int main(int argc, char **argv) { if (nread > 0) { // process 1st subframe only - srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer); + srslte_ofdm_rx_sf(&fft); /* Get channel estimates for each port */ srslte_chest_dl_estimate(&chest, fft_buffer, ce, 0); diff --git a/lib/src/phy/phch/test/pcfich_file_test.c b/lib/src/phy/phch/test/pcfich_file_test.c index dfb8d72e3..e92d6c7ba 100644 --- a/lib/src/phy/phch/test/pcfich_file_test.c +++ b/lib/src/phy/phch/test/pcfich_file_test.c @@ -120,15 +120,15 @@ int base_init() { fmatlab = NULL; } - flen = SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb)); + flen = SRSLTE_SF_LEN(srslte_symbol_sz_power2(cell.nof_prb)); - input_buffer = malloc(flen * sizeof(cf_t)); + input_buffer = srslte_vec_malloc(flen * sizeof(cf_t)); if (!input_buffer) { perror("malloc"); exit(-1); } - fft_buffer = malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); + fft_buffer = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); if (!fft_buffer) { perror("malloc"); return -1; @@ -151,7 +151,7 @@ int base_init() { return -1; } - if (srslte_ofdm_init_(&fft, cell.cp, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { + if (srslte_ofdm_init_(&fft, cell.cp, input_buffer, fft_buffer, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { fprintf(stderr, "Error initializing FFT\n"); return -1; } @@ -215,7 +215,7 @@ int main(int argc, char **argv) { n = srslte_filesource_read(&fsrc, input_buffer, flen); - srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer); + srslte_ofdm_rx_sf(&fft); if (fmatlab) { fprintf(fmatlab, "infft="); diff --git a/lib/src/phy/phch/test/pdcch_file_test.c b/lib/src/phy/phch/test/pdcch_file_test.c index d4ceed4b6..5482d9f98 100644 --- a/lib/src/phy/phch/test/pdcch_file_test.c +++ b/lib/src/phy/phch/test/pdcch_file_test.c @@ -126,7 +126,7 @@ int base_init() { exit(-1); } - flen = 2 * (SRSLTE_SLOT_LEN(srslte_symbol_sz(cell.nof_prb))); + flen = 2 * (SRSLTE_SLOT_LEN(srslte_symbol_sz_power2(cell.nof_prb))); input_buffer = malloc(flen * sizeof(cf_t)); if (!input_buffer) { @@ -157,7 +157,7 @@ int base_init() { return -1; } - if (srslte_ofdm_init_(&fft, cell.cp, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { + if (srslte_ofdm_init_(&fft, cell.cp, input_buffer, fft_buffer, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { fprintf(stderr, "Error initializing FFT\n"); return -1; } @@ -231,7 +231,7 @@ int main(int argc, char **argv) { INFO("Reading %d samples sub-frame %d\n", flen, frame_cnt); - srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer); + srslte_ofdm_rx_sf(&fft); /* Get channel estimates for each port */ srslte_chest_dl_estimate(&chest, fft_buffer, ce, frame_cnt %10); diff --git a/lib/src/phy/phch/test/pdsch_pdcch_file_test.c b/lib/src/phy/phch/test/pdsch_pdcch_file_test.c index 90c0e1c17..0faf7eca1 100644 --- a/lib/src/phy/phch/test/pdsch_pdcch_file_test.c +++ b/lib/src/phy/phch/test/pdsch_pdcch_file_test.c @@ -129,7 +129,7 @@ int base_init() { exit(-1); } - flen = 2 * (SRSLTE_SLOT_LEN(srslte_symbol_sz(cell.nof_prb))); + flen = SRSLTE_SF_LEN(srslte_symbol_sz_power2(cell.nof_prb)); input_buffer[0] = malloc(flen * sizeof(cf_t)); if (!input_buffer[0]) { @@ -137,7 +137,7 @@ int base_init() { exit(-1); } - if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) { + if (srslte_ue_dl_init(&ue_dl, input_buffer, cell.nof_prb, 1)) { fprintf(stderr, "Error initializing UE DL\n"); return -1; } diff --git a/lib/src/phy/phch/test/pdsch_test.c b/lib/src/phy/phch/test/pdsch_test.c index 0c98079b9..b97e8b299 100644 --- a/lib/src/phy/phch/test/pdsch_test.c +++ b/lib/src/phy/phch/test/pdsch_test.c @@ -59,6 +59,7 @@ uint32_t subframe = 1; int rv_idx[SRSLTE_MAX_CODEWORDS] = {0, 1}; uint16_t rnti = 1234; uint32_t nof_rx_antennas = 1; +bool tb_cw_swap = false; uint32_t pmi = 0; char *input_file = NULL; @@ -77,12 +78,13 @@ void usage(char *prog) { printf("\t-n cell.nof_prb [Default %d]\n", cell.nof_prb); printf("\t-a nof_rx_antennas [Default %d]\n", nof_rx_antennas); printf("\t-p pmi (multiplex only) [Default %d]\n", pmi); + printf("\t-w Swap Transport Blocks\n"); printf("\t-v [set srslte_verbose to debug, default none]\n"); } void parse_args(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "fmMcsrtRFpnavx")) != -1) { + while ((opt = getopt(argc, argv, "fmMcsrtRFpnawvx")) != -1) { switch(opt) { case 'f': input_file = argv[optind]; @@ -123,6 +125,9 @@ void parse_args(int argc, char **argv) { case 'a': nof_rx_antennas = (uint32_t) atoi(argv[optind]); break; + case 'w': + tb_cw_swap = true; + break; case 'v': srslte_verbose++; break; @@ -207,6 +212,11 @@ int main(int argc, char **argv) { dci.tb_en[1] = true; } + /* Enable swap */ + if (SRSLTE_RA_DL_GRANT_NOF_TB(&dci) == SRSLTE_MAX_TB && tb_cw_swap) { + dci.tb_cw_swap = tb_cw_swap; + } + /* Generate grant from DCI */ if (srslte_ra_dl_dci_to_grant(&dci, cell.nof_prb, rnti, &grant)) { fprintf(stderr, "Error computing resource allocation\n"); @@ -255,7 +265,7 @@ int main(int argc, char **argv) { } - for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { + for (i = 0; i < SRSLTE_MAX_TB; i++) { if (grant.tb_en[i]) { data_tx[i] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs[i].tbs); if (!data_tx[i]) { @@ -271,6 +281,9 @@ int main(int argc, char **argv) { } bzero(data_rx[i], sizeof(uint8_t) * grant.mcs[i].tbs); + } else { + data_tx[i] = NULL; + data_rx[i] = NULL; } } diff --git a/lib/src/phy/phch/test/phich_file_test.c b/lib/src/phy/phch/test/phich_file_test.c index d7078f933..65f7ce9c0 100644 --- a/lib/src/phy/phch/test/phich_file_test.c +++ b/lib/src/phy/phch/test/phich_file_test.c @@ -144,7 +144,7 @@ int base_init() { fmatlab = NULL; } - flen = SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb)); + flen = SRSLTE_SF_LEN(srslte_symbol_sz_power2(cell.nof_prb)); input_buffer = malloc(flen * sizeof(cf_t)); if (!input_buffer) { @@ -175,7 +175,7 @@ int base_init() { return -1; } - if (srslte_ofdm_init_(&fft, cell.cp, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { + if (srslte_ofdm_init_(&fft, cell.cp, input_buffer, fft_buffer, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { fprintf(stderr, "Error initializing FFT\n"); return -1; } @@ -242,7 +242,7 @@ int main(int argc, char **argv) { n = srslte_filesource_read(&fsrc, input_buffer, flen); - srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer); + srslte_ofdm_rx_sf(&fft); if (fmatlab) { fprintf(fmatlab, "infft="); diff --git a/lib/src/phy/phch/test/pmch_file_test.c b/lib/src/phy/phch/test/pmch_file_test.c index ac66072fa..6586b2ee9 100644 --- a/lib/src/phy/phch/test/pmch_file_test.c +++ b/lib/src/phy/phch/test/pmch_file_test.c @@ -140,7 +140,7 @@ int base_init() { exit(-1); } - if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) { + if (srslte_ue_dl_init(&ue_dl, input_buffer, cell.nof_prb, 1)) { fprintf(stderr, "Error initializing UE DL\n"); return -1; } diff --git a/lib/src/phy/phch/test/pmch_test.c b/lib/src/phy/phch/test/pmch_test.c index a187ca2bb..bf415e692 100644 --- a/lib/src/phy/phch/test/pmch_test.c +++ b/lib/src/phy/phch/test/pmch_test.c @@ -139,7 +139,7 @@ cf_t *tx_slot_symbols[SRSLTE_MAX_PORTS]; cf_t *rx_slot_symbols[SRSLTE_MAX_PORTS]; srslte_pmch_t pmch_tx, pmch_rx; srslte_pdsch_cfg_t pmch_cfg; -srslte_ofdm_t ifft_mbsfn, fft_mbsfn; +srslte_ofdm_t ifft_mbsfn[SRSLTE_MAX_PORTS], fft_mbsfn[SRSLTE_MAX_PORTS]; int main(int argc, char **argv) { uint32_t i, j, k; @@ -167,12 +167,11 @@ int main(int argc, char **argv) { /* If transport block 0 is enabled */ grant.tb_en[0] = true; grant.tb_en[1] = false; - grant.nof_tb = 1; grant.mcs[0].idx = mcs_idx; - + grant.nof_prb = cell.nof_prb; grant.sf_type = SRSLTE_SF_MBSFN; - + srslte_dl_fill_ra_mcs(&grant.mcs[0], cell.nof_prb); grant.Qm[0] = srslte_mod_bits_x_symbol(grant.mcs[0].mod); for(int i = 0; i < 2; i++){ @@ -181,41 +180,6 @@ int main(int argc, char **argv) { } } - - -#ifdef DO_OFDM - - if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn, SRSLTE_CP_EXT, cell.nof_prb)) { - fprintf(stderr, "Error creating iFFT object\n"); - exit(-1); - } - if (srslte_ofdm_rx_init_mbsfn(&fft_mbsfn, SRSLTE_CP_EXT, cell.nof_prb)) { - fprintf(stderr, "Error creating iFFT object\n"); - exit(-1); - } - - srslte_ofdm_set_non_mbsfn_region(&ifft_mbsfn, non_mbsfn_region); - srslte_ofdm_set_non_mbsfn_region(&fft_mbsfn, non_mbsfn_region); - srslte_ofdm_set_normalize(&ifft_mbsfn, true); - srslte_ofdm_set_normalize(&fft_mbsfn, true); - - - for (i = 0; i < cell.nof_ports; i++) { - tx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); - } - - for (i = 0; i < nof_rx_antennas; i++) { - rx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); - } -#endif /* DO_OFDM */ - - /* Configure PDSCH */ - - if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, subframe)) { - fprintf(stderr, "Error configuring PMCH\n"); - exit(-1); - } - /* init memory */ for (i=0;idevice, SOAPY_SDR_RX, 0, rate) != 0) { - printf("setBandwidth Rx failed: %s\n", SoapySDRDevice_lastError()); - return SRSLTE_ERROR; - } - return SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_RX,0); } @@ -302,11 +297,6 @@ double rf_soapy_set_tx_srate(void *h, double rate) return SRSLTE_ERROR; } - if (SoapySDRDevice_setBandwidth(handler->device, SOAPY_SDR_TX, 0, rate) != 0) { - printf("setBandwidth Tx failed: %s\n", SoapySDRDevice_lastError()); - return SRSLTE_ERROR; - } - return SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_TX,0); } diff --git a/lib/src/phy/sync/test/sync_test.c b/lib/src/phy/sync/test/sync_test.c index 8715b316e..1e3951884 100644 --- a/lib/src/phy/sync/test/sync_test.c +++ b/lib/src/phy/sync/test/sync_test.c @@ -108,8 +108,8 @@ int main(int argc, char **argv) { perror("malloc"); exit(-1); } - - if (srslte_ofdm_tx_init(&ifft, cp, nof_prb)) { + + if (srslte_ofdm_tx_init(&ifft, cp, buffer, fft_buffer, nof_prb)) { fprintf(stderr, "Error creating iFFT object\n"); exit(-1); } @@ -150,8 +150,14 @@ int main(int argc, char **argv) { /* Transform to OFDM symbols */ memset(fft_buffer, 0, sizeof(cf_t) * FLEN); - srslte_ofdm_tx_sf(&ifft, buffer, &fft_buffer[offset]); + srslte_ofdm_tx_sf(&ifft); + /* Apply sample offset */ + for (int i = 0; i < FLEN; i++) { + fft_buffer[FLEN - i - 1 + offset] = fft_buffer[FLEN - i - 1]; + } + bzero(fft_buffer, sizeof(cf_t) * offset); + if (srslte_sync_find(&syncobj, fft_buffer, 0, &find_idx) < 0) { fprintf(stderr, "Error running srslte_sync_find\n"); exit(-1); diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index c4e2d3f6c..1c3b79440 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -53,6 +53,7 @@ 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, + cf_t *in_buffer[SRSLTE_MAX_PORTS], uint32_t max_prb, uint32_t nof_rx_antennas) { @@ -73,12 +74,35 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q, q->sample_offset = 0; 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; + for (int j = 0; j < SRSLTE_MAX_PORTS; j++) { + 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;ice_m[i][j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t)); + if (!q->ce_m[i][j]) { + perror("malloc"); + goto clean_exit; + } + bzero(q->ce_m[i][j], MAX_SFLEN_RE * sizeof(cf_t)); + } } - - if (srslte_ofdm_rx_init_mbsfn(&q->fft_mbsfn, SRSLTE_CP_EXT, max_prb)) { + + q->sf_symbols = q->sf_symbols_m[0]; + for (int i=0;ice[i] = q->ce_m[i][0]; + } + + for (int i = 0; i < nof_rx_antennas; i++) { + if (srslte_ofdm_rx_init(&q->fft[i], SRSLTE_CP_NORM, in_buffer[i], q->sf_symbols_m[i], max_prb)) { + fprintf(stderr, "Error initiating FFT\n"); + goto clean_exit; + } + } + + if (srslte_ofdm_rx_init_mbsfn(&q->fft_mbsfn, SRSLTE_CP_EXT, in_buffer[0], q->sf_symbols_m[0], max_prb)) { fprintf(stderr, "Error initiating FFT for MBSFN subframes \n"); goto clean_exit; } @@ -127,28 +151,7 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q, 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 < SRSLTE_MAX_PORTS; j++) { - 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;ice_m[i][j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t)); - if (!q->ce_m[i][j]) { - perror("malloc"); - goto clean_exit; - } - bzero(q->ce_m[i][j], MAX_SFLEN_RE * sizeof(cf_t)); - } - } - - q->sf_symbols = q->sf_symbols_m[0]; - for (int i=0;ice[i] = q->ce_m[i][0]; - } + srslte_cfo_set_tol(&q->sfo_correct, 1e-5f/q->fft[0].symbol_sz); ret = SRSLTE_SUCCESS; } else { @@ -164,7 +167,9 @@ clean_exit: void srslte_ue_dl_free(srslte_ue_dl_t *q) { if (q) { - srslte_ofdm_rx_free(&q->fft); + for (int port = 0; port < SRSLTE_MAX_PORTS; port++) { + srslte_ofdm_rx_free(&q->fft[port]); + } srslte_ofdm_rx_free(&q->fft_mbsfn); srslte_chest_dl_free(&q->chest); srslte_regs_free(&q->regs); @@ -219,10 +224,12 @@ int srslte_ue_dl_set_cell(srslte_ue_dl_t *q, srslte_cell_t cell) 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; + srslte_cfo_set_tol(&q->sfo_correct, 1e-5f/q->fft[0].symbol_sz); + for (int port = 0; port < q->nof_rx_antennas; port++) { + if (srslte_ofdm_rx_set_prb(&q->fft[port], 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"); @@ -339,9 +346,9 @@ int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q, cf_t *input[SRSLTE /* Run FFT for all subframe data */ for (int j=0;jnof_rx_antennas;j++) { if(sf_type == SRSLTE_SF_MBSFN ) { - srslte_ofdm_rx_sf(&q->fft_mbsfn, input[j], q->sf_symbols_m[j]); + srslte_ofdm_rx_sf(&q->fft_mbsfn); }else{ - srslte_ofdm_rx_sf(&q->fft, input[j], q->sf_symbols_m[j]); + srslte_ofdm_rx_sf(&q->fft[j]); } /* Correct SFO multiplying by complex exponential in the time domain */ @@ -351,7 +358,7 @@ int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q, cf_t *input[SRSLTE 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); + q->sample_offset / q->fft[j].symbol_sz); } } } @@ -601,9 +608,9 @@ int srslte_ue_dl_decode_mbsfn(srslte_ue_dl_t * q, //float noise_estimate = 0; grant.sf_type = SRSLTE_SF_MBSFN; - grant.nof_tb = 1; grant.mcs[0].idx = 2; - + grant.tb_en[0] = true; + grant.tb_en[1] = false; grant.nof_prb = q->pmch.cell.nof_prb; srslte_dl_fill_ra_mcs(&grant.mcs[0], grant.nof_prb); srslte_softbuffer_rx_reset_tbs(q->softbuffers[0], (uint32_t) grant.mcs[0].tbs); diff --git a/lib/src/phy/ue/ue_mib.c b/lib/src/phy/ue/ue_mib.c index 46a470ab8..c003a2ba3 100644 --- a/lib/src/phy/ue/ue_mib.c +++ b/lib/src/phy/ue/ue_mib.c @@ -35,7 +35,8 @@ #include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/vector.h" -int srslte_ue_mib_init(srslte_ue_mib_t * q, +int srslte_ue_mib_init(srslte_ue_mib_t * q, + cf_t *in_buffer[SRSLTE_MAX_PORTS], uint32_t max_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -65,7 +66,7 @@ int srslte_ue_mib_init(srslte_ue_mib_t * q, } } - if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) { + if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, in_buffer[0], q->sf_symbols, max_prb)) { fprintf(stderr, "Error initializing FFT\n"); goto clean_exit; } @@ -143,14 +144,14 @@ void srslte_ue_mib_reset(srslte_ue_mib_t * q) srslte_pbch_decode_reset(&q->pbch); } -int srslte_ue_mib_decode(srslte_ue_mib_t * q, cf_t *input, +int srslte_ue_mib_decode(srslte_ue_mib_t * q, uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN], uint32_t *nof_tx_ports, int *sfn_offset) { int ret = SRSLTE_SUCCESS; cf_t *ce_slot1[SRSLTE_MAX_PORTS]; /* Run FFT for the slot symbols */ - srslte_ofdm_rx_sf(&q->fft, input, q->sf_symbols); + srslte_ofdm_rx_sf(&q->fft); /* Get channel estimates of sf idx #0 for each port */ ret = srslte_chest_dl_estimate(&q->chest, q->sf_symbols, q->ce, 0); @@ -198,7 +199,7 @@ int srslte_ue_mib_sync_init_multi(srslte_ue_mib_sync_t *q, } q->nof_rx_antennas = nof_rx_antennas; - if (srslte_ue_mib_init(&q->ue_mib, SRSLTE_UE_MIB_NOF_PRB)) { + if (srslte_ue_mib_init(&q->ue_mib, q->sf_buffer, SRSLTE_UE_MIB_NOF_PRB)) { fprintf(stderr, "Error initiating ue_mib\n"); return SRSLTE_ERROR; } @@ -274,7 +275,7 @@ int srslte_ue_mib_sync_decode(srslte_ue_mib_sync_t * q, return -1; } else if (srslte_ue_sync_get_sfidx(&q->ue_sync) == 0) { if (ret == 1) { - mib_ret = srslte_ue_mib_decode(&q->ue_mib, q->sf_buffer[0], bch_payload, nof_tx_ports, sfn_offset); + mib_ret = srslte_ue_mib_decode(&q->ue_mib, bch_payload, nof_tx_ports, sfn_offset); } else { DEBUG("Resetting PBCH decoder after %d frames\n", q->ue_mib.frame_cnt); srslte_ue_mib_reset(&q->ue_mib); diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index f121c5bac..e9c02ca8b 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -359,6 +359,11 @@ uint32_t srslte_ue_sync_peak_idx(srslte_ue_sync_t *q) { return q->peak_idx; } +void srslte_ue_sync_set_cfo_ema(srslte_ue_sync_t *q, float ema) { + srslte_sync_set_cfo_ema_alpha(&q->sfind, ema); + srslte_sync_set_cfo_ema_alpha(&q->strack, ema); +} + srslte_ue_sync_state_t srslte_ue_sync_get_state(srslte_ue_sync_t *q) { return q->state; } diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index 37dfecd93..853937f7c 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -41,6 +41,7 @@ #define DEFAULT_CFO_TOL 50.0 // Hz int srslte_ue_ul_init(srslte_ue_ul_t *q, + cf_t *out_buffer, uint32_t max_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -50,8 +51,14 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q, ret = SRSLTE_ERROR; bzero(q, sizeof(srslte_ue_ul_t)); - - if (srslte_ofdm_tx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) { + + q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_PRB(max_prb) * sizeof(cf_t)); + if (!q->sf_symbols) { + perror("malloc"); + goto clean_exit; + } + + if (srslte_ofdm_tx_init(&q->fft, SRSLTE_CP_NORM, q->sf_symbols, out_buffer, max_prb)) { fprintf(stderr, "Error initiating FFT\n"); goto clean_exit; } @@ -83,11 +90,6 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q, fprintf(stderr, "Error initiating srslte_refsignal_ul\n"); goto clean_exit; } - 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 * max_prb * sizeof(cf_t)); if (!q->refsignal) { perror("malloc"); @@ -347,7 +349,7 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data, q->last_pucch_format = format; - srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); + srslte_ofdm_tx_sf(&q->fft); if (q->cfo_en) { srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); @@ -417,7 +419,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); + srslte_ofdm_tx_sf(&q->fft); if (q->cfo_en) { srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); @@ -486,7 +488,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); + srslte_ofdm_tx_sf(&q->fft); if (q->cfo_en) { srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); diff --git a/lib/src/phy/utils/bit.c b/lib/src/phy/utils/bit.c index 9ef53c35a..b1ae383a6 100644 --- a/lib/src/phy/utils/bit.c +++ b/lib/src/phy/utils/bit.c @@ -31,6 +31,12 @@ #include #include +#ifdef LV_HAVE_SSE + +#include + +#endif /* LV_HAVE_SSE */ + #include "srslte/phy/utils/bit.h" void srslte_bit_interleave(uint8_t *input, uint8_t *output, uint16_t *interleaver, uint32_t nof_bits) { @@ -53,6 +59,125 @@ void srslte_bit_interleave_w_offset(uint8_t *input, uint8_t *output, uint16_t *i } w_offset_p=8-w_offset; } +#ifdef LV_HAVE_SSE + __m64 m64mask = _mm_setr_pi8((uint8_t) 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1); + __m128i m128mask = _mm_set1_epi64(m64mask); + + union { + uint8_t v[8]; + __m64 m64; + } a, b, c; + + union { + __m128i m128; + uint16_t u16[8]; + uint8_t u8[16]; + struct { + __m64 reg_a; + __m64 reg_b; + } m64; + struct { + uint16_t i0, i1, i2, i3, i4, i5, i6, i7; + } v; + } ipx, epx, ipx2, epx2, b128, a128, c128; + + uint32_t i = st; + for (; i < (nof_bits / 8 - 1); i += 2) { + ipx.m128 = _mm_loadu_si128((__m128i *) (interleaver + (i * 8) - w_offset_p)); + epx.m128 = _mm_shuffle_epi8(ipx.m128, _mm_set_epi8(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E)); + ipx2.m128 = _mm_loadu_si128((__m128i *) (interleaver + ((i + 1) * 8) - w_offset_p)); + epx2.m128 = _mm_shuffle_epi8(ipx2.m128, _mm_set_epi8(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E)); + + epx.m64.reg_b = epx2.m64.reg_a; + + b128.m128 = _mm_and_si128(epx.m128, _mm_set1_epi8(0x7)); + b128.m128 = _mm_shuffle_epi8(m128mask, b128.m128); + + ipx.m128 = _mm_srli_epi16(ipx.m128, 3); + ipx2.m128 = _mm_srli_epi16(ipx2.m128, 3); + + a128.m128 = _mm_set_epi8(input[ipx2.v.i0], + input[ipx2.v.i1], + input[ipx2.v.i2], + input[ipx2.v.i3], + input[ipx2.v.i4], + input[ipx2.v.i5], + input[ipx2.v.i6], + input[ipx2.v.i7], + input[ipx.v.i0], + input[ipx.v.i1], + input[ipx.v.i2], + input[ipx.v.i3], + input[ipx.v.i4], + input[ipx.v.i5], + input[ipx.v.i6], + input[ipx.v.i7]); + + c128.m128 = _mm_cmpeq_epi8(_mm_and_si128(a128.m128, b128.m128), b128.m128); + uint16_t o = (uint16_t) _mm_movemask_epi8(c128.m128); + *((uint16_t *) (output + i)) = o; + } + + for (; i < nof_bits / 8; i++) { + ipx.m128 = _mm_loadu_si128((__m128i *) (interleaver + i * 8 - w_offset_p)); + epx.m128 = _mm_shuffle_epi8(ipx.m128, _mm_set_epi8(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E)); + b.m64 = _mm_and_si64(epx.m64.reg_a, _mm_set1_pi8(0x7)); + b.m64 = _mm_shuffle_pi8(m64mask, b.m64); + + ipx.m128 = _mm_srli_epi16(ipx.m128, 3); + + a.m64 = _mm_set_pi8(input[ipx.v.i0], + input[ipx.v.i1], + input[ipx.v.i2], + input[ipx.v.i3], + input[ipx.v.i4], + input[ipx.v.i5], + input[ipx.v.i6], + input[ipx.v.i7]); + + c.m64 = _mm_cmpeq_pi8(_mm_and_si64(a.m64, b.m64), b.m64); + output[i] = (uint8_t) _mm_movemask_pi8(c.m64); + } + +#if 0 + /* THIS PIECE OF CODE IS FOR CHECKING SIMD BEHAVIOUR. DO NOT ENABLE. */ + uint8_t *output2 = malloc(nof_bits/8); + for (i=st;imsg; - if(pdu_space <= head_len) + if(pdu_space <= head_len + 1) { log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n", rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len); @@ -652,7 +664,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) } // Pull SDUs from queue - while(pdu_space > head_len && tx_sdu_queue.size() > 0) + while(pdu_space > head_len + 1 && tx_sdu_queue.size() > 0) { if(last_li > 0) header.li[header.N_li++] = last_li; diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index b2697178c..4756e2f7c 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -277,8 +277,9 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) int head_len = rlc_um_packed_length(&header); int pdu_space = nof_bytes; - if(pdu_space <= head_len) + if(pdu_space <= head_len + 1) { + pool->deallocate(pdu); log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n", rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len); return 0; @@ -309,7 +310,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) } // Pull SDUs from queue - while(pdu_space > head_len && tx_sdu_queue.size() > 0) + while(pdu_space > head_len + 1 && tx_sdu_queue.size() > 0) { log->debug("pdu_space=%d, head_len=%d\n", pdu_space, head_len); if(last_li > 0) @@ -348,7 +349,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) rlc_um_write_data_pdu_header(&header, pdu); memcpy(payload, pdu->msg, pdu->N_bytes); uint32_t ret = pdu->N_bytes; - log->debug("%sreturning length %d\n", rrc->get_rb_name(lcid).c_str(), pdu->N_bytes); + log->debug("%s returning length %d\n", rrc->get_rb_name(lcid).c_str(), pdu->N_bytes); pool->deallocate(pdu); debug_state(); diff --git a/lib/test/CMakeLists.txt b/lib/test/CMakeLists.txt index a1af8153c..72e9e9100 100644 --- a/lib/test/CMakeLists.txt +++ b/lib/test/CMakeLists.txt @@ -18,5 +18,6 @@ # and at http://www.gnu.org/licenses/. # +add_subdirectory(asn1) add_subdirectory(common) add_subdirectory(upper) diff --git a/lib/test/asn1/CMakeLists.txt b/lib/test/asn1/CMakeLists.txt new file mode 100644 index 000000000..6c52d1972 --- /dev/null +++ b/lib/test/asn1/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright 2013-2017 Software Radio Systems Limited +# +# This file is part of srsLTE +# +# srsLTE is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# srsLTE is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# A copy of the GNU Affero General Public License can be found in +# the LICENSE file in the top-level directory of this distribution +# and at http://www.gnu.org/licenses/. +# + +add_executable(rrc_meas_test rrc_meas_test.cc) +target_link_libraries(rrc_meas_test srslte_common srslte_phy srslte_asn1) +add_test(rrc_meas_test rrc_meas_test) diff --git a/lib/test/asn1/rrc_meas_test.cc b/lib/test/asn1/rrc_meas_test.cc new file mode 100644 index 000000000..63a4d61b6 --- /dev/null +++ b/lib/test/asn1/rrc_meas_test.cc @@ -0,0 +1,91 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2015 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsUE library. + * + * srsUE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsUE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include +#include +#include +#include "srslte/common/log_filter.h" +#include "srslte/asn1/liblte_rrc.h" + + +void basic_test() { + srslte::log_filter log1("RRC"); + log1.set_level(srslte::LOG_LEVEL_DEBUG); + log1.set_hex_limit(128); + + LIBLTE_BIT_MSG_STRUCT bit_buf; + LIBLTE_BIT_MSG_STRUCT bit_buf2; + LIBLTE_BYTE_MSG_STRUCT byte_buf; + LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg; + + uint32_t rrc_message_len = 18; + uint8_t rrc_message[] = {0x08, 0x10, 0x49, 0x3C, 0x0D, 0x97, 0x89, 0x83, + 0xC0, 0x84, 0x20, 0x82, 0x08, 0x21, 0x00, 0x01, + 0xBC, 0x48}; + + srslte_bit_unpack_vector(rrc_message, bit_buf.msg, rrc_message_len*8); + bit_buf.N_bits = rrc_message_len*8; + liblte_rrc_unpack_ul_dcch_msg((LIBLTE_BIT_MSG_STRUCT*)&bit_buf, &ul_dcch_msg); + + assert(ul_dcch_msg.msg_type == LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT); + LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *rep = &ul_dcch_msg.msg.measurement_report; + assert(rep->meas_id == 1); + assert(rep->pcell_rsrp_result == 73); + assert(rep->pcell_rsrq_result == 15); + assert(rep->have_meas_result_neigh_cells); + assert(rep->meas_result_neigh_cells_choice == LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA); + LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA_STRUCT *eutra = &rep->meas_result_neigh_cells.eutra; + assert(eutra->n_result == 1); + assert(eutra->result_eutra_list[0].phys_cell_id == 357); + assert(eutra->result_eutra_list[0].have_cgi_info); + assert(eutra->result_eutra_list[0].cgi_info.have_plmn_identity_list); + assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.plmn_id.mcc == 0xF898); + assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.plmn_id.mnc == 0xFF78); + assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.cell_id == 0x1084104); + assert(eutra->result_eutra_list[0].cgi_info.tracking_area_code == 0x1042); + assert(eutra->result_eutra_list[0].cgi_info.have_plmn_identity_list); + assert(eutra->result_eutra_list[0].cgi_info.n_plmn_identity_list == 1); + assert(eutra->result_eutra_list[0].cgi_info.plmn_identity_list[0].mcc == 0xFFFF); + assert(eutra->result_eutra_list[0].cgi_info.plmn_identity_list[0].mnc == 0xFF00); + assert(eutra->result_eutra_list[0].meas_result.have_rsrp); + assert(eutra->result_eutra_list[0].meas_result.rsrp_result == 60); + assert(eutra->result_eutra_list[0].meas_result.have_rsrp); + assert(eutra->result_eutra_list[0].meas_result.rsrq_result == 18); + + liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT*)&bit_buf2); + srslte_bit_pack_vector(bit_buf2.msg, byte_buf.msg, bit_buf2.N_bits); + byte_buf.N_bytes = (bit_buf2.N_bits+7)/8; + log1.info_hex(byte_buf.msg, byte_buf.N_bytes, "UL_DCCH Packed message\n"); + + for(uint32_t i=0; icell_id = args->enb.s1ap.enb_id; + sib1->cell_id = (args->enb.s1ap.enb_id << 8) + args->enb.s1ap.cell_id; sib1->tracking_area_code = args->enb.s1ap.tac; sib1->freq_band_indicator = srslte_band_get_band(args->rf.dl_earfcn); sib1->N_plmn_ids = 1; diff --git a/srsenb/src/mac/scheduler.cc b/srsenb/src/mac/scheduler.cc index a7e3d12d6..81ed0882e 100644 --- a/srsenb/src/mac/scheduler.cc +++ b/srsenb/src/mac/scheduler.cc @@ -597,12 +597,13 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST]) uint16_t rnti = (uint16_t) iter->first; dl_harq_proc *h = dl_metric->get_user_allocation(user); - + + uint32_t aggr_level = user->get_aggr_level(srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1, cfg.cell.nof_prb, cfg.cell.nof_ports)); if (h) { // Try to schedule DCI first if (generate_dci(&data[nof_data_elems].dci_location, - user->get_locations(current_cfi, sf_idx), - user->get_aggr_level(srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1, cfg.cell.nof_prb, cfg.cell.nof_ports)), user)) + user->get_locations(current_cfi, sf_idx), + aggr_level, user)) { bool is_newtx = h->is_empty(); int tbs = user->generate_format1(h, &data[nof_data_elems], current_tti, current_cfi); @@ -620,7 +621,8 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST]) } } else { h->reset(); - Warning("SCHED: Could not schedule DL DCI for rnti=0x%x, pid=%d\n", rnti, h->get_id()); + Warning("SCHED: Could not schedule DL DCI for rnti=0x%x, pid=%d, L=%d, nof_candidates=%d\n", + rnti, h->get_id(), aggr_level, user->get_locations(current_cfi, sf_idx)->nof_loc[aggr_level] ); } } } diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 52b617fd5..103017fcc 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -93,12 +93,13 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_) fprintf(stderr, "Error allocating memory\n"); return; } - signal_buffer_tx = (cf_t*) srslte_vec_malloc(2*SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t)); - if (!signal_buffer_tx) { + bzero(&signal_buffer_tx, sizeof(cf_t *) * SRSLTE_MAX_PORTS); + signal_buffer_tx[0] = (cf_t*) srslte_vec_malloc(2*SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t)); + if (!signal_buffer_tx[0]) { fprintf(stderr, "Error allocating memory\n"); return; } - if (srslte_enb_dl_init(&enb_dl, phy->cell.nof_prb)) { + if (srslte_enb_dl_init(&enb_dl, signal_buffer_tx, phy->cell.nof_prb)) { fprintf(stderr, "Error initiating ENB DL\n"); return; } @@ -106,7 +107,7 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_) fprintf(stderr, "Error initiating ENB DL\n"); return; } - if (srslte_enb_ul_init(&enb_ul, phy->cell.nof_prb)) { + if (srslte_enb_ul_init(&enb_ul, signal_buffer_rx, phy->cell.nof_prb)) { fprintf(stderr, "Error initiating ENB UL\n"); return; } @@ -156,8 +157,10 @@ void phch_worker::stop() if (signal_buffer_rx) { free(signal_buffer_rx); } - if (signal_buffer_tx) { - free(signal_buffer_tx); + for (int i = 0; i < SRSLTE_MAX_PORTS; i++) { + if (signal_buffer_tx[i]) { + free(signal_buffer_tx[i]); + } } pthread_mutex_unlock(&mutex); pthread_mutex_destroy(&mutex); @@ -338,9 +341,9 @@ void phch_worker::work_imp() } // Generate signal and transmit - srslte_enb_dl_gen_signal(&enb_dl, signal_buffer_tx); + srslte_enb_dl_gen_signal(&enb_dl); Debug("Sending to radio\n"); - phy->worker_end(tx_mutex_cnt, signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time); + phy->worker_end(tx_mutex_cnt, signal_buffer_tx[0], SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time); #ifdef DEBUG_WRITE_FILE fwrite(signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t), 1, f); @@ -408,7 +411,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) srslte_ra_ul_grant_t phy_grant; int res = -1; - if (!srslte_ra_ul_dci_to_grant(&grants[i].grant, enb_ul.cell.nof_prb, n_rb_ho, &phy_grant, tti_rx%8)) { + if (!srslte_ra_ul_dci_to_grant(&grants[i].grant, enb_ul.cell.nof_prb, n_rb_ho, &phy_grant)) { if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) { phy_grant.mcs.mod = SRSLTE_MOD_16QAM; } diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 35abda80a..e176e8ac5 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -768,9 +768,9 @@ bool rrc::ue::is_timeout() } if (deadline_str) { - uint64_t deadline = deadline_s*1e6 + deadline_us; - uint64_t elapsed = t[0].tv_sec*1e6 + t[0].tv_usec; - if (elapsed > deadline) { + int64_t deadline = deadline_s*1e6 + deadline_us; + int64_t elapsed = t[0].tv_sec*1e6 + t[0].tv_usec; + if (elapsed > deadline && elapsed > 0) { parent->rrc_log->warning("User rnti=0x%x expired %s deadline: %d:%d>%d:%d us\n", rnti, deadline_str, t[0].tv_sec, t[0].tv_usec, diff --git a/srsue/hdr/mac/demux.h b/srsue/hdr/mac/demux.h index 8b722e8c9..fb38990ec 100644 --- a/srsue/hdr/mac/demux.h +++ b/srsue/hdr/mac/demux.h @@ -41,14 +41,16 @@ namespace srsue { class demux : public srslte::pdu_queue::process_callback { public: - demux(uint8_t nof_harq_proc_); + demux(); void init(phy_interface_mac_common* phy_h_, rlc_interface_mac *rlc, srslte::log* log_h_, srslte::timers::timer* time_alignment_timer); bool process_pdus(); - uint8_t* request_buffer(uint32_t pid, uint32_t len); + uint8_t* request_buffer(uint32_t len); + uint8_t* request_buffer_bcch(uint32_t len); void deallocate(uint8_t* payload_buffer_ptr); - void push_pdu(uint32_t pid, uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp); + void push_pdu(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp); + void push_pdu_bcch(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp); void push_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes); void set_uecrid_callback(bool (*callback)(void*, uint64_t), void *arg); @@ -59,7 +61,8 @@ public: private: const static int MAX_PDU_LEN = 150*1024/8; // ~ 150 Mbps const static int NOF_BUFFER_PDUS = 64; // Number of PDU buffers per HARQ pid - uint8_t bcch_buffer[1024]; // BCCH PID has a dedicated buffer + const static int MAX_BCCH_PDU_LEN = 1024; + uint8_t bcch_buffer[MAX_BCCH_PDU_LEN]; // BCCH PID has a dedicated buffer bool (*uecrid_callback) (void*, uint64_t); void *uecrid_callback_arg; @@ -76,8 +79,7 @@ private: srslte::log *log_h; srslte::timers::timer *time_alignment_timer; rlc_interface_mac *rlc; - uint8_t nof_harq_proc; - + // Buffer of PDUs srslte::pdu_queue pdus; }; diff --git a/srsue/hdr/mac/dl_harq.h b/srsue/hdr/mac/dl_harq.h index ee925596f..521018d73 100644 --- a/srsue/hdr/mac/dl_harq.h +++ b/srsue/hdr/mac/dl_harq.h @@ -259,13 +259,16 @@ private: memcpy(&cur_grant, &grant, sizeof(Tgrant)); // If data has not yet been successfully decoded - if (!ack) { + if (!ack || (grant.rv[tid]==0 && grant.phy_grant.dl.mcs[tid].idx < 29)) { // Instruct the PHY To combine the received data and attempt to decode it - payload_buffer_ptr = harq_entity->demux_unit->request_buffer(pid * SRSLTE_MAX_TB + tid, - cur_grant.n_bytes[tid]); + if (pid == HARQ_BCCH_PID) { + payload_buffer_ptr = harq_entity->demux_unit->request_buffer_bcch(cur_grant.n_bytes[tid]); + } else { + payload_buffer_ptr = harq_entity->demux_unit->request_buffer(cur_grant.n_bytes[tid]); + } action->payload_ptr[tid] = payload_buffer_ptr; - if (!action->payload_ptr) { + if (!action->payload_ptr[tid]) { action->decode_enabled[tid] = false; Error("Can't get a buffer for TBS=%d\n", cur_grant.n_bytes[tid]); return; @@ -305,8 +308,7 @@ private: harq_entity->pcap->write_dl_sirnti(payload_buffer_ptr, cur_grant.n_bytes[tid], ack, cur_grant.tti); } Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (BCCH)\n", cur_grant.n_bytes[tid]); - harq_entity->demux_unit->push_pdu(pid * SRSLTE_MAX_TB + tid, payload_buffer_ptr, cur_grant.n_bytes[tid], - cur_grant.tti); + harq_entity->demux_unit->push_pdu_bcch(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.tti); } else { if (harq_entity->pcap) { harq_entity->pcap->write_dl_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.rnti, ack, @@ -318,8 +320,7 @@ private: harq_entity->demux_unit->push_pdu_temp_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid]); } else { Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit\n", cur_grant.n_bytes[tid]); - harq_entity->demux_unit->push_pdu(pid * SRSLTE_MAX_TB + tid, payload_buffer_ptr, cur_grant.n_bytes[tid], - cur_grant.tti); + harq_entity->demux_unit->push_pdu(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.tti); // Compute average number of retransmissions per packet harq_entity->average_retx = SRSLTE_VEC_CMA((float) n_retx, harq_entity->average_retx, @@ -346,9 +347,10 @@ private: // Determine if it's a new transmission 5.3.2.2 bool calc_is_new_transmission(Tgrant grant) { - if ((grant.ndi[tid] != cur_grant.ndi[tid]) || // 1st condition (NDI has changed) - (pid == HARQ_BCCH_PID && grant.rv[tid] == 0) || // 2nd condition (Broadcast and 1st transmission) - is_first_tb) // 3rd condition (first TB) + if (grant.phy_grant.dl.mcs[tid].idx <= 28 && // mcs 29,30,31 always retx regardless of rest + ((grant.ndi[tid] != cur_grant.ndi[tid]) || // 1st condition (NDI has changed) + (pid == HARQ_BCCH_PID && grant.rv[tid] == 0) || // 2nd condition (Broadcast and 1st transmission) + is_first_tb)) { is_first_tb = false; is_new_transmission = true; diff --git a/srsue/hdr/metrics_csv.h b/srsue/hdr/metrics_csv.h index a897265d2..f0b3e48c4 100644 --- a/srsue/hdr/metrics_csv.h +++ b/srsue/hdr/metrics_csv.h @@ -48,12 +48,14 @@ class metrics_csv : public srslte::metrics_listener public: metrics_csv(std::string filename); - void set_metrics(ue_metrics_t &m, float report_period_secs); + void set_periodicity(float metrics_report_period_sec); + void set_metrics(ue_metrics_t &m); void set_ue_handle(ue_metrics_interface *ue_); private: std::string float_to_string(float f, int digits, bool add_semicolon = true); + float metrics_report_period; std::ofstream file; ue_metrics_interface* ue; uint32_t n_reports; diff --git a/srsue/hdr/metrics_stdout.h b/srsue/hdr/metrics_stdout.h index 8ae33b24e..87a67cb2e 100644 --- a/srsue/hdr/metrics_stdout.h +++ b/srsue/hdr/metrics_stdout.h @@ -46,8 +46,9 @@ class metrics_stdout : public srslte::metrics_listener public: metrics_stdout(); + void set_periodicity(float metrics_report_period_sec); void toggle_print(bool b); - void set_metrics(ue_metrics_t &m, float report_period_secs); + void set_metrics(ue_metrics_t &m); void set_ue_handle(ue_metrics_interface *ue_); private: @@ -55,6 +56,7 @@ private: std::string float_to_eng_string(float f, int digits); std::string int_to_eng_string(int f, int digits); + float metrics_report_period; bool do_print; uint8_t n_reports; ue_metrics_interface* ue; diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index 0811723e0..c26966c17 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -149,7 +149,12 @@ private: uint32_t I_sr; float cfo; bool rar_cqi_request; - + + // Save last TBS for mcs>28 cases + int last_dl_tbs[2*HARQ_DELAY_MS][SRSLTE_MAX_CODEWORDS]; + int last_ul_tbs[2*HARQ_DELAY_MS]; + srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS]; + // Metrics dl_metrics_t dl_metrics; ul_metrics_t ul_metrics; diff --git a/srsue/hdr/ue_base.h b/srsue/hdr/ue_base.h index 411896f70..b547945a9 100644 --- a/srsue/hdr/ue_base.h +++ b/srsue/hdr/ue_base.h @@ -103,6 +103,7 @@ typedef struct { }gui_args_t; typedef struct { + std::string ip_netmask; phy_args_t phy; float metrics_period_secs; bool pregenerate_signals; diff --git a/srsue/hdr/upper/gw.h b/srsue/hdr/upper/gw.h index 800b31624..b97ceb6c5 100644 --- a/srsue/hdr/upper/gw.h +++ b/srsue/hdr/upper/gw.h @@ -57,8 +57,13 @@ public: // NAS interface srslte::error_t setup_if_addr(uint32_t ip_addr, char *err_str); + void set_netmask(std::string netmask); + private: + bool default_netmask; + std::string netmask; + static const int GW_THREAD_PRIO = 7; pdcp_interface_gw *pdcp; diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 3643f76c3..3e2fb70dd 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -98,6 +98,8 @@ private: uint8_t transaction_id; bool drb_up; + bool reestablishment_in_progress; + // timeouts in ms uint32_t connecting_timeout; @@ -244,7 +246,8 @@ private: // Helpers void rrc_connection_release(); - void radio_link_failure(); + void con_restablish_cell_reselected(); + void radio_link_failure(); static void* start_sib_thread(void *rrc_); void sib_search(); void apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2); diff --git a/srsue/src/mac/demux.cc b/srsue/src/mac/demux.cc index 75bafd1b4..171e7bf45 100644 --- a/srsue/src/mac/demux.cc +++ b/srsue/src/mac/demux.cc @@ -36,7 +36,7 @@ namespace srsue { -demux::demux(uint8_t nof_harq_proc_) : mac_msg(20), pending_mac_msg(20), nof_harq_proc(nof_harq_proc_) +demux::demux() : mac_msg(20), pending_mac_msg(20), rlc(NULL) { } @@ -64,18 +64,18 @@ void demux::deallocate(uint8_t* payload_buffer_ptr) pdus.deallocate(payload_buffer_ptr); } } - -uint8_t* demux::request_buffer(uint32_t pid, uint32_t len) -{ - uint8_t *buff = NULL; - if (pid < nof_harq_proc) { - return pdus.request(len); - } else if (pid == nof_harq_proc) { - buff = bcch_buffer; +uint8_t* demux::request_buffer_bcch(uint32_t len) +{ + if (len < MAX_BCCH_PDU_LEN) { + return bcch_buffer; } else { - Error("Requested buffer for invalid PID=%d\n", pid); + return NULL; } - return buff; +} + +uint8_t* demux::request_buffer(uint32_t len) +{ + return pdus.request(len); } /* Demultiplexing of MAC PDU associated with a Temporal C-RNTI. The PDU will @@ -117,21 +117,17 @@ void demux::push_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes) * This function enqueues the packet and returns quicly because ACK * deadline is important here. */ -void demux::push_pdu(uint32_t pid, uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) -{ - if (pid < nof_harq_proc) { - return pdus.push(buff, nof_bytes, tstamp); - } else if (pid == nof_harq_proc) { - /* Demultiplexing of MAC PDU associated with SI-RNTI. The PDU passes through - * the MAC in transparent mode. - * Warning: In this case function sends the message to RLC now, since SI blocks do not - * require ACK feedback to be transmitted quickly. - */ - Debug("Pushed BCCH MAC PDU in transparent mode\n"); - rlc->write_pdu_bcch_dlsch(buff, nof_bytes); - } else { - Error("Pushed buffer for invalid PID=%d\n", pid); - } +void demux::push_pdu(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) { + return pdus.push(buff, nof_bytes, tstamp); +} + +/* Demultiplexing of MAC PDU associated with SI-RNTI. The PDU passes through +* the MAC in transparent mode. +* Warning: In this case function sends the message to RLC now, since SI blocks do not +* require ACK feedback to be transmitted quickly. +*/ +void demux::push_pdu_bcch(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) { + rlc->write_pdu_bcch_dlsch(buff, nof_bytes); } bool demux::process_pdus() diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index 04b7c4750..f8d10bb34 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -44,7 +44,6 @@ namespace srsue { mac::mac() : ttisync(10240), timers(64), mux_unit(MAC_NOF_HARQ_PROC), - demux_unit(SRSLTE_MAX_TB*MAC_NOF_HARQ_PROC), pdu_process_thread(&demux_unit) { started = false; @@ -118,7 +117,8 @@ void mac::reset() Info("Resetting MAC\n"); - timers.stop_all(); + timers.get(timer_alignment)->stop(); + timers.get(contention_resolution_timer)->stop(); ul_harq.reset_ndi(); diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 0b67cecc1..92745edb8 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -122,6 +122,10 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { /* Expert section */ + ("expert.ip_netmask", + bpo::value(&args->expert.ip_netmask)->default_value("255.255.255.0"), + "Netmask of the tun_srsue device") + ("expert.phy.worker_cpu_mask", bpo::value(&args->expert.phy.worker_cpu_mask)->default_value(-1), "cpu bit mask (eg 255 = 1111 1111)") @@ -198,6 +202,11 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { bpo::value(&args->expert.phy.cfo_correct_tol_hz)->default_value(50.0), "Tolerance (in Hz) for digial CFO compensation.") + ("expert.cfo_ema", + bpo::value(&args->expert.phy.cfo_ema)->default_value(0.4), + "CFO Exponential Moving Average coefficient. Lower makes it more robust to noise " + "but vulnerable to periodic interruptions due to VCO corrections.") + ("expert.time_correct_period", bpo::value(&args->expert.phy.time_correct_period)->default_value(5), "Period for sampling time offset correction.") @@ -377,11 +386,13 @@ int main(int argc, char *argv[]) metricshub.init(ue, args.expert.metrics_period_secs); metricshub.add_listener(&metrics_screen); metrics_screen.set_ue_handle(ue); + metrics_screen.set_periodicity(args.expert.metrics_period_secs); metrics_csv metrics_file(args.expert.metrics_csv_filename); if (args.expert.metrics_csv_enable) { metricshub.add_listener(&metrics_file); metrics_file.set_ue_handle(ue); + metrics_file.set_periodicity(args.expert.metrics_period_secs); } pthread_t input; diff --git a/srsue/src/metrics_csv.cc b/srsue/src/metrics_csv.cc index f9bdce213..7c84659b5 100644 --- a/srsue/src/metrics_csv.cc +++ b/srsue/src/metrics_csv.cc @@ -43,6 +43,7 @@ namespace srsue{ metrics_csv::metrics_csv(std::string filename) :n_reports(0) + ,metrics_report_period(1.0) ,ue(NULL) { file.open(filename.c_str()); @@ -53,7 +54,11 @@ void metrics_csv::set_ue_handle(ue_metrics_interface *ue_) ue = ue_; } -void metrics_csv::set_metrics(ue_metrics_t &metrics, float metrics_report_period) +void metrics_csv::set_periodicity(float metrics_report_period_sec) { + this->metrics_report_period = metrics_report_period_sec; +} + +void metrics_csv::set_metrics(ue_metrics_t &metrics) { if (file.is_open() && ue != NULL) { if(n_reports == 0) { @@ -75,7 +80,7 @@ void metrics_csv::set_metrics(ue_metrics_t &metrics, float metrics_report_period file << float_to_string(metrics.phy.ul.mcs, 2); file << float_to_string((float) metrics.mac.ul_buffer, 2); file << float_to_string((float) metrics.mac.tx_brate/metrics_report_period, 2); - if (metrics.mac.tx_pkts > 0) { + if (metrics.mac.tx_pkts > 0) { file << float_to_string((float) 100*metrics.mac.tx_errors/metrics.mac.tx_pkts, 1); } else { file << float_to_string(0, 2); diff --git a/srsue/src/metrics_stdout.cc b/srsue/src/metrics_stdout.cc index 048532c8f..9f413b65f 100644 --- a/srsue/src/metrics_stdout.cc +++ b/srsue/src/metrics_stdout.cc @@ -50,6 +50,7 @@ char const * const prefixes[2][9] = metrics_stdout::metrics_stdout() :do_print(false) ,n_reports(10) + ,metrics_report_period(1.0) ,ue(NULL) { } @@ -64,8 +65,11 @@ void metrics_stdout::toggle_print(bool b) do_print = b; } +void metrics_stdout::set_periodicity(float metrics_report_period_sec) { + this->metrics_report_period = metrics_report_period_sec; +} -void metrics_stdout::set_metrics(ue_metrics_t &metrics, float metrics_report_period) +void metrics_stdout::set_metrics(ue_metrics_t &metrics) { if(!do_print || ue == NULL) return; diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index 7d2948c1a..d956ddd15 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -336,6 +336,7 @@ void phch_common::reset_ul() pthread_mutex_trylock(&tx_mutex[i]); pthread_mutex_unlock(&tx_mutex[i]); } + radio_h->tx_end(); } } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index f89696015..cf0eab94c 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -65,8 +65,7 @@ phch_worker::phch_worker() : tr_exec(10240) cell_initiated = false; pregen_enabled = false; trace_enabled = false; - - reset(); + reset(); } @@ -97,7 +96,7 @@ void phch_worker::reset() bzero(&period_cqi, sizeof(srslte_cqi_periodic_cfg_t)); I_sr = 0; rnti_is_set = false; - rar_cqi_request = false; + rar_cqi_request = false; cfi = 0; } @@ -118,12 +117,12 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h) } } - if (srslte_ue_dl_init(&ue_dl, max_prb, phy->args->nof_rx_ant)) { + if (srslte_ue_dl_init(&ue_dl, signal_buffer, max_prb, phy->args->nof_rx_ant)) { Error("Initiating UE DL\n"); return false; } - if (srslte_ue_ul_init(&ue_ul, max_prb)) { + if (srslte_ue_ul_init(&ue_ul, signal_buffer[0], max_prb)) { Error("Initiating UE UL\n"); return false; } @@ -479,10 +478,20 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant) return false; } + grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:(tti%(2*HARQ_DELAY_MS)); + + // Set last TBS for this TB (pid) in case of mcs>29 (7.1.7.2 of 36.213) + for (int i=0;iphy_grant.dl.mcs[i].tbs < 0) { + grant->phy_grant.dl.mcs[i].tbs = last_dl_tbs[grant->pid%(2*HARQ_DELAY_MS)][i]; + } + // save it + last_dl_tbs[grant->pid%(2*HARQ_DELAY_MS)][i] = grant->phy_grant.dl.mcs[i].tbs; + } + /* Fill MAC grant structure */ grant->ndi[0] = dci_unpacked.ndi; grant->ndi[1] = dci_unpacked.ndi_1; - grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:(tti%(2*HARQ_DELAY_MS)); grant->n_bytes[0] = grant->phy_grant.dl.mcs[0].tbs / (uint32_t) 8; grant->n_bytes[1] = grant->phy_grant.dl.mcs[1].tbs / (uint32_t) 8; grant->tti = tti; @@ -495,11 +504,6 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant) grant->tb_en[1] = dci_unpacked.tb_en[1]; grant->tb_cw_swap = dci_unpacked.tb_cw_swap; // FIXME: tb_cw_swap not supported - if (grant->tb_cw_swap) { - Info("tb_cw_swap = true\n"); - printf("tb_cw_swap = true\n"); - } - last_dl_pdcch_ncce = srslte_ue_dl_get_ncce(&ue_dl); char hexstr[16]; @@ -624,7 +628,7 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL for (int i=0;itb_en[i]) { - snprintf(tbstr[i], 128, ", TB%d: tbs=%d, mcs=%d, rv=%d, crc=%s, it=%d", + snprintf(tbstr[i], 128, ", CW%d: tbs=%d, mcs=%d, rv=%d, crc=%s, it=%d", i, grant->mcs[i].tbs/8, grant->mcs[i].idx, rv[i], acks[i] ? "OK" : "KO", srslte_pdsch_last_noi_cw(&ue_dl.pdsch, i)); } @@ -719,14 +723,29 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant) ue_dl.last_location_ul.ncce, (1<phy_grant.ul.mcs.tbs==0) { - srslte_vec_fprint_hex(stdout, dci_msg.data, dci_msg.nof_bits); + Info("Received PUSCH grant with empty data\n"); } } } - + + if (ret) { + + // Use last TBS for this TB in case of mcs>28 + if (grant->phy_grant.ul.mcs.tbs < 0) { + grant->phy_grant.ul.mcs.tbs = last_ul_tbs[tti%(2*HARQ_DELAY_MS)]; + } + last_ul_tbs[tti%(2*HARQ_DELAY_MS)] = grant->phy_grant.ul.mcs.tbs; + + if (grant->phy_grant.ul.mcs.mod == SRSLTE_MOD_LAST) { + grant->phy_grant.ul.mcs.mod = last_ul_mod[tti%(2*HARQ_DELAY_MS)]; + grant->phy_grant.ul.Qm = srslte_mod_bits_x_symbol(grant->phy_grant.ul.mcs.mod); + } + last_ul_mod[tti%(2*HARQ_DELAY_MS)] = grant->phy_grant.ul.mcs.mod; + } + /* Limit UL modulation if not supported by the UE or disabled by higher layers */ if (!phy->config->enable_64qam) { - if (grant->phy_grant.ul.mcs.mod == SRSLTE_MOD_64QAM) { + if (grant->phy_grant.ul.mcs.mod >= SRSLTE_MOD_64QAM) { grant->phy_grant.ul.mcs.mod = SRSLTE_MOD_16QAM; grant->phy_grant.ul.Qm = 4; } @@ -899,7 +918,7 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui if (srslte_ue_ul_cfg_grant(&ue_ul, grant, TTI_TX(tti), rv, current_tx_nb)) { Error("Configuring UL grant\n"); } - + if (srslte_ue_ul_pusch_encode_rnti_softbuffer(&ue_ul, payload, uci_data, softbuffer, @@ -926,12 +945,12 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui #endif Info("PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d, ack=%s, ri=%s, cfo=%.1f KHz%s\n", - (tti+4)%10240, - grant->n_prb[0], grant->n_prb[0]+grant->L_prb, - grant->mcs.tbs/8, grant->mcs.idx, rv, - uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", - uci_data.uci_ri_len>0?(uci_data.uci_ri?"1":"0"):"no", - cfo*15, timestr); + (tti+HARQ_DELAY_MS)%10240, + grant->n_prb[0], grant->n_prb[0]+grant->L_prb, + grant->mcs.tbs/8, grant->mcs.idx, rv, + uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", + uci_data.uci_ri_len>0?(uci_data.uci_ri?"1":"0"):"no", + cfo*15, timestr); // Store metrics ul_metrics.mcs = grant->mcs.idx; diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 0e4bcdc5f..2c140c191 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -200,8 +200,8 @@ void phy::set_timeadv_rar(uint32_t ta_cmd) { void phy::set_timeadv(uint32_t ta_cmd) { n_ta = srslte_N_ta_new(n_ta, ta_cmd); - //sf_recv.set_time_adv_sec(((float) n_ta)*SRSLTE_LTE_TS); - Warning("Not supported: Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, ((float) n_ta)*SRSLTE_LTE_TS*1e6); + sf_recv.set_time_adv_sec(((float) n_ta)*SRSLTE_LTE_TS); + //Warning("Not supported: Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, ((float) n_ta)*SRSLTE_LTE_TS*1e6); } void phy::configure_prach_params() @@ -313,7 +313,8 @@ void phy::reset() pdcch_dl_search_reset(); for(uint32_t i=0;iexpert.ip_netmask); + rrc.init(&phy, &mac, &rlc, &pdcp, &nas, &usim, &mac, &rrc_log); rrc.set_ue_category(atoi(args->expert.ue_cateogry.c_str())); diff --git a/srsue/src/upper/gw.cc b/srsue/src/upper/gw.cc index 07ac36989..1e3e81999 100644 --- a/srsue/src/upper/gw.cc +++ b/srsue/src/upper/gw.cc @@ -44,6 +44,7 @@ gw::gw() :if_up(false) { current_ip_addr = 0; + default_netmask = true; } void gw::init(pdcp_interface_gw *pdcp_, nas_interface_gw *nas_, srslte::log *gw_log_, uint32_t lcid_) @@ -104,6 +105,12 @@ void gw::get_metrics(gw_metrics_t &m) ul_tput_bytes = 0; } +void gw::set_netmask(std::string netmask) { + default_netmask = false; + this->netmask = netmask; +} + + /******************************************************************************* PDCP interface *******************************************************************************/ @@ -152,7 +159,11 @@ srslte::error_t gw::setup_if_addr(uint32_t ip_addr, char *err_str) return(srslte::ERROR_CANT_START); } ifr.ifr_netmask.sa_family = AF_INET; - ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0"); + const char *mask = "255.255.255.0"; + if (!default_netmask) { + mask = netmask.c_str(); + } + ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr(mask); if(0 > ioctl(sock, SIOCSIFNETMASK, &ifr)) { err_str = strerror(errno); diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index f0fd8cf54..110c8c78e 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -281,7 +281,6 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT act_def_eps_bearer_context_accept; nas_log->info("Received Attach Accept\n"); - count_dl++; liblte_mme_unpack_attach_accept_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &attach_accept); @@ -359,6 +358,8 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { state = EMM_STATE_REGISTERED; current_plmn = selecting_plmn; + count_dl++; + // Send EPS bearer context accept and attach complete count_ul++; act_def_eps_bearer_context_accept.eps_bearer_id = eps_bearer_id; @@ -437,6 +438,9 @@ void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu) { nas_log->console("Warning: Network authentication failure\n"); pool->deallocate(pdu); } + + // Reset DL counter (as per 24.301 5.4.3.2) + count_dl = 0; } void nas::parse_authentication_reject(uint32_t lcid, byte_buffer_t *pdu) { @@ -539,6 +543,8 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) { } } + count_dl++; + if (!success) { // Reuse pdu for response pdu->reset(); diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 94c2e449a..10373dcf2 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -35,8 +35,6 @@ #include "srslte/common/security.h" #include "srslte/common/bcd_helpers.h" -#define TIMEOUT_RESYNC_REESTABLISH 100 - using namespace srslte; namespace srsue { @@ -92,6 +90,8 @@ void rrc::init(phy_interface_rrc *phy_, pthread_mutex_init(&mutex, NULL); + reestablishment_in_progress = false; + ue_category = SRSLTE_UE_CATEGORY; t301 = mac_timers->timer_get_unique_id(); t310 = mac_timers->timer_get_unique_id(); @@ -207,7 +207,11 @@ void rrc::run_thread() { break; case RRC_STATE_CELL_SELECTED: rrc_log->info("RRC Cell Selected: Sending connection request...\n"); - send_con_request(); + if (reestablishment_in_progress) { + con_restablish_cell_reselected(); + } else { + send_con_request(); + } state = RRC_STATE_CONNECTING; connecting_timeout = 0; break; @@ -226,6 +230,7 @@ void rrc::run_thread() { usleep(60000); rrc_log->info("Leaving RRC_CONNECTED state\n"); drb_up = false; + reestablishment_in_progress = false; pdcp->reset(); rlc->reset(); phy->reset(); @@ -484,12 +489,12 @@ void rrc::earfcn_end() { // Detection of physical layer problems (5.3.11.1) void rrc::out_of_sync() { - current_cell->in_sync = false; + current_cell->in_sync = false; if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) { n310_cnt++; if (n310_cnt == N310) { // attempt resync - phy->sync_reset(); + //phy->sync_reset(); mac_timers->timer_get(t310)->reset(); mac_timers->timer_get(t310)->run(); @@ -663,6 +668,8 @@ void rrc::send_con_restablish_request() { ul_ccch_msg.msg.rrc_con_reest_req.cause = LIBLTE_RRC_CON_REEST_REQ_CAUSE_OTHER_FAILURE; liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); + reestablishment_in_progress = true; + rrc_log->info("Initiating RRC Connection Reestablishment Procedure\n"); rrc_log->console("RRC Connection Reestablishment\n"); mac_timers->timer_get(t310)->stop(); @@ -673,19 +680,16 @@ void rrc::send_con_restablish_request() { set_phy_default(); mac->reset(); set_mac_default(); +} - // FIXME: Cell selection should be different?? - - // Wait for cell re-synchronization - uint32_t timeout_cnt = 0; - while (!phy->sync_status() && timeout_cnt < TIMEOUT_RESYNC_REESTABLISH) { - usleep(10000); - timeout_cnt++; - } +// Actions following cell reselection 5.3.7.3 +void rrc::con_restablish_cell_reselected() +{ + reestablishment_in_progress = false; + rrc_log->info("Cell Selection finished. Initiating transmission of RRC Connection Reestablishment Request\n"); mac_timers->timer_get(t301)->reset(); mac_timers->timer_get(t301)->run(); mac_timers->timer_get(t311)->stop(); - rrc_log->info("Cell Selection finished. Initiating transmission of RRC Connection Reestablishment Request\n"); // Byte align and pack the message bits for PDCP if ((bit_buf.N_bits % 8) != 0) { diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 5d14d3c3c..5b3559ae9 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -98,7 +98,11 @@ enable = false ##################################################################### # Expert configuration options # -# ue_category: Sets UE category (range 1-5). Default: 4 +# ue_category: Sets UE category (range 1-5). Default: 4 +# ip_netmask: Netmask of the tun_srsue device. Default: 255.255.255.0 +# rssi_sensor_enabled: Enable or disable RF frontend RSSI sensor. Required for RSRP metrics but +# can cause UHD instability for long-duration testing. Default true. +# ue_category: Sets UE category (range 1-5). Default: 4 # # prach_gain: PRACH gain (dB). If defined, forces a gain for the tranmsission of PRACH only., # Default is to use tx_gain in [rf] section. @@ -115,7 +119,9 @@ enable = false # nof_phy_threads: Selects the number of PHY threads (maximum 4, minimum 1, default 2) # equalizer_mode: Selects equalizer mode. Valid modes are: "mmse", "zf" or any # non-negative real number to indicate a regularized zf coefficient. -# Default is MMSE. +# Default is MMSE. +# cfo_ema: CFO Exponential Moving Average coefficient. Lower makes it more robust to noise +# but vulnerable to periodic interruptions due to VCO corrections. # cfo_integer_enabled: Enables integer CFO estimation and correction. This needs improvement # and may lead to incorrect synchronization. Use with caution. # cfo_correct_tol_hz: Tolerance (in Hz) for digial CFO compensation. Lower tolerance means that @@ -138,6 +144,8 @@ enable = false # ##################################################################### [expert] +#ip_netmask = 255.255.255.0 +#rssi_sensor_enabled = false #ue_category = 4 #prach_gain = 30 #cqi_max = 15 @@ -148,6 +156,7 @@ enable = false #attach_enable_64qam = false #nof_phy_threads = 2 #equalizer_mode = mmse +#cfo_ema = 0.4 #cfo_integer_enabled = false #cfo_correct_tol_hz = 50 #time_correct_period = 5